From ad0313058d8b1d77544875211131024ce3de75a7 Mon Sep 17 00:00:00 2001 From: Wilson Ng Jing An <31720838+wilsonngja@users.noreply.github.com> Date: Fri, 30 Sep 2022 11:15:00 +0800 Subject: [PATCH 001/325] Update AboutUs.md --- docs/AboutUs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 0f072953e..09a43456b 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -2,7 +2,7 @@ Display | Name | Github Profile | Portfolio --------|:----:|:--------------:|:---------: -![](https://via.placeholder.com/100.png?text=Photo) | John Doe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Wilson Ng Jing An | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Don Joe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Ron John | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | John Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) From a2c69a4c0e434a6922ce918af51fcb005e181eba Mon Sep 17 00:00:00 2001 From: FeliciaBeatrice Date: Fri, 30 Sep 2022 11:43:14 +0800 Subject: [PATCH 002/325] Update AboutUs.md --- docs/AboutUs.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 09a43456b..92fe4616f 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -1,9 +1,9 @@ # About us -Display | Name | Github Profile | Portfolio ---------|:----:|:--------------:|:---------: -![](https://via.placeholder.com/100.png?text=Photo) | Wilson Ng Jing An | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Don Joe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Ron John | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | John Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Don Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +Display | Name | Github Profile | Portfolio +--------|:-------------------------:|:--------------------------------------------:|:---------: +![](https://via.placeholder.com/100.png?text=Photo) | Wilson Ng Jing An | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Don Joe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Ron John | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Felicia Beatrice Budiawan | [Github](https://github.com/FeliciaBeatrice) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Don Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) From 1827ec1c030703eb4aa0443bf6c283c6491c175e Mon Sep 17 00:00:00 2001 From: "LAPTOP-S1RS66RO\\marcu" Date: Fri, 30 Sep 2022 11:44:24 +0800 Subject: [PATCH 003/325] Add Name in AboutUs --- docs/AboutUs.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 09a43456b..faab32939 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -1,9 +1,9 @@ # About us -Display | Name | Github Profile | Portfolio ---------|:----:|:--------------:|:---------: +Display | Name | Github Profile | Portfolio +--------|:-----------------:|:--------------:|:---------: ![](https://via.placeholder.com/100.png?text=Photo) | Wilson Ng Jing An | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Don Joe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Ron John | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | John Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Don Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Ang Jia Le Marcus | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Ron John | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | John Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Don Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) From 9d914abc0c186c0a79f63602b18ca94ca8faab9b Mon Sep 17 00:00:00 2001 From: ngdeqi Date: Fri, 30 Sep 2022 11:45:01 +0800 Subject: [PATCH 004/325] Update AboutUs --- docs/AboutUs.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 09a43456b..4a5fa7ef9 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -1,9 +1,9 @@ # About us -Display | Name | Github Profile | Portfolio ---------|:----:|:--------------:|:---------: +Display | Name | Github Profile | Portfolio +--------|:-----------------:|:--------------:|:---------: ![](https://via.placeholder.com/100.png?text=Photo) | Wilson Ng Jing An | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Don Joe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Ron John | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | John Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Don Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Don Joe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Ng De Qi | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | John Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Don Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) From ee453adcd3bfaf664ca58f8e57a0c1b4e8d8968a Mon Sep 17 00:00:00 2001 From: ngdeqi Date: Fri, 30 Sep 2022 11:47:50 +0800 Subject: [PATCH 005/325] Update AboutUs with github link --- docs/AboutUs.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 4a5fa7ef9..d03462909 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -1,9 +1,9 @@ # About us -Display | Name | Github Profile | Portfolio ---------|:-----------------:|:--------------:|:---------: -![](https://via.placeholder.com/100.png?text=Photo) | Wilson Ng Jing An | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Don Joe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Ng De Qi | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | John Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Don Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +Display | Name | Github Profile | Portfolio +--------|:-----------------:|:-----------------------------------:|:---------: +![](https://via.placeholder.com/100.png?text=Photo) | Wilson Ng Jing An | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Don Joe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Ng De Qi | [Github](https://github.com/ngdeqi) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | John Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Don Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) From bb7b96387e4f831a7d0aa0bb21edf9c9518ec7dd Mon Sep 17 00:00:00 2001 From: "ZORAN\\syedo" Date: Fri, 30 Sep 2022 11:50:35 +0800 Subject: [PATCH 006/325] Update AboutUs --- docs/AboutUs.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 09a43456b..e110dec8f 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -1,9 +1,9 @@ # About us -Display | Name | Github Profile | Portfolio ---------|:----:|:--------------:|:---------: +Display | Name | Github Profile | Portfolio +--------|:-----------------:|:--------------:|:---------: ![](https://via.placeholder.com/100.png?text=Photo) | Wilson Ng Jing An | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Don Joe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Ron John | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | John Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Don Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Don Joe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Ron John | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | John Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Syed Omar Zoran | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) From 2d88ea05f34c4cdad017f6fb5d6a8e305e311bf4 Mon Sep 17 00:00:00 2001 From: "MSI\\User" Date: Fri, 7 Oct 2022 12:46:38 +0800 Subject: [PATCH 007/325] Add baseline for project to start. --- .../java/seedu/duke/Command/CommandAdd.java | 7 ++++++ src/main/java/seedu/duke/Duke.java | 25 +++++++++++-------- src/main/java/seedu/duke/Parser.java | 18 +++++++++++++ src/main/java/seedu/duke/Ui.java | 12 +++++++++ 4 files changed, 52 insertions(+), 10 deletions(-) create mode 100644 src/main/java/seedu/duke/Command/CommandAdd.java create mode 100644 src/main/java/seedu/duke/Parser.java create mode 100644 src/main/java/seedu/duke/Ui.java diff --git a/src/main/java/seedu/duke/Command/CommandAdd.java b/src/main/java/seedu/duke/Command/CommandAdd.java new file mode 100644 index 000000000..d1106017a --- /dev/null +++ b/src/main/java/seedu/duke/Command/CommandAdd.java @@ -0,0 +1,7 @@ +package seedu.duke.Command; + +public class CommandAdd { + public CommandAdd(String[] commands) { + + } +} diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 5c74e68d5..70090402d 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -2,20 +2,25 @@ import java.util.Scanner; + public class Duke { + private Parser parser; + private Ui ui; + + + public void run() { + this.parser = new Parser(); + String command; + + do { + command = Ui.readCommand(); + } while (!command.equals("bye")); + } + /** * Main entry-point for the java.duke.Duke application. */ public static void main(String[] args) { - String logo = " ____ _ \n" - + "| _ \\ _ _| | _____ \n" - + "| | | | | | | |/ / _ \\\n" - + "| |_| | |_| | < __/\n" - + "|____/ \\__,_|_|\\_\\___|\n"; - System.out.println("Hello from\n" + logo); - System.out.println("What is your name?"); - - Scanner in = new Scanner(System.in); - System.out.println("Hello " + in.nextLine()); + new Duke().run(); } } diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java new file mode 100644 index 000000000..29c2b1b42 --- /dev/null +++ b/src/main/java/seedu/duke/Parser.java @@ -0,0 +1,18 @@ +package seedu.duke; + +import seedu.duke.Command.CommandAdd; + +public class Parser { + public CommandAdd parseCommand(String input) { + final int LIMIT = 2; + String[] commands = input.trim().split(" ", LIMIT); + + // This is the type of command that will be executed + String commandType = commands[0]; + + switch (commandType) { + default: + return new CommandAdd(commands); + } + } +} diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java new file mode 100644 index 000000000..104ad71c2 --- /dev/null +++ b/src/main/java/seedu/duke/Ui.java @@ -0,0 +1,12 @@ +package seedu.duke; + +import java.util.Scanner; + +public class Ui { + + public static String readCommand() { + Scanner input = new Scanner(System.in); + + return input.nextLine(); + } +} From 8ec9db922c6af79be0226d65c3e8bd7f7da75184 Mon Sep 17 00:00:00 2001 From: "MSI\\User" Date: Fri, 7 Oct 2022 12:52:36 +0800 Subject: [PATCH 008/325] Fix coding standards error to fit CI --- src/main/java/seedu/duke/Parser.java | 6 ++++-- .../java/seedu/duke/{Command => command}/CommandAdd.java | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) rename src/main/java/seedu/duke/{Command => command}/CommandAdd.java (73%) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 29c2b1b42..5b94797be 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -1,10 +1,12 @@ package seedu.duke; -import seedu.duke.Command.CommandAdd; +import seedu.duke.command.CommandAdd; public class Parser { + final int LIMIT = 2; + public CommandAdd parseCommand(String input) { - final int LIMIT = 2; + String[] commands = input.trim().split(" ", LIMIT); // This is the type of command that will be executed diff --git a/src/main/java/seedu/duke/Command/CommandAdd.java b/src/main/java/seedu/duke/command/CommandAdd.java similarity index 73% rename from src/main/java/seedu/duke/Command/CommandAdd.java rename to src/main/java/seedu/duke/command/CommandAdd.java index d1106017a..a1362dde3 100644 --- a/src/main/java/seedu/duke/Command/CommandAdd.java +++ b/src/main/java/seedu/duke/command/CommandAdd.java @@ -1,4 +1,4 @@ -package seedu.duke.Command; +package seedu.duke.command; public class CommandAdd { public CommandAdd(String[] commands) { From ee7645d7184b2f3a4b8114903c7d6bee08115255 Mon Sep 17 00:00:00 2001 From: Ng De Qi <88148155+ngdeqi@users.noreply.github.com> Date: Fri, 7 Oct 2022 13:14:03 +0800 Subject: [PATCH 009/325] Revert "Add baseline for project to start." --- src/main/java/seedu/duke/Duke.java | 25 ++++++++----------- src/main/java/seedu/duke/Parser.java | 20 --------------- src/main/java/seedu/duke/Ui.java | 12 --------- .../java/seedu/duke/command/CommandAdd.java | 7 ------ 4 files changed, 10 insertions(+), 54 deletions(-) delete mode 100644 src/main/java/seedu/duke/Parser.java delete mode 100644 src/main/java/seedu/duke/Ui.java delete mode 100644 src/main/java/seedu/duke/command/CommandAdd.java diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 70090402d..5c74e68d5 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -2,25 +2,20 @@ import java.util.Scanner; - public class Duke { - private Parser parser; - private Ui ui; - - - public void run() { - this.parser = new Parser(); - String command; - - do { - command = Ui.readCommand(); - } while (!command.equals("bye")); - } - /** * Main entry-point for the java.duke.Duke application. */ public static void main(String[] args) { - new Duke().run(); + String logo = " ____ _ \n" + + "| _ \\ _ _| | _____ \n" + + "| | | | | | | |/ / _ \\\n" + + "| |_| | |_| | < __/\n" + + "|____/ \\__,_|_|\\_\\___|\n"; + System.out.println("Hello from\n" + logo); + System.out.println("What is your name?"); + + Scanner in = new Scanner(System.in); + System.out.println("Hello " + in.nextLine()); } } diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java deleted file mode 100644 index 5b94797be..000000000 --- a/src/main/java/seedu/duke/Parser.java +++ /dev/null @@ -1,20 +0,0 @@ -package seedu.duke; - -import seedu.duke.command.CommandAdd; - -public class Parser { - final int LIMIT = 2; - - public CommandAdd parseCommand(String input) { - - String[] commands = input.trim().split(" ", LIMIT); - - // This is the type of command that will be executed - String commandType = commands[0]; - - switch (commandType) { - default: - return new CommandAdd(commands); - } - } -} diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java deleted file mode 100644 index 104ad71c2..000000000 --- a/src/main/java/seedu/duke/Ui.java +++ /dev/null @@ -1,12 +0,0 @@ -package seedu.duke; - -import java.util.Scanner; - -public class Ui { - - public static String readCommand() { - Scanner input = new Scanner(System.in); - - return input.nextLine(); - } -} diff --git a/src/main/java/seedu/duke/command/CommandAdd.java b/src/main/java/seedu/duke/command/CommandAdd.java deleted file mode 100644 index a1362dde3..000000000 --- a/src/main/java/seedu/duke/command/CommandAdd.java +++ /dev/null @@ -1,7 +0,0 @@ -package seedu.duke.command; - -public class CommandAdd { - public CommandAdd(String[] commands) { - - } -} From 5085bc4175e2026bcef6583e03a5a1a69ce9a220 Mon Sep 17 00:00:00 2001 From: "MSI\\User" Date: Fri, 7 Oct 2022 14:13:32 +0800 Subject: [PATCH 010/325] Initialise starting point for team project. --- src/main/java/seedu/duke/Client.java | 4 ++++ src/main/java/seedu/duke/ClientList.java | 4 ++++ src/main/java/seedu/duke/Duke.java | 17 +++++++++++++++-- src/main/java/seedu/duke/Parser.java | 5 ++--- src/main/java/seedu/duke/Property.java | 4 ++++ src/main/java/seedu/duke/PropertyList.java | 4 ++++ src/main/java/seedu/duke/Storage.java | 4 ++++ src/main/java/seedu/duke/Ui.java | 12 +++++++++++- src/main/java/seedu/duke/command/Command.java | 7 +++++++ .../java/seedu/duke/command/CommandAdd.java | 12 +++++++++++- 10 files changed, 66 insertions(+), 7 deletions(-) create mode 100644 src/main/java/seedu/duke/Client.java create mode 100644 src/main/java/seedu/duke/ClientList.java create mode 100644 src/main/java/seedu/duke/Property.java create mode 100644 src/main/java/seedu/duke/PropertyList.java create mode 100644 src/main/java/seedu/duke/Storage.java create mode 100644 src/main/java/seedu/duke/command/Command.java diff --git a/src/main/java/seedu/duke/Client.java b/src/main/java/seedu/duke/Client.java new file mode 100644 index 000000000..65b18143f --- /dev/null +++ b/src/main/java/seedu/duke/Client.java @@ -0,0 +1,4 @@ +package seedu.duke; + +public class Client { +} diff --git a/src/main/java/seedu/duke/ClientList.java b/src/main/java/seedu/duke/ClientList.java new file mode 100644 index 000000000..3b11cf7eb --- /dev/null +++ b/src/main/java/seedu/duke/ClientList.java @@ -0,0 +1,4 @@ +package seedu.duke; + +public class ClientList { +} diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 70090402d..2f1f97a84 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -1,19 +1,32 @@ package seedu.duke; +import seedu.duke.command.Command; + import java.util.Scanner; public class Duke { private Parser parser; private Ui ui; + private Storage storage; + private PropertyList propertyList; + private ClientList clientList; public void run() { this.parser = new Parser(); - String command; + this.ui = new Ui(); + this.storage = new Storage(); + this.propertyList = new PropertyList(); + this.clientList = new ClientList(); + + Command command; do { - command = Ui.readCommand(); + String userInputText = ui.readCommand(); + command = parser.parseCommand(userInputText); + command.execute(ui, storage, propertyList, clientList); + } while (!command.equals("bye")); } diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 5b94797be..ea79cdd0b 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -3,11 +3,10 @@ import seedu.duke.command.CommandAdd; public class Parser { - final int LIMIT = 2; - + public CommandAdd parseCommand(String input) { - String[] commands = input.trim().split(" ", LIMIT); + String[] commands = input.trim().split(" ", 2); // This is the type of command that will be executed String commandType = commands[0]; diff --git a/src/main/java/seedu/duke/Property.java b/src/main/java/seedu/duke/Property.java new file mode 100644 index 000000000..09e562999 --- /dev/null +++ b/src/main/java/seedu/duke/Property.java @@ -0,0 +1,4 @@ +package seedu.duke; + +public class Property { +} diff --git a/src/main/java/seedu/duke/PropertyList.java b/src/main/java/seedu/duke/PropertyList.java new file mode 100644 index 000000000..35fad2686 --- /dev/null +++ b/src/main/java/seedu/duke/PropertyList.java @@ -0,0 +1,4 @@ +package seedu.duke; + +public class PropertyList { +} diff --git a/src/main/java/seedu/duke/Storage.java b/src/main/java/seedu/duke/Storage.java new file mode 100644 index 000000000..4844e3266 --- /dev/null +++ b/src/main/java/seedu/duke/Storage.java @@ -0,0 +1,4 @@ +package seedu.duke; + +public class Storage { +} diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index 104ad71c2..87deaca90 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -4,9 +4,19 @@ public class Ui { + private static boolean inputIsEmpty(String rawInput) { + return rawInput.trim().isEmpty(); + } public static String readCommand() { Scanner input = new Scanner(System.in); - return input.nextLine(); + String rawInput = input.nextLine(); + boolean isEmpty = inputIsEmpty(rawInput); + while (isEmpty) { + rawInput = input.nextLine(); + isEmpty = inputIsEmpty(rawInput); + } + + return rawInput; } } diff --git a/src/main/java/seedu/duke/command/Command.java b/src/main/java/seedu/duke/command/Command.java new file mode 100644 index 000000000..b56573ac7 --- /dev/null +++ b/src/main/java/seedu/duke/command/Command.java @@ -0,0 +1,7 @@ +package seedu.duke.command; + +import seedu.duke.*; + +abstract public class Command { + public abstract void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList); +} diff --git a/src/main/java/seedu/duke/command/CommandAdd.java b/src/main/java/seedu/duke/command/CommandAdd.java index a1362dde3..8b4298a7a 100644 --- a/src/main/java/seedu/duke/command/CommandAdd.java +++ b/src/main/java/seedu/duke/command/CommandAdd.java @@ -1,7 +1,17 @@ package seedu.duke.command; -public class CommandAdd { +import seedu.duke.ClientList; +import seedu.duke.PropertyList; +import seedu.duke.Storage; +import seedu.duke.Ui; + +public class CommandAdd extends Command { public CommandAdd(String[] commands) { } + + @Override + public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList) { + + } } From 1aff51b3d6c7362d9f17e7f0c0c94c61cc369d4d Mon Sep 17 00:00:00 2001 From: "MSI\\User" Date: Fri, 7 Oct 2022 14:28:23 +0800 Subject: [PATCH 011/325] Fix styling error in Ui and Command. --- src/main/java/seedu/duke/Ui.java | 1 + src/main/java/seedu/duke/command/Command.java | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index 87deaca90..d9b810829 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -7,6 +7,7 @@ public class Ui { private static boolean inputIsEmpty(String rawInput) { return rawInput.trim().isEmpty(); } + public static String readCommand() { Scanner input = new Scanner(System.in); diff --git a/src/main/java/seedu/duke/command/Command.java b/src/main/java/seedu/duke/command/Command.java index b56573ac7..cabb89394 100644 --- a/src/main/java/seedu/duke/command/Command.java +++ b/src/main/java/seedu/duke/command/Command.java @@ -1,7 +1,11 @@ package seedu.duke.command; -import seedu.duke.*; +import seedu.duke.Ui; +import seedu.duke.ClientList; +import seedu.duke.PropertyList; +import seedu.duke.Storage; -abstract public class Command { + +public abstract class Command { public abstract void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList); } From bbf39b3bb719f020fd80d82c526ea6c5c9128629 Mon Sep 17 00:00:00 2001 From: "MSI\\User" Date: Fri, 7 Oct 2022 14:42:24 +0800 Subject: [PATCH 012/325] Update EXPECTED.txt --- text-ui-test/EXPECTED.TXT | 9 --------- 1 file changed, 9 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 892cb6cae..e69de29bb 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,9 +0,0 @@ -Hello from - ____ _ -| _ \ _ _| | _____ -| | | | | | | |/ / _ \ -| |_| | |_| | < __/ -|____/ \__,_|_|\_\___| - -What is your name? -Hello James Gosling From 1dfa733d6e051b1f92fe3e06d8cdaee0f068a43e Mon Sep 17 00:00:00 2001 From: "MSI\\User" Date: Sat, 8 Oct 2022 01:27:01 +0800 Subject: [PATCH 013/325] Creates directory if not exists and append property, client and pairs to text files --- src/main/java/seedu/duke/ClientList.java | 4 + src/main/java/seedu/duke/Duke.java | 13 +- src/main/java/seedu/duke/PropertyList.java | 3 + src/main/java/seedu/duke/Storage.java | 184 ++++++++++++++++++ .../seedu/duke/CheckFileCreationTest.java | 23 +++ 5 files changed, 222 insertions(+), 5 deletions(-) create mode 100644 src/test/java/seedu/duke/CheckFileCreationTest.java diff --git a/src/main/java/seedu/duke/ClientList.java b/src/main/java/seedu/duke/ClientList.java index 3b11cf7eb..96051cc28 100644 --- a/src/main/java/seedu/duke/ClientList.java +++ b/src/main/java/seedu/duke/ClientList.java @@ -1,4 +1,8 @@ package seedu.duke; +import java.util.ArrayList; + public class ClientList { + protected static ArrayList clients = new ArrayList<>(); + } diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 2f1f97a84..54c5e75b3 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -2,7 +2,7 @@ import seedu.duke.command.Command; -import java.util.Scanner; +import java.io.IOException; public class Duke { @@ -13,7 +13,7 @@ public class Duke { private ClientList clientList; - public void run() { + public void run() throws IOException { this.parser = new Parser(); this.ui = new Ui(); this.storage = new Storage(); @@ -21,19 +21,22 @@ public void run() { this.clientList = new ClientList(); Command command; + String userInputText = ""; do { - String userInputText = ui.readCommand(); + userInputText = ui.readCommand(); command = parser.parseCommand(userInputText); command.execute(ui, storage, propertyList, clientList); - } while (!command.equals("bye")); + + } while (!userInputText.equals("quit")); + } /** * Main entry-point for the java.duke.Duke application. */ - public static void main(String[] args) { + public static void main(String[] args) throws IOException { new Duke().run(); } } diff --git a/src/main/java/seedu/duke/PropertyList.java b/src/main/java/seedu/duke/PropertyList.java index 35fad2686..aca4419c0 100644 --- a/src/main/java/seedu/duke/PropertyList.java +++ b/src/main/java/seedu/duke/PropertyList.java @@ -1,4 +1,7 @@ package seedu.duke; +import java.util.ArrayList; + public class PropertyList { + protected static ArrayList properties = new ArrayList<>(); } diff --git a/src/main/java/seedu/duke/Storage.java b/src/main/java/seedu/duke/Storage.java index 4844e3266..a477b46eb 100644 --- a/src/main/java/seedu/duke/Storage.java +++ b/src/main/java/seedu/duke/Storage.java @@ -1,4 +1,188 @@ package seedu.duke; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Scanner; + public class Storage { + private static final String DIRECTORY = "./data/"; + private static final String PROPERTY_PATH = "./data/property.txt"; + private static final String CLIENT_PATH = "./data/client.txt"; + private static final String PAIR_PATH = "./data/pair.txt"; + private static final String SEPARATOR = " | "; + private static final String DOLLAR_SIGN = "$"; + private static final String OPEN_BRACKET = "["; + private static final String CLOSE_BRACKET = "]"; + private static final String COLON = " : "; + + /** + * Constructor + */ + public Storage() { + checkFile(); + } + + /** + * Checks if all the file exist. + */ + public void checkFile() { + checkDirectory(); + checkPropertyFile(); + checkClientFile(); + checkPair(); + } + + /** + * Checks if the data directory exist. + */ + public void checkDirectory() { + File dir = new File(DIRECTORY); + boolean hasDirectory = dir.exists(); + + // Create a directory if the directory does not exist. + if (!hasDirectory) { + dir.mkdir(); + } + } + + /** + * Checks if the property file exist. + */ + public void checkPropertyFile() { + File propertyFile = new File(PROPERTY_PATH); + boolean hasPropertyFile = propertyFile.exists(); + + if (hasPropertyFile) { + // Load property into the array list + loadProperty(propertyFile); + } + } + + /** + * Checks if the client file exist. + */ + public void checkClientFile() { + File clientFile = new File(CLIENT_PATH); + boolean hasClientFile = clientFile.exists(); + + if (!hasClientFile) { + // Load client into the array list + loadClient(clientFile); + } + } + + /** + * Checks if the pair file exit. + */ + public void checkPair() { + File pairFile = new File(PAIR_PATH); + boolean hasPairFile = pairFile.exists(); + + if (!hasPairFile) { + // Load pair into the hash map + loadPair(pairFile); + } + } + + /** + * Adds the client list in the text file to the array list. + * + * @param clientFile The file that stores the list of client. + */ + public void loadClient(File clientFile) { + + } + + /** + * Loads the stored property file into the property array list. + * + * @param propertyFile The file that stores the list of property. + */ + public void loadProperty(File propertyFile) { + + } + + /** + * Loads the stored pair file into the pair hash map. + * + * @param pairFile The file that stores all the pairs. + */ + public void loadPair(File pairFile) { + + } + + + /** + * Appends the latest property into property text file. + * + * @param landlord The name of the landlord. + * @param address The address of the property being leased. + * @param price The monthly rental price. + * @param unitType The type of the unit being leased. + */ + public void addToPropertyFile(String landlord, String address, int price, String unitType) { + try { + FileWriter fw = new FileWriter(PROPERTY_PATH, true); + String rentalPrice = DOLLAR_SIGN + price; + String newText = landlord + SEPARATOR + address + SEPARATOR + rentalPrice + + SEPARATOR + unitType + System.lineSeparator(); + + fw.write(newText); + fw.close(); + } catch (IOException e) { + System.out.println("Property file does not exist."); + } + + } + + /** + * Appends the latest client into the client text file. + * + * @param name The name of the client. + * @param contact The contact number of the client. + * @param email The email of the client. + * @param budget The budget the client is looking at. + */ + public void addToClientFile(String name, String contact, String email, int budget) { + try { + FileWriter fw = new FileWriter(CLIENT_PATH, true); + String budgetPrice = DOLLAR_SIGN + budget; + String newText = name + SEPARATOR + contact + SEPARATOR + email + SEPARATOR + budgetPrice; + + fw.write(newText); + fw.close(); + + } catch (IOException e) { + System.out.println("Client file does not exist."); + } + } + + /** + * Appends the latest pair into the pair text file. + * + * @param client The name of the client. + * @param contact The contact number of the client. + * @param landlord The name of the landlord. + * @param address The address of the rental unit. + * @param price The monthly rental price per month. + * @param type The type of the rental unit. + */ + public void addToPairFile(String client, String contact, String landlord, + String address, int price, String type) { + try { + FileWriter fw = new FileWriter(PAIR_PATH, true); + String monthlyPrice = DOLLAR_SIGN + price; + String clientPortion = OPEN_BRACKET + client + SEPARATOR + contact + CLOSE_BRACKET; + String propertyPortion = OPEN_BRACKET + landlord + SEPARATOR + address + + SEPARATOR + monthlyPrice + SEPARATOR + type + CLOSE_BRACKET; + String finalString = clientPortion + COLON + propertyPortion; + fw.write(finalString); + fw.close(); + + } catch (IOException e) { + System.out.println("Pairing file does not exist."); + } + } } diff --git a/src/test/java/seedu/duke/CheckFileCreationTest.java b/src/test/java/seedu/duke/CheckFileCreationTest.java new file mode 100644 index 000000000..fa12f5690 --- /dev/null +++ b/src/test/java/seedu/duke/CheckFileCreationTest.java @@ -0,0 +1,23 @@ +package seedu.duke; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.File; + + +public class CheckFileCreationTest { + private static String DIRECTORY = "./test_dir/"; + + @Test + void checkDirectory_noDirectory_expectCreation() { + + File dir = new File(DIRECTORY); + dir.mkdir(); + assertTrue(dir.exists()); + // Delete the test directory after test is completed. + dir.delete(); + } + + +} From 3e6a7f152d503229ea592bac55efa26f6107efc8 Mon Sep 17 00:00:00 2001 From: "MSI\\User" Date: Sat, 8 Oct 2022 01:32:14 +0800 Subject: [PATCH 014/325] Fix coding standard violation --- src/main/java/seedu/duke/Storage.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/main/java/seedu/duke/Storage.java b/src/main/java/seedu/duke/Storage.java index a477b46eb..fe484591e 100644 --- a/src/main/java/seedu/duke/Storage.java +++ b/src/main/java/seedu/duke/Storage.java @@ -17,9 +17,7 @@ public class Storage { private static final String CLOSE_BRACKET = "]"; private static final String COLON = " : "; - /** - * Constructor - */ + public Storage() { checkFile(); } @@ -126,8 +124,8 @@ public void addToPropertyFile(String landlord, String address, int price, String try { FileWriter fw = new FileWriter(PROPERTY_PATH, true); String rentalPrice = DOLLAR_SIGN + price; - String newText = landlord + SEPARATOR + address + SEPARATOR + rentalPrice + - SEPARATOR + unitType + System.lineSeparator(); + String newText = landlord + SEPARATOR + address + SEPARATOR + rentalPrice + + SEPARATOR + unitType + System.lineSeparator(); fw.write(newText); fw.close(); @@ -175,8 +173,8 @@ public void addToPairFile(String client, String contact, String landlord, FileWriter fw = new FileWriter(PAIR_PATH, true); String monthlyPrice = DOLLAR_SIGN + price; String clientPortion = OPEN_BRACKET + client + SEPARATOR + contact + CLOSE_BRACKET; - String propertyPortion = OPEN_BRACKET + landlord + SEPARATOR + address + - SEPARATOR + monthlyPrice + SEPARATOR + type + CLOSE_BRACKET; + String propertyPortion = OPEN_BRACKET + landlord + SEPARATOR + address + + SEPARATOR + monthlyPrice + SEPARATOR + type + CLOSE_BRACKET; String finalString = clientPortion + COLON + propertyPortion; fw.write(finalString); fw.close(); From 6c5ebc990837a7d658bcbf3c3604db38f286badb Mon Sep 17 00:00:00 2001 From: "MSI\\User" Date: Sat, 8 Oct 2022 13:36:12 +0800 Subject: [PATCH 015/325] Add more test code for file creation and append text. --- .../seedu/duke/CheckFileCreationTest.java | 47 ++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/src/test/java/seedu/duke/CheckFileCreationTest.java b/src/test/java/seedu/duke/CheckFileCreationTest.java index fa12f5690..f691bbf2a 100644 --- a/src/test/java/seedu/duke/CheckFileCreationTest.java +++ b/src/test/java/seedu/duke/CheckFileCreationTest.java @@ -2,12 +2,21 @@ import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertEquals; import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Scanner; public class CheckFileCreationTest { - private static String DIRECTORY = "./test_dir/"; + private static final String DIRECTORY = "./test_dir/"; + private static final String INCORRECT_FILE_PATH = "./test_dir2/test_file.txt"; + private static final String FILE_PATH = "./test_file.txt"; + private static final String SEPARATOR = " | "; @Test void checkDirectory_noDirectory_expectCreation() { @@ -19,5 +28,41 @@ void checkDirectory_noDirectory_expectCreation() { dir.delete(); } + @Test + void storeFile_noDirectory_expectThrow() { + assertThrows(FileNotFoundException.class, () -> new FileWriter(INCORRECT_FILE_PATH)); + } + + @Test + void storeFile_fileExist_expectCorrectRead() { + String name = "Bobby Tan"; + String contact = "91234567"; + String email = "abc123@example.com"; + int budget = 2000; + String fileText = name + SEPARATOR + contact + SEPARATOR + email + SEPARATOR + budget; + + // Store text into the text file + try { + FileWriter fw = new FileWriter(FILE_PATH); + fw.write(fileText); + fw.close(); + } catch (IOException e) { + System.out.println("Write operation failed."); + } + + // Read the text file. + File file = new File(FILE_PATH); + try { + Scanner input = new Scanner(file); + if (input.hasNext()) { + String inputText = input.nextLine(); + file.delete(); + assertEquals(fileText, inputText); + } + } catch (FileNotFoundException e) { + System.out.println("File is not found."); + } + } + } From 0587c989dab0b8143bb4e8b1ca53a7769a10d41c Mon Sep 17 00:00:00 2001 From: "LAPTOP-S1RS66RO\\marcu" Date: Sun, 9 Oct 2022 09:53:55 +0800 Subject: [PATCH 016/325] Add Client Feature Implemented --- src/main/java/seedu/duke/Client.java | 24 ++ src/main/java/seedu/duke/ClientList.java | 23 ++ src/main/java/seedu/duke/Duke.java | 32 ++- src/main/java/seedu/duke/DukeException.java | 4 + .../duke/EmptyClientDetailException.java | 4 + .../IncorrectAddClientFlagOrderException.java | 4 + .../duke/IncorrectFlagOrderException.java | 4 + .../duke/InvalidBudgetFormatException.java | 4 + .../duke/InvalidContactNumberException.java | 4 + .../seedu/duke/InvalidEmailException.java | 4 + src/main/java/seedu/duke/Messages.java | 32 +++ .../duke/MissingClientDetailException.java | 4 + .../duke/MissingClientFlagException.java | 4 + .../MissingCommandAddDetailException.java | 4 + .../java/seedu/duke/MissingFlagException.java | 4 + src/main/java/seedu/duke/Parser.java | 215 +++++++++++++++++- src/main/java/seedu/duke/Ui.java | 52 +++++ .../UndefinedSubCommandAddTypeException.java | 4 + .../java/seedu/duke/command/CommandAdd.java | 10 +- .../seedu/duke/command/CommandAddClient.java | 28 +++ .../java/seedu/duke/command/CommandBye.java | 13 ++ .../seedu/duke/command/CommandUndefined.java | 13 ++ 22 files changed, 465 insertions(+), 25 deletions(-) create mode 100644 src/main/java/seedu/duke/DukeException.java create mode 100644 src/main/java/seedu/duke/EmptyClientDetailException.java create mode 100644 src/main/java/seedu/duke/IncorrectAddClientFlagOrderException.java create mode 100644 src/main/java/seedu/duke/IncorrectFlagOrderException.java create mode 100644 src/main/java/seedu/duke/InvalidBudgetFormatException.java create mode 100644 src/main/java/seedu/duke/InvalidContactNumberException.java create mode 100644 src/main/java/seedu/duke/InvalidEmailException.java create mode 100644 src/main/java/seedu/duke/Messages.java create mode 100644 src/main/java/seedu/duke/MissingClientDetailException.java create mode 100644 src/main/java/seedu/duke/MissingClientFlagException.java create mode 100644 src/main/java/seedu/duke/MissingCommandAddDetailException.java create mode 100644 src/main/java/seedu/duke/MissingFlagException.java create mode 100644 src/main/java/seedu/duke/UndefinedSubCommandAddTypeException.java create mode 100644 src/main/java/seedu/duke/command/CommandAddClient.java create mode 100644 src/main/java/seedu/duke/command/CommandBye.java create mode 100644 src/main/java/seedu/duke/command/CommandUndefined.java diff --git a/src/main/java/seedu/duke/Client.java b/src/main/java/seedu/duke/Client.java index 65b18143f..fa2f796e9 100644 --- a/src/main/java/seedu/duke/Client.java +++ b/src/main/java/seedu/duke/Client.java @@ -1,4 +1,28 @@ package seedu.duke; public class Client { + private String clientName; + private String clientContactNumber; + private String clientEmail; + private String clientBudgetPerMonth; + + public Client(String clientName, String clientContactNumber, String clientEmail, String clientBudgetPerMonth) { + this.clientName = clientName; + this.clientContactNumber = clientContactNumber; + this.clientEmail = clientEmail; + this.clientBudgetPerMonth = clientBudgetPerMonth; + } + + @Override + public String toString() { + StringBuilder clientDetails = new StringBuilder(); + clientDetails.append(" Client: " + clientName).append(System.lineSeparator()); + clientDetails.append(" Contact Number: " + clientContactNumber).append(System.lineSeparator()); + boolean hasEmail = (!clientEmail.isEmpty()); + if (hasEmail) { + clientDetails.append(" Email: " + clientEmail).append(System.lineSeparator()); + } + clientDetails.append(" Budget: SGD" + clientBudgetPerMonth + "/month").append(System.lineSeparator()); + return clientDetails.toString().trim(); + } } diff --git a/src/main/java/seedu/duke/ClientList.java b/src/main/java/seedu/duke/ClientList.java index 3b11cf7eb..29b7936ad 100644 --- a/src/main/java/seedu/duke/ClientList.java +++ b/src/main/java/seedu/duke/ClientList.java @@ -1,4 +1,27 @@ package seedu.duke; +import java.util.ArrayList; + public class ClientList { + private static int currentListSize; + private static ArrayList clientList; + + public ClientList() { + clientList = new ArrayList<>(); + currentListSize = 0; + } + + public int getCurrentListSize() { + return currentListSize; + } + + public ArrayList getClientList() { + return clientList; + } + + public void addClient(String clientName, String clientContactNumber, String clientEmail, + String clientBudgetPerMonth) { + clientList.add(new Client(clientName, clientContactNumber, clientEmail, clientBudgetPerMonth)); + currentListSize++; + } } diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 2f1f97a84..439b0a8ef 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -1,9 +1,7 @@ package seedu.duke; import seedu.duke.command.Command; - -import java.util.Scanner; - +import seedu.duke.command.CommandBye; public class Duke { private Parser parser; @@ -21,13 +19,31 @@ public void run() { this.clientList = new ClientList(); Command command; + boolean isCommandBye = false; do { - String userInputText = ui.readCommand(); - command = parser.parseCommand(userInputText); - command.execute(ui, storage, propertyList, clientList); - - } while (!command.equals("bye")); + try { + String userInputText = ui.readCommand(); + command = parser.parseCommand(userInputText); + command.execute(ui, storage, propertyList, clientList); + isCommandBye = (command instanceof CommandBye); + } catch (MissingCommandAddDetailException e) { + ui.showMissingCommandAddDetailMessage(); + } catch (UndefinedSubCommandAddTypeException e) { + ui.showUndefinedSubCommandAddTypeMessage(); + } catch (EmptyClientDetailException e) { + ui.showEmptyClientDetailMessage(); + } catch (MissingClientFlagException | IncorrectAddClientFlagOrderException + | MissingClientDetailException e) { + ui.showAddClientWrongFormatMessage(); + } catch (InvalidContactNumberException e) { + ui.showInvalidContactNumberMessage(); + } catch (InvalidEmailException e) { + ui.showInvalidEmailMessage(); + } catch (InvalidBudgetFormatException e) { + ui.showInvalidBudgetFormatMessage(); + } + } while (!isCommandBye); } /** diff --git a/src/main/java/seedu/duke/DukeException.java b/src/main/java/seedu/duke/DukeException.java new file mode 100644 index 000000000..d1deb9421 --- /dev/null +++ b/src/main/java/seedu/duke/DukeException.java @@ -0,0 +1,4 @@ +package seedu.duke; + +public abstract class DukeException extends Exception { +} diff --git a/src/main/java/seedu/duke/EmptyClientDetailException.java b/src/main/java/seedu/duke/EmptyClientDetailException.java new file mode 100644 index 000000000..736dd345e --- /dev/null +++ b/src/main/java/seedu/duke/EmptyClientDetailException.java @@ -0,0 +1,4 @@ +package seedu.duke; + +public class EmptyClientDetailException extends DukeException { +} diff --git a/src/main/java/seedu/duke/IncorrectAddClientFlagOrderException.java b/src/main/java/seedu/duke/IncorrectAddClientFlagOrderException.java new file mode 100644 index 000000000..8a277461b --- /dev/null +++ b/src/main/java/seedu/duke/IncorrectAddClientFlagOrderException.java @@ -0,0 +1,4 @@ +package seedu.duke; + +public class IncorrectAddClientFlagOrderException extends IncorrectFlagOrderException { +} diff --git a/src/main/java/seedu/duke/IncorrectFlagOrderException.java b/src/main/java/seedu/duke/IncorrectFlagOrderException.java new file mode 100644 index 000000000..bf49cc741 --- /dev/null +++ b/src/main/java/seedu/duke/IncorrectFlagOrderException.java @@ -0,0 +1,4 @@ +package seedu.duke; + +public class IncorrectFlagOrderException extends DukeException { +} diff --git a/src/main/java/seedu/duke/InvalidBudgetFormatException.java b/src/main/java/seedu/duke/InvalidBudgetFormatException.java new file mode 100644 index 000000000..481a4c2ec --- /dev/null +++ b/src/main/java/seedu/duke/InvalidBudgetFormatException.java @@ -0,0 +1,4 @@ +package seedu.duke; + +public class InvalidBudgetFormatException extends DukeException { +} diff --git a/src/main/java/seedu/duke/InvalidContactNumberException.java b/src/main/java/seedu/duke/InvalidContactNumberException.java new file mode 100644 index 000000000..37c4aab9f --- /dev/null +++ b/src/main/java/seedu/duke/InvalidContactNumberException.java @@ -0,0 +1,4 @@ +package seedu.duke; + +public class InvalidContactNumberException extends DukeException { +} diff --git a/src/main/java/seedu/duke/InvalidEmailException.java b/src/main/java/seedu/duke/InvalidEmailException.java new file mode 100644 index 000000000..7aac933c2 --- /dev/null +++ b/src/main/java/seedu/duke/InvalidEmailException.java @@ -0,0 +1,4 @@ +package seedu.duke; + +public class InvalidEmailException extends DukeException { +} diff --git a/src/main/java/seedu/duke/Messages.java b/src/main/java/seedu/duke/Messages.java new file mode 100644 index 000000000..711955f4f --- /dev/null +++ b/src/main/java/seedu/duke/Messages.java @@ -0,0 +1,32 @@ +package seedu.duke; + +public class Messages { + public static final String MESSAGE_CLIENT_ADDED = "Adding a client with the following information:"; + + public static final String MESSAGE_EMPTY_ADD_DESCRIPTION = "OOPS!!! The description for add cannot be empty."; + + public static final String MESSAGE_MISSING_SUB_COMMAND_TYPE_FOR_ADD = "OOPS!!! To add, " + + "please specify sub-command type.\n" + + "For client: add -client\n" + + "For property: add -property"; + + public static final String MESSAGE_EMPTY_CLIENT_DESCRIPTION = "OOPS!!! The description of client cannot be empty."; + + public static final String MESSAGE_ADD_CLIENT_WRONG_FORMAT = "OOPS!!! To add a client, it requires " + + "the following format and details as shown below."; + + public static final String MESSAGE_CLIENT_INPUT_EXAMPLE = "Format: add -client n/NAME c/CONTACT_NUMBER e/EMAIL " + + "b/BUDGET_MONTH\n" + + "Example: add -client n/Doja Cat c/93437878 e/doja88@example.com b/2000\n" + + "Note: Email is optional"; + + public static final String MESSAGE_TRY_AGAIN = "Please try again."; + + public static final String MESSAGE_INVALID_CONTACT_NUMBER = "OOPS!!! Please enter a valid Singapore Contact Number " + + "(No extension)"; + + public static final String MESSAGE_INVALID_EMAIL = "OOPS!!! Please enter a valid Email Address"; + + public static final String MESSAGE_INVALID_BUDGET_FORMAT = "OOPS!!! Please enter positive number " + + "(No letter/symbols, etc) for budget"; +} diff --git a/src/main/java/seedu/duke/MissingClientDetailException.java b/src/main/java/seedu/duke/MissingClientDetailException.java new file mode 100644 index 000000000..57403cd91 --- /dev/null +++ b/src/main/java/seedu/duke/MissingClientDetailException.java @@ -0,0 +1,4 @@ +package seedu.duke; + +public class MissingClientDetailException extends DukeException { +} diff --git a/src/main/java/seedu/duke/MissingClientFlagException.java b/src/main/java/seedu/duke/MissingClientFlagException.java new file mode 100644 index 000000000..7a283f418 --- /dev/null +++ b/src/main/java/seedu/duke/MissingClientFlagException.java @@ -0,0 +1,4 @@ +package seedu.duke; + +public class MissingClientFlagException extends MissingFlagException { +} diff --git a/src/main/java/seedu/duke/MissingCommandAddDetailException.java b/src/main/java/seedu/duke/MissingCommandAddDetailException.java new file mode 100644 index 000000000..6b8b1237e --- /dev/null +++ b/src/main/java/seedu/duke/MissingCommandAddDetailException.java @@ -0,0 +1,4 @@ +package seedu.duke; + +public class MissingCommandAddDetailException extends DukeException { +} diff --git a/src/main/java/seedu/duke/MissingFlagException.java b/src/main/java/seedu/duke/MissingFlagException.java new file mode 100644 index 000000000..9e32a0474 --- /dev/null +++ b/src/main/java/seedu/duke/MissingFlagException.java @@ -0,0 +1,4 @@ +package seedu.duke; + +public class MissingFlagException extends DukeException { +} diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index ea79cdd0b..1a8bd4c65 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -1,19 +1,218 @@ package seedu.duke; -import seedu.duke.command.CommandAdd; +import seedu.duke.command.Command; +import seedu.duke.command.CommandAddClient; +import seedu.duke.command.CommandUndefined; -public class Parser { - - public CommandAdd parseCommand(String input) { +import java.util.ArrayList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; - String[] commands = input.trim().split(" ", 2); - // This is the type of command that will be executed - String commandType = commands[0]; +public class Parser { + public static final int ADD_CLIENT_FLAG_SIZE = 4; + public Command parseCommand(String input) throws MissingCommandAddDetailException, + UndefinedSubCommandAddTypeException, EmptyClientDetailException, MissingClientFlagException, + IncorrectAddClientFlagOrderException, MissingClientDetailException, InvalidContactNumberException, + InvalidEmailException, InvalidBudgetFormatException { + ArrayList processedCommandDetails = partitionCommandTypeAndDetails(input); + String commandType = processedCommandDetails.get(0); + String commandDetails = processedCommandDetails.get(1); switch (commandType) { + case ("add"): + checkForEmptyCommandAddDetails(commandDetails); + ArrayList processedAddCommandDetails = partitionCommandTypeAndDetails(commandDetails); + String subCommandType = processedAddCommandDetails.get(0); + String clientOrPropertyDescriptions = processedAddCommandDetails.get(1); + + if (subCommandType.equals("-client")) { + return prepareForCommandAddClient(clientOrPropertyDescriptions); + } else { + throw new UndefinedSubCommandAddTypeException(); + } + default: - return new CommandAdd(commands); + return new CommandUndefined(); + } + } + + private ArrayList partitionCommandTypeAndDetails(String fullCommandDetails) { + String[] inputDetails = fullCommandDetails.trim().split(" ", 2); + // This is the type of command/sub-command that will be executed + String commandType = inputDetails[0]; + String commandDetails = fullCommandDetails.replaceFirst(commandType, "").trim(); + ArrayList processedCommandDetails = new ArrayList<>(); + processedCommandDetails.add(commandType); + processedCommandDetails.add(commandDetails); + return processedCommandDetails; + } + + private void checkForEmptyCommandAddDetails(String commandAddDetails) throws MissingCommandAddDetailException { + boolean isEmptyCommandAddDetail = checkForEmptyDetail(commandAddDetails); + if (isEmptyCommandAddDetail) { + throw new MissingCommandAddDetailException(); + } + } + + private Command prepareForCommandAddClient(String rawClientDescriptions) throws EmptyClientDetailException, + MissingClientFlagException, IncorrectAddClientFlagOrderException, MissingClientDetailException, + InvalidContactNumberException, InvalidEmailException, InvalidBudgetFormatException { + checkForEmptyAddClientDetails(rawClientDescriptions); + try { + ArrayList clientDetails = processClientDetails(rawClientDescriptions); + validateClientDetails(clientDetails); + return new CommandAddClient(clientDetails); + } catch (MissingFlagException e) { + throw new MissingClientFlagException(); + } catch (IncorrectFlagOrderException e) { + throw new IncorrectAddClientFlagOrderException(); + } + } + + private void validateClientDetails(ArrayList clientDetails) throws MissingClientDetailException, + InvalidContactNumberException, InvalidEmailException, InvalidBudgetFormatException { + //Checks for Missing Client Name, Contact Number, Budget Per Month (SGD) + checkForMissingClientDetails(clientDetails.get(0)); + checkForMissingClientDetails(clientDetails.get(1)); + checkForMissingClientDetails(clientDetails.get(3)); + + //Checks for Contact Number, Email and Budget Format + checkForValidSingaporeContactNumber(clientDetails.get(1)); + boolean hasEmail = !clientDetails.get(2).isEmpty(); + if (hasEmail) { + checkForValidEmail(clientDetails.get(2)); + } + checkForBudgetNumberFormat(clientDetails.get(3)); + } + + private void checkForValidSingaporeContactNumber(String clientContactNumber) throws InvalidContactNumberException { + boolean hasValidContactNumber = checkForDetailFormat("^[689]\\d{7}$", clientContactNumber); + if (!hasValidContactNumber) { + throw new InvalidContactNumberException(); + } + } + + private void checkForValidEmail(String clientEmail) throws InvalidEmailException { + //General Email Regex (RFC 5322 Official Standard) + String regex = "(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\" + + "x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-" + + "9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-" + + "9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0" + + "c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])"; + boolean hasValidContactNumber = checkForDetailFormat(regex, clientEmail); + if (!hasValidContactNumber) { + throw new InvalidEmailException(); + } + } + + private void checkForBudgetNumberFormat(String budget) throws InvalidBudgetFormatException { + //Accepts only positive whole number + String regex = "^[1-9]\\d*$"; + boolean hasValidBudgetNumberFormat = checkForDetailFormat(regex, budget); + if (!hasValidBudgetNumberFormat) { + throw new InvalidBudgetFormatException(); + } + } + + private boolean checkForDetailFormat(String regex, String detail) { + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(detail); + return matcher.matches(); + } + + private void checkForMissingClientDetails(String clientDetail) throws MissingClientDetailException { + boolean isEmptyDetail = checkForEmptyDetail(clientDetail); + if (isEmptyDetail) { + throw new MissingClientDetailException(); + } + } + + private void checkForEmptyAddClientDetails(String commandAddDescriptions) throws EmptyClientDetailException { + boolean isEmptyCommandAddDetail = checkForEmptyDetail(commandAddDescriptions); + if (isEmptyCommandAddDetail) { + throw new EmptyClientDetailException(); + } + } + + private ArrayList processClientDetails(String rawClientDetails) throws MissingFlagException, + IncorrectFlagOrderException { + String[] addClientFlags = {"n/", "c/", "e/", "b/"}; + int[] addClientFlagIndexPositions = new int[ADD_CLIENT_FLAG_SIZE]; + + for (int i = 0; i < addClientFlags.length; i++) { + addClientFlagIndexPositions[i] = rawClientDetails.indexOf(addClientFlags[i]); + } + + checkForMissingClientFlags(addClientFlagIndexPositions); + checkForClientFlagsOrder(addClientFlagIndexPositions); + return extractClientDetails(rawClientDetails, addClientFlagIndexPositions); + } + + private void checkForMissingClientFlags(int[] addClientFlagIndexPositions) throws MissingFlagException { + checkForEssentialAddFlag(addClientFlagIndexPositions[0]); + checkForEssentialAddFlag(addClientFlagIndexPositions[1]); + checkForEssentialAddFlag(addClientFlagIndexPositions[3]); + } + + private void checkForClientFlagsOrder(int[] addClientFlagIndexPositions) throws IncorrectFlagOrderException { + boolean hasEmail = (addClientFlagIndexPositions[2] != -1); + checkForCorrectFlagOrder(addClientFlagIndexPositions[0], addClientFlagIndexPositions[1]); + checkForCorrectFlagOrder(addClientFlagIndexPositions[1], addClientFlagIndexPositions[3]); + if (hasEmail) { + checkForCorrectFlagOrder(addClientFlagIndexPositions[1], addClientFlagIndexPositions[2]); + checkForCorrectFlagOrder(addClientFlagIndexPositions[2], addClientFlagIndexPositions[3]); + } + } + + private ArrayList extractClientDetails(String rawClientDetails, int[] addClientFlagIndexPositions) { + boolean hasEmail = (addClientFlagIndexPositions[2] != -1); + String clientContactNumber; + String clientEmail = ""; + if (hasEmail) { + clientContactNumber = extractDetail(rawClientDetails, addClientFlagIndexPositions[1] + 2, + addClientFlagIndexPositions[2]); + clientEmail = extractDetail(rawClientDetails, addClientFlagIndexPositions[2] + 2, + addClientFlagIndexPositions[3]); + } else { + clientContactNumber = extractDetail(rawClientDetails, addClientFlagIndexPositions[1] + 2, + addClientFlagIndexPositions[3]); + } + String clientName = extractDetail(rawClientDetails, addClientFlagIndexPositions[0] + 2, + addClientFlagIndexPositions[1]); + String clientBudgetPerMonth = extractDetail(rawClientDetails, addClientFlagIndexPositions[3] + 2); + + ArrayList processedClientDetails = new ArrayList<>(); + processedClientDetails.add(clientName.trim()); + processedClientDetails.add(clientContactNumber.trim()); + processedClientDetails.add(clientEmail.trim()); + processedClientDetails.add(clientBudgetPerMonth.trim()); + return processedClientDetails; + } + + private void checkForEssentialAddFlag(int addClientFlagIndexes) throws MissingFlagException { + boolean hasFlag = (addClientFlagIndexes != -1); + if (!hasFlag) { + throw new MissingFlagException(); } } + + private void checkForCorrectFlagOrder(int flagPosition, int nextFlagPosition) throws IncorrectFlagOrderException { + boolean hasCorrectOrder = (flagPosition < nextFlagPosition); + if (!hasCorrectOrder) { + throw new IncorrectFlagOrderException(); + } + } + + private static String extractDetail(String rawClientDetails, int beginIndex) { + return rawClientDetails.substring(beginIndex).trim(); + } + + private static String extractDetail(String rawClientDetails, int beginIndex, int endIndex) { + return rawClientDetails.substring(beginIndex, endIndex).trim(); + } + + private boolean checkForEmptyDetail(String commandDetails) { + return commandDetails.trim().isEmpty(); + } } diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index d9b810829..16270a53f 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -2,6 +2,17 @@ import java.util.Scanner; +import static seedu.duke.Messages.MESSAGE_CLIENT_ADDED; +import static seedu.duke.Messages.MESSAGE_EMPTY_ADD_DESCRIPTION; +import static seedu.duke.Messages.MESSAGE_MISSING_SUB_COMMAND_TYPE_FOR_ADD; +import static seedu.duke.Messages.MESSAGE_EMPTY_CLIENT_DESCRIPTION; +import static seedu.duke.Messages.MESSAGE_ADD_CLIENT_WRONG_FORMAT; +import static seedu.duke.Messages.MESSAGE_CLIENT_INPUT_EXAMPLE; +import static seedu.duke.Messages.MESSAGE_TRY_AGAIN; +import static seedu.duke.Messages.MESSAGE_INVALID_CONTACT_NUMBER; +import static seedu.duke.Messages.MESSAGE_INVALID_EMAIL; +import static seedu.duke.Messages.MESSAGE_INVALID_BUDGET_FORMAT; + public class Ui { private static boolean inputIsEmpty(String rawInput) { @@ -20,4 +31,45 @@ public static String readCommand() { return rawInput; } + + public void showToUser(String message) { + System.out.println(message); + } + + public void showClientAddedConfirmationMessage(ClientList clientList) { + int currentListSize = clientList.getCurrentListSize(); + showToUser(MESSAGE_CLIENT_ADDED); + showToUser(" " + clientList.getClientList().get(currentListSize - 1)); + } + + /* Add Client Related Exceptions */ + public void showMissingCommandAddDetailMessage() { + showToUser(MESSAGE_EMPTY_ADD_DESCRIPTION); + } + + public void showUndefinedSubCommandAddTypeMessage() { + showToUser(MESSAGE_MISSING_SUB_COMMAND_TYPE_FOR_ADD); + } + + public void showEmptyClientDetailMessage() { + showToUser(MESSAGE_EMPTY_CLIENT_DESCRIPTION); + } + + public void showAddClientWrongFormatMessage() { + showToUser(MESSAGE_ADD_CLIENT_WRONG_FORMAT); + showToUser(MESSAGE_CLIENT_INPUT_EXAMPLE); + showToUser(MESSAGE_TRY_AGAIN); + } + + public void showInvalidContactNumberMessage() { + showToUser(MESSAGE_INVALID_CONTACT_NUMBER); + } + + public void showInvalidEmailMessage() { + showToUser(MESSAGE_INVALID_EMAIL); + } + + public void showInvalidBudgetFormatMessage() { + showToUser(MESSAGE_INVALID_BUDGET_FORMAT); + } } diff --git a/src/main/java/seedu/duke/UndefinedSubCommandAddTypeException.java b/src/main/java/seedu/duke/UndefinedSubCommandAddTypeException.java new file mode 100644 index 000000000..f7d3289cd --- /dev/null +++ b/src/main/java/seedu/duke/UndefinedSubCommandAddTypeException.java @@ -0,0 +1,4 @@ +package seedu.duke; + +public class UndefinedSubCommandAddTypeException extends DukeException { +} diff --git a/src/main/java/seedu/duke/command/CommandAdd.java b/src/main/java/seedu/duke/command/CommandAdd.java index 8b4298a7a..6c313f63f 100644 --- a/src/main/java/seedu/duke/command/CommandAdd.java +++ b/src/main/java/seedu/duke/command/CommandAdd.java @@ -5,13 +5,5 @@ import seedu.duke.Storage; import seedu.duke.Ui; -public class CommandAdd extends Command { - public CommandAdd(String[] commands) { - - } - - @Override - public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList) { - - } +public abstract class CommandAdd extends Command { } diff --git a/src/main/java/seedu/duke/command/CommandAddClient.java b/src/main/java/seedu/duke/command/CommandAddClient.java new file mode 100644 index 000000000..782a0016d --- /dev/null +++ b/src/main/java/seedu/duke/command/CommandAddClient.java @@ -0,0 +1,28 @@ +package seedu.duke.command; + +import seedu.duke.ClientList; +import seedu.duke.PropertyList; +import seedu.duke.Storage; +import seedu.duke.Ui; + +import java.util.ArrayList; + +public class CommandAddClient extends CommandAdd { + private final String clientName; + private final String clientContactNumber; + private final String clientEmail; + private final String clientBudgetPerMonth; + + public CommandAddClient(ArrayList clientDetails) { + this.clientName = clientDetails.get(0); + this.clientContactNumber = clientDetails.get(1); + this.clientEmail = clientDetails.get(2); + this.clientBudgetPerMonth = clientDetails.get(3); + } + + @Override + public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList) { + clientList.addClient(clientName, clientContactNumber, clientEmail, clientBudgetPerMonth); + ui.showClientAddedConfirmationMessage(clientList); + } +} diff --git a/src/main/java/seedu/duke/command/CommandBye.java b/src/main/java/seedu/duke/command/CommandBye.java new file mode 100644 index 000000000..89efbc0b0 --- /dev/null +++ b/src/main/java/seedu/duke/command/CommandBye.java @@ -0,0 +1,13 @@ +package seedu.duke.command; + +import seedu.duke.ClientList; +import seedu.duke.PropertyList; +import seedu.duke.Storage; +import seedu.duke.Ui; + +public class CommandBye extends Command { + @Override + public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList) { + //print bye message + } +} diff --git a/src/main/java/seedu/duke/command/CommandUndefined.java b/src/main/java/seedu/duke/command/CommandUndefined.java new file mode 100644 index 000000000..aee798ebf --- /dev/null +++ b/src/main/java/seedu/duke/command/CommandUndefined.java @@ -0,0 +1,13 @@ +package seedu.duke.command; + +import seedu.duke.ClientList; +import seedu.duke.PropertyList; +import seedu.duke.Storage; +import seedu.duke.Ui; + +public class CommandUndefined extends Command { + @Override + public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList) { + //showCommandUndefinedMessage + } +} From fcd0a0396e3382c9658c79014db898068d318158 Mon Sep 17 00:00:00 2001 From: "LAPTOP-S1RS66RO\\marcu" Date: Sun, 9 Oct 2022 10:26:54 +0800 Subject: [PATCH 017/325] Added JavaDoc for Command Add Client related Classes --- src/main/java/seedu/duke/Client.java | 3 +++ src/main/java/seedu/duke/ClientList.java | 11 +++++++++++ src/main/java/seedu/duke/Duke.java | 2 +- src/main/java/seedu/duke/DukeException.java | 3 +++ .../java/seedu/duke/EmptyClientDetailException.java | 3 +++ .../seedu/duke/EmptyCommandAddDetailException.java | 7 +++++++ .../duke/IncorrectAddClientFlagOrderException.java | 3 +++ .../java/seedu/duke/IncorrectFlagOrderException.java | 3 +++ .../java/seedu/duke/InvalidBudgetFormatException.java | 3 +++ .../seedu/duke/InvalidContactNumberException.java | 3 +++ src/main/java/seedu/duke/InvalidEmailException.java | 3 +++ src/main/java/seedu/duke/Messages.java | 3 +++ .../java/seedu/duke/MissingClientDetailException.java | 3 +++ .../java/seedu/duke/MissingClientFlagException.java | 3 +++ .../seedu/duke/MissingCommandAddDetailException.java | 4 ---- src/main/java/seedu/duke/MissingFlagException.java | 3 +++ src/main/java/seedu/duke/Parser.java | 6 +++--- .../duke/UndefinedSubCommandAddTypeException.java | 3 +++ src/main/java/seedu/duke/command/Command.java | 4 +++- src/main/java/seedu/duke/command/CommandAdd.java | 8 +++----- .../java/seedu/duke/command/CommandAddClient.java | 9 +++++++++ 21 files changed, 76 insertions(+), 14 deletions(-) create mode 100644 src/main/java/seedu/duke/EmptyCommandAddDetailException.java delete mode 100644 src/main/java/seedu/duke/MissingCommandAddDetailException.java diff --git a/src/main/java/seedu/duke/Client.java b/src/main/java/seedu/duke/Client.java index fa2f796e9..5d24b44af 100644 --- a/src/main/java/seedu/duke/Client.java +++ b/src/main/java/seedu/duke/Client.java @@ -1,5 +1,8 @@ package seedu.duke; +/** + * Represents a client. + */ public class Client { private String clientName; private String clientContactNumber; diff --git a/src/main/java/seedu/duke/ClientList.java b/src/main/java/seedu/duke/ClientList.java index 29b7936ad..4c82ca371 100644 --- a/src/main/java/seedu/duke/ClientList.java +++ b/src/main/java/seedu/duke/ClientList.java @@ -2,6 +2,9 @@ import java.util.ArrayList; +/** + * Stores the list of clients. + */ public class ClientList { private static int currentListSize; private static ArrayList clientList; @@ -19,6 +22,14 @@ public ArrayList getClientList() { return clientList; } + /** + * Adds a client to client list and updates client list size. + * + * @param clientName Name of client. + * @param clientContactNumber Contact Number of client. + * @param clientEmail Email of client. + * @param clientBudgetPerMonth Budget Per Month for client. + */ public void addClient(String clientName, String clientContactNumber, String clientEmail, String clientBudgetPerMonth) { clientList.add(new Client(clientName, clientContactNumber, clientEmail, clientBudgetPerMonth)); diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 439b0a8ef..23c4ce4d5 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -27,7 +27,7 @@ public void run() { command = parser.parseCommand(userInputText); command.execute(ui, storage, propertyList, clientList); isCommandBye = (command instanceof CommandBye); - } catch (MissingCommandAddDetailException e) { + } catch (EmptyCommandAddDetailException e) { ui.showMissingCommandAddDetailMessage(); } catch (UndefinedSubCommandAddTypeException e) { ui.showUndefinedSubCommandAddTypeMessage(); diff --git a/src/main/java/seedu/duke/DukeException.java b/src/main/java/seedu/duke/DukeException.java index d1deb9421..22e6cbcfa 100644 --- a/src/main/java/seedu/duke/DukeException.java +++ b/src/main/java/seedu/duke/DukeException.java @@ -1,4 +1,7 @@ package seedu.duke; +/** + * Represents exceptions local to Duke. + */ public abstract class DukeException extends Exception { } diff --git a/src/main/java/seedu/duke/EmptyClientDetailException.java b/src/main/java/seedu/duke/EmptyClientDetailException.java index 736dd345e..8a0f66cb0 100644 --- a/src/main/java/seedu/duke/EmptyClientDetailException.java +++ b/src/main/java/seedu/duke/EmptyClientDetailException.java @@ -1,4 +1,7 @@ package seedu.duke; +/** + * Represents exception when no client description is given when adding client. + */ public class EmptyClientDetailException extends DukeException { } diff --git a/src/main/java/seedu/duke/EmptyCommandAddDetailException.java b/src/main/java/seedu/duke/EmptyCommandAddDetailException.java new file mode 100644 index 000000000..e84242314 --- /dev/null +++ b/src/main/java/seedu/duke/EmptyCommandAddDetailException.java @@ -0,0 +1,7 @@ +package seedu.duke; + +/** + * Represents exception when no information is provided when adding (property/client). + */ +public class EmptyCommandAddDetailException extends DukeException { +} diff --git a/src/main/java/seedu/duke/IncorrectAddClientFlagOrderException.java b/src/main/java/seedu/duke/IncorrectAddClientFlagOrderException.java index 8a277461b..6393ec72a 100644 --- a/src/main/java/seedu/duke/IncorrectAddClientFlagOrderException.java +++ b/src/main/java/seedu/duke/IncorrectAddClientFlagOrderException.java @@ -1,4 +1,7 @@ package seedu.duke; +/** + * Represents exception when incorrect flag order is given when adding client. + */ public class IncorrectAddClientFlagOrderException extends IncorrectFlagOrderException { } diff --git a/src/main/java/seedu/duke/IncorrectFlagOrderException.java b/src/main/java/seedu/duke/IncorrectFlagOrderException.java index bf49cc741..71c06fc6e 100644 --- a/src/main/java/seedu/duke/IncorrectFlagOrderException.java +++ b/src/main/java/seedu/duke/IncorrectFlagOrderException.java @@ -1,4 +1,7 @@ package seedu.duke; +/** + * Represents exception when incorrect flag order is given by user. + */ public class IncorrectFlagOrderException extends DukeException { } diff --git a/src/main/java/seedu/duke/InvalidBudgetFormatException.java b/src/main/java/seedu/duke/InvalidBudgetFormatException.java index 481a4c2ec..f8300aa2b 100644 --- a/src/main/java/seedu/duke/InvalidBudgetFormatException.java +++ b/src/main/java/seedu/duke/InvalidBudgetFormatException.java @@ -1,4 +1,7 @@ package seedu.duke; +/** + * Represents exception when incorrect format for budget is given when adding client. + */ public class InvalidBudgetFormatException extends DukeException { } diff --git a/src/main/java/seedu/duke/InvalidContactNumberException.java b/src/main/java/seedu/duke/InvalidContactNumberException.java index 37c4aab9f..284464ce5 100644 --- a/src/main/java/seedu/duke/InvalidContactNumberException.java +++ b/src/main/java/seedu/duke/InvalidContactNumberException.java @@ -1,4 +1,7 @@ package seedu.duke; +/** + * Represents exception when incorrect contact number (Singapore) format is given when adding client. + */ public class InvalidContactNumberException extends DukeException { } diff --git a/src/main/java/seedu/duke/InvalidEmailException.java b/src/main/java/seedu/duke/InvalidEmailException.java index 7aac933c2..f74c26cce 100644 --- a/src/main/java/seedu/duke/InvalidEmailException.java +++ b/src/main/java/seedu/duke/InvalidEmailException.java @@ -1,4 +1,7 @@ package seedu.duke; +/** + * Represents exception when incorrect email format is given when adding client. + */ public class InvalidEmailException extends DukeException { } diff --git a/src/main/java/seedu/duke/Messages.java b/src/main/java/seedu/duke/Messages.java index 711955f4f..d9c8ede50 100644 --- a/src/main/java/seedu/duke/Messages.java +++ b/src/main/java/seedu/duke/Messages.java @@ -1,5 +1,8 @@ package seedu.duke; +/** + * Container for user visible messages. + */ public class Messages { public static final String MESSAGE_CLIENT_ADDED = "Adding a client with the following information:"; diff --git a/src/main/java/seedu/duke/MissingClientDetailException.java b/src/main/java/seedu/duke/MissingClientDetailException.java index 57403cd91..d9d9fe1e6 100644 --- a/src/main/java/seedu/duke/MissingClientDetailException.java +++ b/src/main/java/seedu/duke/MissingClientDetailException.java @@ -1,4 +1,7 @@ package seedu.duke; +/** + * Represents exception when there is missing client details when adding client. + */ public class MissingClientDetailException extends DukeException { } diff --git a/src/main/java/seedu/duke/MissingClientFlagException.java b/src/main/java/seedu/duke/MissingClientFlagException.java index 7a283f418..140710f4b 100644 --- a/src/main/java/seedu/duke/MissingClientFlagException.java +++ b/src/main/java/seedu/duke/MissingClientFlagException.java @@ -1,4 +1,7 @@ package seedu.duke; +/** + * Represents exception when there is missing client flags when adding client. + */ public class MissingClientFlagException extends MissingFlagException { } diff --git a/src/main/java/seedu/duke/MissingCommandAddDetailException.java b/src/main/java/seedu/duke/MissingCommandAddDetailException.java deleted file mode 100644 index 6b8b1237e..000000000 --- a/src/main/java/seedu/duke/MissingCommandAddDetailException.java +++ /dev/null @@ -1,4 +0,0 @@ -package seedu.duke; - -public class MissingCommandAddDetailException extends DukeException { -} diff --git a/src/main/java/seedu/duke/MissingFlagException.java b/src/main/java/seedu/duke/MissingFlagException.java index 9e32a0474..61368864d 100644 --- a/src/main/java/seedu/duke/MissingFlagException.java +++ b/src/main/java/seedu/duke/MissingFlagException.java @@ -1,4 +1,7 @@ package seedu.duke; +/** + * Represents exception when flags required for command are missing. + */ public class MissingFlagException extends DukeException { } diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 1a8bd4c65..f67eeffe4 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -12,7 +12,7 @@ public class Parser { public static final int ADD_CLIENT_FLAG_SIZE = 4; - public Command parseCommand(String input) throws MissingCommandAddDetailException, + public Command parseCommand(String input) throws EmptyCommandAddDetailException, UndefinedSubCommandAddTypeException, EmptyClientDetailException, MissingClientFlagException, IncorrectAddClientFlagOrderException, MissingClientDetailException, InvalidContactNumberException, InvalidEmailException, InvalidBudgetFormatException { @@ -48,10 +48,10 @@ private ArrayList partitionCommandTypeAndDetails(String fullCommandDetai return processedCommandDetails; } - private void checkForEmptyCommandAddDetails(String commandAddDetails) throws MissingCommandAddDetailException { + private void checkForEmptyCommandAddDetails(String commandAddDetails) throws EmptyCommandAddDetailException { boolean isEmptyCommandAddDetail = checkForEmptyDetail(commandAddDetails); if (isEmptyCommandAddDetail) { - throw new MissingCommandAddDetailException(); + throw new EmptyCommandAddDetailException(); } } diff --git a/src/main/java/seedu/duke/UndefinedSubCommandAddTypeException.java b/src/main/java/seedu/duke/UndefinedSubCommandAddTypeException.java index f7d3289cd..955fe51ac 100644 --- a/src/main/java/seedu/duke/UndefinedSubCommandAddTypeException.java +++ b/src/main/java/seedu/duke/UndefinedSubCommandAddTypeException.java @@ -1,4 +1,7 @@ package seedu.duke; +/** + * Represents exception when sub command type required for command add is missing (-property/-client). + */ public class UndefinedSubCommandAddTypeException extends DukeException { } diff --git a/src/main/java/seedu/duke/command/Command.java b/src/main/java/seedu/duke/command/Command.java index cabb89394..1e575e515 100644 --- a/src/main/java/seedu/duke/command/Command.java +++ b/src/main/java/seedu/duke/command/Command.java @@ -5,7 +5,9 @@ import seedu.duke.PropertyList; import seedu.duke.Storage; - +/** + * Represents an executable command. + */ public abstract class Command { public abstract void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList); } diff --git a/src/main/java/seedu/duke/command/CommandAdd.java b/src/main/java/seedu/duke/command/CommandAdd.java index 6c313f63f..e1b3c9b31 100644 --- a/src/main/java/seedu/duke/command/CommandAdd.java +++ b/src/main/java/seedu/duke/command/CommandAdd.java @@ -1,9 +1,7 @@ package seedu.duke.command; -import seedu.duke.ClientList; -import seedu.duke.PropertyList; -import seedu.duke.Storage; -import seedu.duke.Ui; - +/** + * Represents an add-type command. + */ public abstract class CommandAdd extends Command { } diff --git a/src/main/java/seedu/duke/command/CommandAddClient.java b/src/main/java/seedu/duke/command/CommandAddClient.java index 782a0016d..bd834363e 100644 --- a/src/main/java/seedu/duke/command/CommandAddClient.java +++ b/src/main/java/seedu/duke/command/CommandAddClient.java @@ -7,12 +7,20 @@ import java.util.ArrayList; +/** + * Adds a client to the client list. + */ public class CommandAddClient extends CommandAdd { private final String clientName; private final String clientContactNumber; private final String clientEmail; private final String clientBudgetPerMonth; + /** + * Constructs constructor for Command Add Client which stores client's name, contact number, email and budget/month. + * + * @param clientDetails Contains client's name, contact number, email and budget/month. + */ public CommandAddClient(ArrayList clientDetails) { this.clientName = clientDetails.get(0); this.clientContactNumber = clientDetails.get(1); @@ -24,5 +32,6 @@ public CommandAddClient(ArrayList clientDetails) { public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList) { clientList.addClient(clientName, clientContactNumber, clientEmail, clientBudgetPerMonth); ui.showClientAddedConfirmationMessage(clientList); + //Update Storage } } From 0efd452196b8f11dd3c8fd031a354797e1cd3e05 Mon Sep 17 00:00:00 2001 From: ngdeqi Date: Sun, 9 Oct 2022 17:21:36 +0800 Subject: [PATCH 018/325] Put Exceptions into exception class --- src/main/java/seedu/duke/Client.java | 1 + src/main/java/seedu/duke/Duke.java | 1 + src/main/java/seedu/duke/Parser.java | 1 + src/main/java/seedu/duke/{ => exception}/DukeException.java | 2 +- .../duke/{ => exception}/EmptyClientDetailException.java | 2 +- .../duke/{ => exception}/EmptyCommandAddDetailException.java | 2 +- .../{ => exception}/IncorrectAddClientFlagOrderException.java | 2 +- .../duke/{ => exception}/IncorrectFlagOrderException.java | 2 +- .../duke/{ => exception}/InvalidBudgetFormatException.java | 2 +- .../duke/{ => exception}/InvalidContactNumberException.java | 2 +- .../seedu/duke/{ => exception}/InvalidEmailException.java | 2 +- .../duke/{ => exception}/MissingClientDetailException.java | 4 +++- .../duke/{ => exception}/MissingClientFlagException.java | 2 +- .../java/seedu/duke/{ => exception}/MissingFlagException.java | 4 +++- .../{ => exception}/UndefinedSubCommandAddTypeException.java | 4 +++- 15 files changed, 21 insertions(+), 12 deletions(-) rename src/main/java/seedu/duke/{ => exception}/DukeException.java (78%) rename src/main/java/seedu/duke/{ => exception}/EmptyClientDetailException.java (83%) rename src/main/java/seedu/duke/{ => exception}/EmptyCommandAddDetailException.java (84%) rename src/main/java/seedu/duke/{ => exception}/IncorrectAddClientFlagOrderException.java (85%) rename src/main/java/seedu/duke/{ => exception}/IncorrectFlagOrderException.java (82%) rename src/main/java/seedu/duke/{ => exception}/InvalidBudgetFormatException.java (84%) rename src/main/java/seedu/duke/{ => exception}/InvalidContactNumberException.java (85%) rename src/main/java/seedu/duke/{ => exception}/InvalidEmailException.java (83%) rename src/main/java/seedu/duke/{ => exception}/MissingClientDetailException.java (68%) rename src/main/java/seedu/duke/{ => exception}/MissingClientFlagException.java (84%) rename src/main/java/seedu/duke/{ => exception}/MissingFlagException.java (65%) rename src/main/java/seedu/duke/{ => exception}/UndefinedSubCommandAddTypeException.java (71%) diff --git a/src/main/java/seedu/duke/Client.java b/src/main/java/seedu/duke/Client.java index 5d24b44af..5912418b6 100644 --- a/src/main/java/seedu/duke/Client.java +++ b/src/main/java/seedu/duke/Client.java @@ -28,4 +28,5 @@ public String toString() { clientDetails.append(" Budget: SGD" + clientBudgetPerMonth + "/month").append(System.lineSeparator()); return clientDetails.toString().trim(); } + } diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 6e556cffb..debf46ff6 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -2,6 +2,7 @@ import seedu.duke.command.Command; import seedu.duke.command.CommandBye; +import seedu.duke.exception.*; import java.io.IOException; diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index f67eeffe4..300595a32 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -3,6 +3,7 @@ import seedu.duke.command.Command; import seedu.duke.command.CommandAddClient; import seedu.duke.command.CommandUndefined; +import seedu.duke.exception.*; import java.util.ArrayList; import java.util.regex.Matcher; diff --git a/src/main/java/seedu/duke/DukeException.java b/src/main/java/seedu/duke/exception/DukeException.java similarity index 78% rename from src/main/java/seedu/duke/DukeException.java rename to src/main/java/seedu/duke/exception/DukeException.java index 22e6cbcfa..73913a7b4 100644 --- a/src/main/java/seedu/duke/DukeException.java +++ b/src/main/java/seedu/duke/exception/DukeException.java @@ -1,4 +1,4 @@ -package seedu.duke; +package seedu.duke.exception; /** * Represents exceptions local to Duke. diff --git a/src/main/java/seedu/duke/EmptyClientDetailException.java b/src/main/java/seedu/duke/exception/EmptyClientDetailException.java similarity index 83% rename from src/main/java/seedu/duke/EmptyClientDetailException.java rename to src/main/java/seedu/duke/exception/EmptyClientDetailException.java index 8a0f66cb0..c91bf6170 100644 --- a/src/main/java/seedu/duke/EmptyClientDetailException.java +++ b/src/main/java/seedu/duke/exception/EmptyClientDetailException.java @@ -1,4 +1,4 @@ -package seedu.duke; +package seedu.duke.exception; /** * Represents exception when no client description is given when adding client. diff --git a/src/main/java/seedu/duke/EmptyCommandAddDetailException.java b/src/main/java/seedu/duke/exception/EmptyCommandAddDetailException.java similarity index 84% rename from src/main/java/seedu/duke/EmptyCommandAddDetailException.java rename to src/main/java/seedu/duke/exception/EmptyCommandAddDetailException.java index e84242314..f67613046 100644 --- a/src/main/java/seedu/duke/EmptyCommandAddDetailException.java +++ b/src/main/java/seedu/duke/exception/EmptyCommandAddDetailException.java @@ -1,4 +1,4 @@ -package seedu.duke; +package seedu.duke.exception; /** * Represents exception when no information is provided when adding (property/client). diff --git a/src/main/java/seedu/duke/IncorrectAddClientFlagOrderException.java b/src/main/java/seedu/duke/exception/IncorrectAddClientFlagOrderException.java similarity index 85% rename from src/main/java/seedu/duke/IncorrectAddClientFlagOrderException.java rename to src/main/java/seedu/duke/exception/IncorrectAddClientFlagOrderException.java index 6393ec72a..b9828f701 100644 --- a/src/main/java/seedu/duke/IncorrectAddClientFlagOrderException.java +++ b/src/main/java/seedu/duke/exception/IncorrectAddClientFlagOrderException.java @@ -1,4 +1,4 @@ -package seedu.duke; +package seedu.duke.exception; /** * Represents exception when incorrect flag order is given when adding client. diff --git a/src/main/java/seedu/duke/IncorrectFlagOrderException.java b/src/main/java/seedu/duke/exception/IncorrectFlagOrderException.java similarity index 82% rename from src/main/java/seedu/duke/IncorrectFlagOrderException.java rename to src/main/java/seedu/duke/exception/IncorrectFlagOrderException.java index 71c06fc6e..126466270 100644 --- a/src/main/java/seedu/duke/IncorrectFlagOrderException.java +++ b/src/main/java/seedu/duke/exception/IncorrectFlagOrderException.java @@ -1,4 +1,4 @@ -package seedu.duke; +package seedu.duke.exception; /** * Represents exception when incorrect flag order is given by user. diff --git a/src/main/java/seedu/duke/InvalidBudgetFormatException.java b/src/main/java/seedu/duke/exception/InvalidBudgetFormatException.java similarity index 84% rename from src/main/java/seedu/duke/InvalidBudgetFormatException.java rename to src/main/java/seedu/duke/exception/InvalidBudgetFormatException.java index f8300aa2b..64700e957 100644 --- a/src/main/java/seedu/duke/InvalidBudgetFormatException.java +++ b/src/main/java/seedu/duke/exception/InvalidBudgetFormatException.java @@ -1,4 +1,4 @@ -package seedu.duke; +package seedu.duke.exception; /** * Represents exception when incorrect format for budget is given when adding client. diff --git a/src/main/java/seedu/duke/InvalidContactNumberException.java b/src/main/java/seedu/duke/exception/InvalidContactNumberException.java similarity index 85% rename from src/main/java/seedu/duke/InvalidContactNumberException.java rename to src/main/java/seedu/duke/exception/InvalidContactNumberException.java index 284464ce5..9697a892e 100644 --- a/src/main/java/seedu/duke/InvalidContactNumberException.java +++ b/src/main/java/seedu/duke/exception/InvalidContactNumberException.java @@ -1,4 +1,4 @@ -package seedu.duke; +package seedu.duke.exception; /** * Represents exception when incorrect contact number (Singapore) format is given when adding client. diff --git a/src/main/java/seedu/duke/InvalidEmailException.java b/src/main/java/seedu/duke/exception/InvalidEmailException.java similarity index 83% rename from src/main/java/seedu/duke/InvalidEmailException.java rename to src/main/java/seedu/duke/exception/InvalidEmailException.java index f74c26cce..b8419b592 100644 --- a/src/main/java/seedu/duke/InvalidEmailException.java +++ b/src/main/java/seedu/duke/exception/InvalidEmailException.java @@ -1,4 +1,4 @@ -package seedu.duke; +package seedu.duke.exception; /** * Represents exception when incorrect email format is given when adding client. diff --git a/src/main/java/seedu/duke/MissingClientDetailException.java b/src/main/java/seedu/duke/exception/MissingClientDetailException.java similarity index 68% rename from src/main/java/seedu/duke/MissingClientDetailException.java rename to src/main/java/seedu/duke/exception/MissingClientDetailException.java index d9d9fe1e6..478f7cacb 100644 --- a/src/main/java/seedu/duke/MissingClientDetailException.java +++ b/src/main/java/seedu/duke/exception/MissingClientDetailException.java @@ -1,4 +1,6 @@ -package seedu.duke; +package seedu.duke.exception; + +import seedu.duke.exception.DukeException; /** * Represents exception when there is missing client details when adding client. diff --git a/src/main/java/seedu/duke/MissingClientFlagException.java b/src/main/java/seedu/duke/exception/MissingClientFlagException.java similarity index 84% rename from src/main/java/seedu/duke/MissingClientFlagException.java rename to src/main/java/seedu/duke/exception/MissingClientFlagException.java index 140710f4b..c823727d4 100644 --- a/src/main/java/seedu/duke/MissingClientFlagException.java +++ b/src/main/java/seedu/duke/exception/MissingClientFlagException.java @@ -1,4 +1,4 @@ -package seedu.duke; +package seedu.duke.exception; /** * Represents exception when there is missing client flags when adding client. diff --git a/src/main/java/seedu/duke/MissingFlagException.java b/src/main/java/seedu/duke/exception/MissingFlagException.java similarity index 65% rename from src/main/java/seedu/duke/MissingFlagException.java rename to src/main/java/seedu/duke/exception/MissingFlagException.java index 61368864d..527c83242 100644 --- a/src/main/java/seedu/duke/MissingFlagException.java +++ b/src/main/java/seedu/duke/exception/MissingFlagException.java @@ -1,4 +1,6 @@ -package seedu.duke; +package seedu.duke.exception; + +import seedu.duke.exception.DukeException; /** * Represents exception when flags required for command are missing. diff --git a/src/main/java/seedu/duke/UndefinedSubCommandAddTypeException.java b/src/main/java/seedu/duke/exception/UndefinedSubCommandAddTypeException.java similarity index 71% rename from src/main/java/seedu/duke/UndefinedSubCommandAddTypeException.java rename to src/main/java/seedu/duke/exception/UndefinedSubCommandAddTypeException.java index 955fe51ac..b2e7b4ba3 100644 --- a/src/main/java/seedu/duke/UndefinedSubCommandAddTypeException.java +++ b/src/main/java/seedu/duke/exception/UndefinedSubCommandAddTypeException.java @@ -1,4 +1,6 @@ -package seedu.duke; +package seedu.duke.exception; + +import seedu.duke.exception.DukeException; /** * Represents exception when sub command type required for command add is missing (-property/-client). From 7176654836af375470c8e24f09e85905ffb15bf2 Mon Sep 17 00:00:00 2001 From: FeliciaBeatrice Date: Sun, 9 Oct 2022 21:56:57 +0800 Subject: [PATCH 019/325] Created CommandDelete class, Created CommandDeleteClient class, Added deleteClient method to ClientList class --- src/main/java/seedu/duke/ClientList.java | 13 +++++++++++ src/main/java/seedu/duke/Parser.java | 2 +- src/main/java/seedu/duke/Ui.java | 2 ++ .../seedu/duke/command/CommandDelete.java | 7 ++++++ .../duke/command/CommandDeleteClient.java | 23 +++++++++++++++++++ 5 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 src/main/java/seedu/duke/command/CommandDelete.java create mode 100644 src/main/java/seedu/duke/command/CommandDeleteClient.java diff --git a/src/main/java/seedu/duke/ClientList.java b/src/main/java/seedu/duke/ClientList.java index 4c82ca371..6457b992a 100644 --- a/src/main/java/seedu/duke/ClientList.java +++ b/src/main/java/seedu/duke/ClientList.java @@ -35,4 +35,17 @@ public void addClient(String clientName, String clientContactNumber, String clie clientList.add(new Client(clientName, clientContactNumber, clientEmail, clientBudgetPerMonth)); currentListSize++; } + + /** + * Deletes a client from the client list and updates client list size. + * + * @param clientIndex Index of client to be deleted. + * @return Client deleted. + */ + public Client deleteClient(int clientIndex) { + Client deletedClient = clientList.get(clientIndex); + clientList.remove(clientIndex); + currentListSize--; + return deletedClient; + } } diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index f67eeffe4..ae87713ff 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -31,7 +31,7 @@ public Command parseCommand(String input) throws EmptyCommandAddDetailException, } else { throw new UndefinedSubCommandAddTypeException(); } - + case ("delete"): default: return new CommandUndefined(); } diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index 16270a53f..808ad92fa 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -72,4 +72,6 @@ public void showInvalidEmailMessage() { public void showInvalidBudgetFormatMessage() { showToUser(MESSAGE_INVALID_BUDGET_FORMAT); } + + /* Delete Client Related Exceptions */ } diff --git a/src/main/java/seedu/duke/command/CommandDelete.java b/src/main/java/seedu/duke/command/CommandDelete.java new file mode 100644 index 000000000..8670e9886 --- /dev/null +++ b/src/main/java/seedu/duke/command/CommandDelete.java @@ -0,0 +1,7 @@ +package seedu.duke.command; + +/** + * Represents a delete-type command. + */ +public abstract class CommandDelete extends Command { +} diff --git a/src/main/java/seedu/duke/command/CommandDeleteClient.java b/src/main/java/seedu/duke/command/CommandDeleteClient.java new file mode 100644 index 000000000..36ff61370 --- /dev/null +++ b/src/main/java/seedu/duke/command/CommandDeleteClient.java @@ -0,0 +1,23 @@ +package seedu.duke.command; + +import seedu.duke.*; + +import java.util.ArrayList; + +/** + * Deletes a client from the client list. + */ +public class CommandDeleteClient extends CommandDelete { + private final int clientIndex; + + public CommandDeleteClient(int clientIndex) { + this.clientIndex = clientIndex; + } + + @Override + public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList) { + Client deletedClient = clientList.deleteClient(clientIndex); + ui.showClientDeletedConfirmationMessage(deletedClient); + //Update Storage + } +} From 2ddc386534c19dafdf82f013aa4b86e104479629 Mon Sep 17 00:00:00 2001 From: ngdeqi Date: Mon, 10 Oct 2022 08:13:14 +0800 Subject: [PATCH 020/325] Add Pair and Unpair Features and refactoring --- src/main/java/seedu/duke/Client.java | 15 ++ src/main/java/seedu/duke/Duke.java | 18 ++- src/main/java/seedu/duke/Messages.java | 25 +++- src/main/java/seedu/duke/PairingList.java | 43 ++++++ src/main/java/seedu/duke/Parser.java | 135 +++++++++++++++++- src/main/java/seedu/duke/Property.java | 35 +++++ src/main/java/seedu/duke/PropertyList.java | 34 ++++- src/main/java/seedu/duke/Ui.java | 38 +++-- src/main/java/seedu/duke/command/Command.java | 7 +- .../seedu/duke/command/CommandAddClient.java | 5 +- .../java/seedu/duke/command/CommandBye.java | 5 +- .../java/seedu/duke/command/CommandPair.java | 33 +++++ .../seedu/duke/command/CommandUndefined.java | 5 +- .../seedu/duke/command/CommandUnpair.java | 32 +++++ .../duke/exception/AddPairException.java | 4 + ...mptyCommandPairUnpairDetailsException.java | 4 + ...IncorrectPairUnpairFlagOrderException.java | 4 + .../MissingPairUnpairDetailException.java | 4 + .../MissingPairUnpairFlagException.java | 4 + .../duke/exception/NotIntegerException.java | 4 + .../exception/NotValidIndexException.java | 4 + 21 files changed, 434 insertions(+), 24 deletions(-) create mode 100644 src/main/java/seedu/duke/PairingList.java create mode 100644 src/main/java/seedu/duke/command/CommandPair.java create mode 100644 src/main/java/seedu/duke/command/CommandUnpair.java create mode 100644 src/main/java/seedu/duke/exception/AddPairException.java create mode 100644 src/main/java/seedu/duke/exception/EmptyCommandPairUnpairDetailsException.java create mode 100644 src/main/java/seedu/duke/exception/IncorrectPairUnpairFlagOrderException.java create mode 100644 src/main/java/seedu/duke/exception/MissingPairUnpairDetailException.java create mode 100644 src/main/java/seedu/duke/exception/MissingPairUnpairFlagException.java create mode 100644 src/main/java/seedu/duke/exception/NotIntegerException.java create mode 100644 src/main/java/seedu/duke/exception/NotValidIndexException.java diff --git a/src/main/java/seedu/duke/Client.java b/src/main/java/seedu/duke/Client.java index 5912418b6..ac3a90762 100644 --- a/src/main/java/seedu/duke/Client.java +++ b/src/main/java/seedu/duke/Client.java @@ -29,4 +29,19 @@ public String toString() { return clientDetails.toString().trim(); } + public String getClientName() { + return clientName; + } + + public String getClientContactNumber() { + return clientContactNumber; + } + + public String getClientEmail() { + return clientEmail; + } + + public String getClientBudgetPerMonth() { + return clientBudgetPerMonth; + } } diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index debf46ff6..f9b8ff863 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -12,23 +12,27 @@ public class Duke { private Storage storage; private PropertyList propertyList; private ClientList clientList; + private PairingList pairingList; public void run() throws IOException { - this.parser = new Parser(); this.ui = new Ui(); this.storage = new Storage(); this.propertyList = new PropertyList(); this.clientList = new ClientList(); + this.parser = new Parser(clientList, propertyList); + this.pairingList = new PairingList(); Command command; boolean isCommandBye = false; + ui.showWelcomeMessage(); + do { try { String userInputText = ui.readCommand(); command = parser.parseCommand(userInputText); - command.execute(ui, storage, propertyList, clientList); + command.execute(ui, storage, propertyList, clientList, pairingList); isCommandBye = (command instanceof CommandBye); } catch (EmptyCommandAddDetailException e) { ui.showMissingCommandAddDetailMessage(); @@ -37,7 +41,7 @@ public void run() throws IOException { } catch (EmptyClientDetailException e) { ui.showEmptyClientDetailMessage(); } catch (MissingClientFlagException | IncorrectAddClientFlagOrderException - | MissingClientDetailException e) { + | MissingClientDetailException e) { ui.showAddClientWrongFormatMessage(); } catch (InvalidContactNumberException e) { ui.showInvalidContactNumberMessage(); @@ -45,6 +49,14 @@ public void run() throws IOException { ui.showInvalidEmailMessage(); } catch (InvalidBudgetFormatException e) { ui.showInvalidBudgetFormatMessage(); + } catch (EmptyCommandPairUnpairDetailsException e) { + ui.showEmptyCommandPairUnpairDetailsMessage(); + } catch (MissingPairUnpairFlagException | IncorrectPairUnpairFlagOrderException e) { + ui.showPairUnpairWrongFormatMessage(); + } catch (NotValidIndexException e) { + ui.showNotValidIndexMessage(); + } catch (NotIntegerException e) { + ui.showNotIntegerMessage(); } } while (!isCommandBye); } diff --git a/src/main/java/seedu/duke/Messages.java b/src/main/java/seedu/duke/Messages.java index d9c8ede50..3d9eaa420 100644 --- a/src/main/java/seedu/duke/Messages.java +++ b/src/main/java/seedu/duke/Messages.java @@ -1,9 +1,10 @@ package seedu.duke; - /** * Container for user visible messages. */ public class Messages { + public static final String MESSAGE_WELCOME = "Welcome to Property Manager! How may I help you?"; + public static final String MESSAGE_CLIENT_ADDED = "Adding a client with the following information:"; public static final String MESSAGE_EMPTY_ADD_DESCRIPTION = "OOPS!!! The description for add cannot be empty."; @@ -32,4 +33,26 @@ public class Messages { public static final String MESSAGE_INVALID_BUDGET_FORMAT = "OOPS!!! Please enter positive number " + "(No letter/symbols, etc) for budget"; + + public static final String MESSAGE_PAIRED = "Pairing the following client and property: "; + + public static final String MESSAGE_EMPTY_COMMAND_PAIR_UNPAIR = "OOPS!!! The description of a pair/unpair message " + + "cannot be empty"; + + public static final String MESSAGE_NOT_VALID_INDEX = "OOPS!!! Please enter an index that appears within the " + + "property list or client list"; + + public static final String MESSAGE_NOT_INTEGER = "OOPS!!! Please enter an integer"; + + public static final String MESSAGE_PAIR_UNPAIR_WRONG_FORMAT = "OOPS!!! To pair or unpair, it requires " + + "the following format and details as shown below."; + + public static final String MESSAGE_PAIR_UNPAIR_INPUT_EXAMPLE = "Format:\n" + + " pair ip/PROPERTY_INDEX ic/CLIENT_INDEX\n" + + " unpair ip/PROPERTY_INDEX ic/CLIENT_INDEX\n" + + "Examples:\n" + + " pair ip/1 ic/5\n" + + " unpair ip/2 ic/1"; + + } diff --git a/src/main/java/seedu/duke/PairingList.java b/src/main/java/seedu/duke/PairingList.java new file mode 100644 index 000000000..f24a10bc2 --- /dev/null +++ b/src/main/java/seedu/duke/PairingList.java @@ -0,0 +1,43 @@ +package seedu.duke; + +import java.util.HashMap; + +public class PairingList { + private static final String SEPARATOR = " | "; + + private static final HashMap clientPropertyPairs = new HashMap<>(); + + public PairingList() { + + } + + public void addPairing(Client client, Property property) { + String clientPairingData = convertToPairingData(client); + String propertyPairingData = convertToPairingData(property); + + clientPropertyPairs.put(clientPairingData, propertyPairingData); + } + + public void deletePairing(Client client, Property property) { + + String clientPairingData = convertToPairingData(client); + String propertyPairingData = convertToPairingData(property); + + clientPropertyPairs.remove(clientPairingData, propertyPairingData); + } + + private String convertToPairingData(Client client) { + return client.getClientName() + SEPARATOR + client.getClientContactNumber(); + } + + private String convertToPairingData(Property property) { + return property.getLandlordName() + + SEPARATOR + + property.getPropertyAddress() + + SEPARATOR + + property.getRentingPrice() + + SEPARATOR + + property.getUnitType(); + } + +} diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 300595a32..8baa5b5ff 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -2,8 +2,25 @@ import seedu.duke.command.Command; import seedu.duke.command.CommandAddClient; +import seedu.duke.command.CommandPair; +import seedu.duke.command.CommandUnpair; import seedu.duke.command.CommandUndefined; -import seedu.duke.exception.*; +import seedu.duke.exception.EmptyClientDetailException; +import seedu.duke.exception.EmptyCommandAddDetailException; +import seedu.duke.exception.EmptyCommandPairUnpairDetailsException; +import seedu.duke.exception.IncorrectAddClientFlagOrderException; +import seedu.duke.exception.IncorrectFlagOrderException; +import seedu.duke.exception.IncorrectPairUnpairFlagOrderException; +import seedu.duke.exception.InvalidBudgetFormatException; +import seedu.duke.exception.InvalidContactNumberException; +import seedu.duke.exception.InvalidEmailException; +import seedu.duke.exception.MissingClientDetailException; +import seedu.duke.exception.MissingClientFlagException; +import seedu.duke.exception.MissingFlagException; +import seedu.duke.exception.MissingPairUnpairFlagException; +import seedu.duke.exception.NotIntegerException; +import seedu.duke.exception.NotValidIndexException; +import seedu.duke.exception.UndefinedSubCommandAddTypeException; import java.util.ArrayList; import java.util.regex.Matcher; @@ -11,17 +28,28 @@ public class Parser { + private static ClientList clientList; + private static PropertyList propertyList; + public static final int ADD_CLIENT_FLAG_SIZE = 4; + public static final int PAIR_UNPAIR_FLAG_SIZE = 2; + + public Parser(ClientList cl, PropertyList pl) { + clientList = cl; + propertyList = pl; + } public Command parseCommand(String input) throws EmptyCommandAddDetailException, UndefinedSubCommandAddTypeException, EmptyClientDetailException, MissingClientFlagException, IncorrectAddClientFlagOrderException, MissingClientDetailException, InvalidContactNumberException, - InvalidEmailException, InvalidBudgetFormatException { + InvalidEmailException, InvalidBudgetFormatException, EmptyCommandPairUnpairDetailsException, + MissingPairUnpairFlagException, IncorrectPairUnpairFlagOrderException, NotValidIndexException, + NotIntegerException { ArrayList processedCommandDetails = partitionCommandTypeAndDetails(input); String commandType = processedCommandDetails.get(0); String commandDetails = processedCommandDetails.get(1); switch (commandType) { - case ("add"): + case "add": checkForEmptyCommandAddDetails(commandDetails); ArrayList processedAddCommandDetails = partitionCommandTypeAndDetails(commandDetails); String subCommandType = processedAddCommandDetails.get(0); @@ -32,6 +60,12 @@ public Command parseCommand(String input) throws EmptyCommandAddDetailException, } else { throw new UndefinedSubCommandAddTypeException(); } + case "pair": + checkForEmptyCommandPairUnpairDetails(commandDetails); + return prepareForCommandPair(commandDetails); + case "unpair": + checkForEmptyCommandPairUnpairDetails(commandDetails); + return prepareForCommandUnpair(commandDetails); default: return new CommandUndefined(); @@ -216,4 +250,99 @@ private static String extractDetail(String rawClientDetails, int beginIndex, int private boolean checkForEmptyDetail(String commandDetails) { return commandDetails.trim().isEmpty(); } + + private void checkForEmptyCommandPairUnpairDetails(String commandPairUnpairDetails) + throws EmptyCommandPairUnpairDetailsException { + boolean isEmptyCommandPairUnpairDetail = checkForEmptyDetail(commandPairUnpairDetails); + if (isEmptyCommandPairUnpairDetail) { + throw new EmptyCommandPairUnpairDetailsException(); + } + } + + private Command prepareForCommandPair(String rawPairDescriptions) throws NotIntegerException, + NotValidIndexException, MissingPairUnpairFlagException, IncorrectPairUnpairFlagOrderException { + + ArrayList pairDetails = processPairUnpairDetails(rawPairDescriptions); + validatePairUnpairDetails(pairDetails); + return new CommandPair(pairDetails); + } + + private Command prepareForCommandUnpair(String rawUnpairDescriptions) throws NotIntegerException, + NotValidIndexException, MissingPairUnpairFlagException, IncorrectPairUnpairFlagOrderException { + + ArrayList unpairDetails = processPairUnpairDetails(rawUnpairDescriptions); + validatePairUnpairDetails(unpairDetails); + return new CommandUnpair(unpairDetails); + } + + private ArrayList processPairUnpairDetails(String rawPairUnpairDetails) + throws MissingPairUnpairFlagException, IncorrectPairUnpairFlagOrderException, NotIntegerException { + String[] pairUnpairFlags = {"ip/", "ic/"}; + int[] pairUnpairFlagIndexPositions = new int[PAIR_UNPAIR_FLAG_SIZE]; + + for (int i = 0; i < pairUnpairFlags.length; i++) { + pairUnpairFlagIndexPositions[i] = rawPairUnpairDetails.indexOf(pairUnpairFlags[i]); + } + + checkForMissingPairUnpairFlags(pairUnpairFlagIndexPositions); + checkForPairUnpairFlagsOrder(pairUnpairFlagIndexPositions); + return extractPairUnpairDetails(rawPairUnpairDetails, pairUnpairFlagIndexPositions, pairUnpairFlags); + } + + + private void checkForMissingPairUnpairFlags(int[] pairUnpairFlagIndexPosition) + throws MissingPairUnpairFlagException { + try { + for (int flagIndex : pairUnpairFlagIndexPosition) { + checkForEssentialAddFlag(flagIndex); + } + } catch (MissingFlagException e) { + throw new MissingPairUnpairFlagException(); + } + } + + private void checkForPairUnpairFlagsOrder(int[] PairUnpairFlagIndexPosition) + throws IncorrectPairUnpairFlagOrderException { + try { + checkForCorrectFlagOrder(PairUnpairFlagIndexPosition[0], PairUnpairFlagIndexPosition[1]); + } catch (IncorrectFlagOrderException e) { + throw new IncorrectPairUnpairFlagOrderException(); + } + } + + private ArrayList extractPairUnpairDetails(String rawPairUnpairDetails, int[] pairFlagIndexPositions, + String[] pairUnpairFlags) throws NotIntegerException { + String propertyIndexString = extractDetail(rawPairUnpairDetails, + pairFlagIndexPositions[0] + pairUnpairFlags[0].length(), + pairFlagIndexPositions[1]); + + String clientIndexString = extractDetail(rawPairUnpairDetails, + pairFlagIndexPositions[1] + pairUnpairFlags[1].length()); + + int propertyIndex; + int clientIndex; + + try { + propertyIndex = Integer.parseInt(propertyIndexString); + clientIndex = Integer.parseInt(clientIndexString); + } catch (NumberFormatException e) { + throw new NotIntegerException(); + } + + ArrayList processedPairUnpairDetails = new ArrayList<>(); + processedPairUnpairDetails.add(clientIndex - 1); + processedPairUnpairDetails.add(propertyIndex - 1); + return processedPairUnpairDetails; + } + + private void validatePairUnpairDetails(ArrayList pairUnpairDetails) throws NotValidIndexException { + int clientIndex = pairUnpairDetails.get(0); + int propertyIndex = pairUnpairDetails.get(1); + + if (clientIndex < 0 || clientIndex > clientList.getCurrentListSize() - 1 || + propertyIndex < 0 || propertyIndex > propertyList.getCurrentListSize() - 1) { + throw new NotValidIndexException(); + } + } + } diff --git a/src/main/java/seedu/duke/Property.java b/src/main/java/seedu/duke/Property.java index 09e562999..f48f041b7 100644 --- a/src/main/java/seedu/duke/Property.java +++ b/src/main/java/seedu/duke/Property.java @@ -1,4 +1,39 @@ package seedu.duke; public class Property { + private String landlordName; + private String propertyAddress; + private String rentingPrice; + private String unitType; + + public Property(String landlordName, String propertyAddress, String rentingPrice, String unitType) { + this.landlordName = landlordName; + this.propertyAddress = propertyAddress; + this.rentingPrice = rentingPrice; + this.unitType = unitType; + } + + public String toString() { + String propertyDetails = " Landlord: " + landlordName + System.lineSeparator() + + " Address: " + propertyAddress + System.lineSeparator() + + " Renting Price: SGD" + rentingPrice + "/month" + System.lineSeparator() + + " Unit Type: " + unitType + System.lineSeparator(); + return propertyDetails.trim(); + } + + public String getLandlordName() { + return landlordName; + } + + public String getPropertyAddress() { + return propertyAddress; + } + + public String getRentingPrice() { + return rentingPrice; + } + + public String getUnitType() { + return unitType; + } } diff --git a/src/main/java/seedu/duke/PropertyList.java b/src/main/java/seedu/duke/PropertyList.java index aca4419c0..95124184e 100644 --- a/src/main/java/seedu/duke/PropertyList.java +++ b/src/main/java/seedu/duke/PropertyList.java @@ -2,6 +2,36 @@ import java.util.ArrayList; +/** + * Stores the list of properties. + */ public class PropertyList { - protected static ArrayList properties = new ArrayList<>(); -} + private static int currentListSize; + private static ArrayList propertyList; + + public PropertyList() { + propertyList = new ArrayList<>(); + currentListSize = 0; + } + + public int getCurrentListSize() { + return currentListSize; + } + + public ArrayList getPropertyList() { + return propertyList; + } + + /** + * Adds a property to property list and updates property list size. + * + * @param landlordName Name of landlord of property. + * @param propertyAddress Address of property. + * @param rentingPrice Renting price per month for property. + * @param unitType Unit type of property. + */ + public void addProperty(String landlordName, String propertyAddress, String rentingPrice, String unitType) { + propertyList.add(new Property(landlordName, propertyAddress, rentingPrice, unitType)); + currentListSize++; + } +} \ No newline at end of file diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index 16270a53f..404478380 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -2,16 +2,7 @@ import java.util.Scanner; -import static seedu.duke.Messages.MESSAGE_CLIENT_ADDED; -import static seedu.duke.Messages.MESSAGE_EMPTY_ADD_DESCRIPTION; -import static seedu.duke.Messages.MESSAGE_MISSING_SUB_COMMAND_TYPE_FOR_ADD; -import static seedu.duke.Messages.MESSAGE_EMPTY_CLIENT_DESCRIPTION; -import static seedu.duke.Messages.MESSAGE_ADD_CLIENT_WRONG_FORMAT; -import static seedu.duke.Messages.MESSAGE_CLIENT_INPUT_EXAMPLE; -import static seedu.duke.Messages.MESSAGE_TRY_AGAIN; -import static seedu.duke.Messages.MESSAGE_INVALID_CONTACT_NUMBER; -import static seedu.duke.Messages.MESSAGE_INVALID_EMAIL; -import static seedu.duke.Messages.MESSAGE_INVALID_BUDGET_FORMAT; +import static seedu.duke.Messages.*; public class Ui { @@ -36,6 +27,10 @@ public void showToUser(String message) { System.out.println(message); } + public void showWelcomeMessage() { + showToUser(MESSAGE_WELCOME); + } + public void showClientAddedConfirmationMessage(ClientList clientList) { int currentListSize = clientList.getCurrentListSize(); showToUser(MESSAGE_CLIENT_ADDED); @@ -72,4 +67,27 @@ public void showInvalidEmailMessage() { public void showInvalidBudgetFormatMessage() { showToUser(MESSAGE_INVALID_BUDGET_FORMAT); } + + public void showPairedConfirmationMessage(Client client, Property property) { + showToUser(MESSAGE_PAIRED); + showToUser(" " + client.getClientName() + " and " + property.getPropertyAddress()); + } + + public void showEmptyCommandPairUnpairDetailsMessage() { + showToUser(MESSAGE_EMPTY_COMMAND_PAIR_UNPAIR); + } + + public void showNotValidIndexMessage() { + showToUser(MESSAGE_NOT_VALID_INDEX); + } + + public void showNotIntegerMessage() { + showToUser(MESSAGE_NOT_INTEGER); + } + + public void showPairUnpairWrongFormatMessage() { + showToUser(MESSAGE_PAIR_UNPAIR_WRONG_FORMAT); + showToUser(MESSAGE_PAIR_UNPAIR_INPUT_EXAMPLE); + showToUser(MESSAGE_TRY_AGAIN); + } } diff --git a/src/main/java/seedu/duke/command/Command.java b/src/main/java/seedu/duke/command/Command.java index 1e575e515..46810ce4a 100644 --- a/src/main/java/seedu/duke/command/Command.java +++ b/src/main/java/seedu/duke/command/Command.java @@ -1,13 +1,16 @@ package seedu.duke.command; -import seedu.duke.Ui; + import seedu.duke.ClientList; +import seedu.duke.PairingList; import seedu.duke.PropertyList; import seedu.duke.Storage; +import seedu.duke.Ui; /** * Represents an executable command. */ public abstract class Command { - public abstract void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList); + public abstract void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, + PairingList pairingList); } diff --git a/src/main/java/seedu/duke/command/CommandAddClient.java b/src/main/java/seedu/duke/command/CommandAddClient.java index bd834363e..87b647100 100644 --- a/src/main/java/seedu/duke/command/CommandAddClient.java +++ b/src/main/java/seedu/duke/command/CommandAddClient.java @@ -1,6 +1,8 @@ package seedu.duke.command; + import seedu.duke.ClientList; +import seedu.duke.PairingList; import seedu.duke.PropertyList; import seedu.duke.Storage; import seedu.duke.Ui; @@ -29,7 +31,8 @@ public CommandAddClient(ArrayList clientDetails) { } @Override - public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList) { + public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, + PairingList pairingList) { clientList.addClient(clientName, clientContactNumber, clientEmail, clientBudgetPerMonth); ui.showClientAddedConfirmationMessage(clientList); //Update Storage diff --git a/src/main/java/seedu/duke/command/CommandBye.java b/src/main/java/seedu/duke/command/CommandBye.java index 89efbc0b0..79d6f6715 100644 --- a/src/main/java/seedu/duke/command/CommandBye.java +++ b/src/main/java/seedu/duke/command/CommandBye.java @@ -1,13 +1,16 @@ package seedu.duke.command; + import seedu.duke.ClientList; +import seedu.duke.PairingList; import seedu.duke.PropertyList; import seedu.duke.Storage; import seedu.duke.Ui; public class CommandBye extends Command { + @Override - public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList) { + public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, PairingList pairingList) { //print bye message } } diff --git a/src/main/java/seedu/duke/command/CommandPair.java b/src/main/java/seedu/duke/command/CommandPair.java new file mode 100644 index 000000000..dc801c250 --- /dev/null +++ b/src/main/java/seedu/duke/command/CommandPair.java @@ -0,0 +1,33 @@ +package seedu.duke.command; + + +import seedu.duke.Client; +import seedu.duke.ClientList; +import seedu.duke.PairingList; +import seedu.duke.Property; +import seedu.duke.PropertyList; +import seedu.duke.Storage; +import seedu.duke.Ui; + +import java.util.ArrayList; + +public class CommandPair extends Command { + + private int clientIndex; + private int propertyIndex; + + public CommandPair(ArrayList commandPairDetails) { + this.clientIndex = commandPairDetails.get(0); + this.propertyIndex = commandPairDetails.get(1); + } + + @Override + public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, + PairingList pairingList) { + Client client = clientList.getClientList().get(clientIndex); + Property property = propertyList.getPropertyList().get(propertyIndex); + + pairingList.addPairing(client, property); + ui.showPairedConfirmationMessage(client, property); + } +} diff --git a/src/main/java/seedu/duke/command/CommandUndefined.java b/src/main/java/seedu/duke/command/CommandUndefined.java index aee798ebf..00dab02b8 100644 --- a/src/main/java/seedu/duke/command/CommandUndefined.java +++ b/src/main/java/seedu/duke/command/CommandUndefined.java @@ -1,13 +1,16 @@ package seedu.duke.command; + import seedu.duke.ClientList; +import seedu.duke.PairingList; import seedu.duke.PropertyList; import seedu.duke.Storage; import seedu.duke.Ui; public class CommandUndefined extends Command { @Override - public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList) { + public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, + PairingList pairingList) { //showCommandUndefinedMessage } } diff --git a/src/main/java/seedu/duke/command/CommandUnpair.java b/src/main/java/seedu/duke/command/CommandUnpair.java new file mode 100644 index 000000000..92cca1355 --- /dev/null +++ b/src/main/java/seedu/duke/command/CommandUnpair.java @@ -0,0 +1,32 @@ +package seedu.duke.command; + + +import seedu.duke.Client; +import seedu.duke.ClientList; +import seedu.duke.PairingList; +import seedu.duke.Property; +import seedu.duke.PropertyList; +import seedu.duke.Storage; +import seedu.duke.Ui; + +import java.util.ArrayList; + +public class CommandUnpair extends Command { + + private int clientIndex; + private int propertyIndex; + + public CommandUnpair(ArrayList commandUnpairDetails) { + this.clientIndex = commandUnpairDetails.get(0); + this.propertyIndex = commandUnpairDetails.get(1); + } + + @Override + public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, + PairingList pairingList) { + Client client = clientList.getClientList().get(clientIndex); + Property property = propertyList.getPropertyList().get(propertyIndex); + + pairingList.deletePairing(client, property); + } +} diff --git a/src/main/java/seedu/duke/exception/AddPairException.java b/src/main/java/seedu/duke/exception/AddPairException.java new file mode 100644 index 000000000..0d1f5c2a3 --- /dev/null +++ b/src/main/java/seedu/duke/exception/AddPairException.java @@ -0,0 +1,4 @@ +package seedu.duke.exception; + +public class AddPairException extends DukeException{ +} diff --git a/src/main/java/seedu/duke/exception/EmptyCommandPairUnpairDetailsException.java b/src/main/java/seedu/duke/exception/EmptyCommandPairUnpairDetailsException.java new file mode 100644 index 000000000..4b23cc0cf --- /dev/null +++ b/src/main/java/seedu/duke/exception/EmptyCommandPairUnpairDetailsException.java @@ -0,0 +1,4 @@ +package seedu.duke.exception; + +public class EmptyCommandPairUnpairDetailsException extends DukeException { +} diff --git a/src/main/java/seedu/duke/exception/IncorrectPairUnpairFlagOrderException.java b/src/main/java/seedu/duke/exception/IncorrectPairUnpairFlagOrderException.java new file mode 100644 index 000000000..73aaa75e2 --- /dev/null +++ b/src/main/java/seedu/duke/exception/IncorrectPairUnpairFlagOrderException.java @@ -0,0 +1,4 @@ +package seedu.duke.exception; + +public class IncorrectPairUnpairFlagOrderException extends IncorrectFlagOrderException { +} diff --git a/src/main/java/seedu/duke/exception/MissingPairUnpairDetailException.java b/src/main/java/seedu/duke/exception/MissingPairUnpairDetailException.java new file mode 100644 index 000000000..7ac5f38ff --- /dev/null +++ b/src/main/java/seedu/duke/exception/MissingPairUnpairDetailException.java @@ -0,0 +1,4 @@ +package seedu.duke.exception; + +public class MissingPairUnpairDetailException extends MissingFlagException { +} diff --git a/src/main/java/seedu/duke/exception/MissingPairUnpairFlagException.java b/src/main/java/seedu/duke/exception/MissingPairUnpairFlagException.java new file mode 100644 index 000000000..403421e9a --- /dev/null +++ b/src/main/java/seedu/duke/exception/MissingPairUnpairFlagException.java @@ -0,0 +1,4 @@ +package seedu.duke.exception; + +public class MissingPairUnpairFlagException extends MissingFlagException{ +} diff --git a/src/main/java/seedu/duke/exception/NotIntegerException.java b/src/main/java/seedu/duke/exception/NotIntegerException.java new file mode 100644 index 000000000..7ba93e1f5 --- /dev/null +++ b/src/main/java/seedu/duke/exception/NotIntegerException.java @@ -0,0 +1,4 @@ +package seedu.duke.exception; + +public class NotIntegerException extends DukeException { +} diff --git a/src/main/java/seedu/duke/exception/NotValidIndexException.java b/src/main/java/seedu/duke/exception/NotValidIndexException.java new file mode 100644 index 000000000..464bf15a6 --- /dev/null +++ b/src/main/java/seedu/duke/exception/NotValidIndexException.java @@ -0,0 +1,4 @@ +package seedu.duke.exception; + +public class NotValidIndexException extends DukeException { +} From 12323aff272742f53f2ad78574cdd73a43e9b58f Mon Sep 17 00:00:00 2001 From: ngdeqi Date: Mon, 10 Oct 2022 08:19:38 +0800 Subject: [PATCH 021/325] Remove wildcard imports --- src/main/java/seedu/duke/Duke.java | 15 ++++++++++++++- src/main/java/seedu/duke/Ui.java | 20 ++++++++++++++++++-- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index f9b8ff863..f0f170245 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -2,7 +2,20 @@ import seedu.duke.command.Command; import seedu.duke.command.CommandBye; -import seedu.duke.exception.*; +import seedu.duke.exception.EmptyClientDetailException; +import seedu.duke.exception.EmptyCommandAddDetailException; +import seedu.duke.exception.EmptyCommandPairUnpairDetailsException; +import seedu.duke.exception.IncorrectAddClientFlagOrderException; +import seedu.duke.exception.IncorrectPairUnpairFlagOrderException; +import seedu.duke.exception.InvalidBudgetFormatException; +import seedu.duke.exception.InvalidContactNumberException; +import seedu.duke.exception.InvalidEmailException; +import seedu.duke.exception.MissingClientDetailException; +import seedu.duke.exception.MissingClientFlagException; +import seedu.duke.exception.MissingPairUnpairFlagException; +import seedu.duke.exception.NotIntegerException; +import seedu.duke.exception.NotValidIndexException; +import seedu.duke.exception.UndefinedSubCommandAddTypeException; import java.io.IOException; diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index 404478380..8a80c0477 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -2,7 +2,23 @@ import java.util.Scanner; -import static seedu.duke.Messages.*; +import static seedu.duke.Messages.MESSAGE_ADD_CLIENT_WRONG_FORMAT; +import static seedu.duke.Messages.MESSAGE_CLIENT_ADDED; +import static seedu.duke.Messages.MESSAGE_CLIENT_INPUT_EXAMPLE; +import static seedu.duke.Messages.MESSAGE_EMPTY_ADD_DESCRIPTION; +import static seedu.duke.Messages.MESSAGE_EMPTY_CLIENT_DESCRIPTION; +import static seedu.duke.Messages.MESSAGE_EMPTY_COMMAND_PAIR_UNPAIR; +import static seedu.duke.Messages.MESSAGE_INVALID_BUDGET_FORMAT; +import static seedu.duke.Messages.MESSAGE_INVALID_CONTACT_NUMBER; +import static seedu.duke.Messages.MESSAGE_INVALID_EMAIL; +import static seedu.duke.Messages.MESSAGE_MISSING_SUB_COMMAND_TYPE_FOR_ADD; +import static seedu.duke.Messages.MESSAGE_NOT_INTEGER; +import static seedu.duke.Messages.MESSAGE_NOT_VALID_INDEX; +import static seedu.duke.Messages.MESSAGE_PAIR_UNPAIR_INPUT_EXAMPLE; +import static seedu.duke.Messages.MESSAGE_PAIR_UNPAIR_WRONG_FORMAT; +import static seedu.duke.Messages.MESSAGE_TRY_AGAIN; +import static seedu.duke.Messages.MESSAGE_WELCOME; + public class Ui { @@ -69,7 +85,7 @@ public void showInvalidBudgetFormatMessage() { } public void showPairedConfirmationMessage(Client client, Property property) { - showToUser(MESSAGE_PAIRED); + showToUser(Messages.MESSAGE_PAIRED); showToUser(" " + client.getClientName() + " and " + property.getPropertyAddress()); } From 637ee246e767773c2986c226b410f00c6830c7f8 Mon Sep 17 00:00:00 2001 From: ngdeqi Date: Mon, 10 Oct 2022 08:32:55 +0800 Subject: [PATCH 022/325] Fix coding standard violations --- src/main/java/seedu/duke/Messages.java | 3 +-- src/main/java/seedu/duke/PairingList.java | 2 +- src/main/java/seedu/duke/Parser.java | 15 +++++++-------- src/main/java/seedu/duke/command/CommandBye.java | 3 ++- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/main/java/seedu/duke/Messages.java b/src/main/java/seedu/duke/Messages.java index 3d9eaa420..548da3175 100644 --- a/src/main/java/seedu/duke/Messages.java +++ b/src/main/java/seedu/duke/Messages.java @@ -1,4 +1,5 @@ package seedu.duke; + /** * Container for user visible messages. */ @@ -53,6 +54,4 @@ public class Messages { + "Examples:\n" + " pair ip/1 ic/5\n" + " unpair ip/2 ic/1"; - - } diff --git a/src/main/java/seedu/duke/PairingList.java b/src/main/java/seedu/duke/PairingList.java index f24a10bc2..74d4373ae 100644 --- a/src/main/java/seedu/duke/PairingList.java +++ b/src/main/java/seedu/duke/PairingList.java @@ -23,7 +23,7 @@ public void deletePairing(Client client, Property property) { String clientPairingData = convertToPairingData(client); String propertyPairingData = convertToPairingData(property); - clientPropertyPairs.remove(clientPairingData, propertyPairingData); + clientPropertyPairs.remove(clientPairingData, propertyPairingData); } private String convertToPairingData(Client client) { diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 8baa5b5ff..054838e78 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -261,10 +261,9 @@ private void checkForEmptyCommandPairUnpairDetails(String commandPairUnpairDetai private Command prepareForCommandPair(String rawPairDescriptions) throws NotIntegerException, NotValidIndexException, MissingPairUnpairFlagException, IncorrectPairUnpairFlagOrderException { - - ArrayList pairDetails = processPairUnpairDetails(rawPairDescriptions); - validatePairUnpairDetails(pairDetails); - return new CommandPair(pairDetails); + ArrayList pairDetails = processPairUnpairDetails(rawPairDescriptions); + validatePairUnpairDetails(pairDetails); + return new CommandPair(pairDetails); } private Command prepareForCommandUnpair(String rawUnpairDescriptions) throws NotIntegerException, @@ -301,10 +300,10 @@ private void checkForMissingPairUnpairFlags(int[] pairUnpairFlagIndexPosition) } } - private void checkForPairUnpairFlagsOrder(int[] PairUnpairFlagIndexPosition) + private void checkForPairUnpairFlagsOrder(int[] pairUnpairFlagIndexPosition) throws IncorrectPairUnpairFlagOrderException { try { - checkForCorrectFlagOrder(PairUnpairFlagIndexPosition[0], PairUnpairFlagIndexPosition[1]); + checkForCorrectFlagOrder(pairUnpairFlagIndexPosition[0], pairUnpairFlagIndexPosition[1]); } catch (IncorrectFlagOrderException e) { throw new IncorrectPairUnpairFlagOrderException(); } @@ -339,8 +338,8 @@ private void validatePairUnpairDetails(ArrayList pairUnpairDetails) thr int clientIndex = pairUnpairDetails.get(0); int propertyIndex = pairUnpairDetails.get(1); - if (clientIndex < 0 || clientIndex > clientList.getCurrentListSize() - 1 || - propertyIndex < 0 || propertyIndex > propertyList.getCurrentListSize() - 1) { + if (clientIndex < 0 || clientIndex > clientList.getCurrentListSize() - 1 + || propertyIndex < 0 || propertyIndex > propertyList.getCurrentListSize() - 1) { throw new NotValidIndexException(); } } diff --git a/src/main/java/seedu/duke/command/CommandBye.java b/src/main/java/seedu/duke/command/CommandBye.java index 79d6f6715..7f5949f7a 100644 --- a/src/main/java/seedu/duke/command/CommandBye.java +++ b/src/main/java/seedu/duke/command/CommandBye.java @@ -10,7 +10,8 @@ public class CommandBye extends Command { @Override - public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, PairingList pairingList) { + public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, + PairingList pairingList) { //print bye message } } From 38517e98800ae87c01d8d5cb9b5b39f974b9ace9 Mon Sep 17 00:00:00 2001 From: ngdeqi Date: Mon, 10 Oct 2022 08:38:45 +0800 Subject: [PATCH 023/325] Fix CI failure --- text-ui-test/input.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index f6ec2e9f9..e69de29bb 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -1 +0,0 @@ -James Gosling \ No newline at end of file From fa047da3a88a91a34ea623837ddd301748033ede Mon Sep 17 00:00:00 2001 From: ngdeqi Date: Mon, 10 Oct 2022 08:43:15 +0800 Subject: [PATCH 024/325] Fx CI failure --- src/main/java/seedu/duke/Duke.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index f0f170245..445165d82 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -43,6 +43,7 @@ public void run() throws IOException { do { try { + System.exit(0); //to pass CI String userInputText = ui.readCommand(); command = parser.parseCommand(userInputText); command.execute(ui, storage, propertyList, clientList, pairingList); From 278b6fe815e36f012b4c9a50c70528026564fe34 Mon Sep 17 00:00:00 2001 From: ngdeqi Date: Mon, 10 Oct 2022 08:45:31 +0800 Subject: [PATCH 025/325] Fix CI failure --- text-ui-test/EXPECTED.TXT | 1 + 1 file changed, 1 insertion(+) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index e69de29bb..394794b12 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -0,0 +1 @@ +Welcome to Property Manager! How may I help you? \ No newline at end of file From 533241d2815b93b1b23d91aa1737155f38b995db Mon Sep 17 00:00:00 2001 From: ngdeqi Date: Mon, 10 Oct 2022 08:47:05 +0800 Subject: [PATCH 026/325] Fix CI failure --- text-ui-test/EXPECTED.TXT | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 394794b12..344dc6ee7 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1 +1 @@ -Welcome to Property Manager! How may I help you? \ No newline at end of file +Welcome to Property Manager! How may I help you? From 65f280652cfa87475a3ee9e54c9d8fb693801e8d Mon Sep 17 00:00:00 2001 From: FeliciaBeatrice Date: Mon, 10 Oct 2022 10:51:20 +0800 Subject: [PATCH 027/325] Added UI messages, Added more exceptions --- src/main/java/seedu/duke/ClientList.java | 2 +- src/main/java/seedu/duke/Duke.java | 2 ++ .../InvalidClientIndexDeleteException.java | 7 +++++++ src/main/java/seedu/duke/Messages.java | 7 +++++++ src/main/java/seedu/duke/Parser.java | 21 ++++++++++++++++++- src/main/java/seedu/duke/Ui.java | 19 ++++++++--------- ...ndefinedSubCommandDeleteTypeException.java | 7 +++++++ .../duke/command/CommandDeleteClient.java | 2 +- 8 files changed, 54 insertions(+), 13 deletions(-) create mode 100644 src/main/java/seedu/duke/InvalidClientIndexDeleteException.java create mode 100644 src/main/java/seedu/duke/UndefinedSubCommandDeleteTypeException.java diff --git a/src/main/java/seedu/duke/ClientList.java b/src/main/java/seedu/duke/ClientList.java index 6457b992a..93b3b0a04 100644 --- a/src/main/java/seedu/duke/ClientList.java +++ b/src/main/java/seedu/duke/ClientList.java @@ -42,7 +42,7 @@ public void addClient(String clientName, String clientContactNumber, String clie * @param clientIndex Index of client to be deleted. * @return Client deleted. */ - public Client deleteClient(int clientIndex) { + public Client deleteClient(int clientIndex){ Client deletedClient = clientList.get(clientIndex); clientList.remove(clientIndex); currentListSize--; diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 6e556cffb..d99273d08 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -44,6 +44,8 @@ public void run() throws IOException { ui.showInvalidEmailMessage(); } catch (InvalidBudgetFormatException e) { ui.showInvalidBudgetFormatMessage(); + } catch (UndefinedSubCommandDeleteTypeException e) { + ui.showUndefinedSubCommandDeleteTypeMessage(); } } while (!isCommandBye); } diff --git a/src/main/java/seedu/duke/InvalidClientIndexDeleteException.java b/src/main/java/seedu/duke/InvalidClientIndexDeleteException.java new file mode 100644 index 000000000..5e26d8e97 --- /dev/null +++ b/src/main/java/seedu/duke/InvalidClientIndexDeleteException.java @@ -0,0 +1,7 @@ +package seedu.duke; + +/** + * Represents exception when an invalid index is provided. + */ +public class InvalidClientIndexDeleteException extends DukeException { +} diff --git a/src/main/java/seedu/duke/Messages.java b/src/main/java/seedu/duke/Messages.java index d9c8ede50..020eba0b0 100644 --- a/src/main/java/seedu/duke/Messages.java +++ b/src/main/java/seedu/duke/Messages.java @@ -32,4 +32,11 @@ public class Messages { public static final String MESSAGE_INVALID_BUDGET_FORMAT = "OOPS!!! Please enter positive number " + "(No letter/symbols, etc) for budget"; + + public static final String MESSAGE_CLIENT_DELETED = "Deleting a client with the following information:"; + + public static final String MESSAGE_MISSING_SUB_COMMAND_TYPE_FOR_DELETE = "OOPS!!! To delete, " + + "please specify sub-command type.\n" + + "For client: add -client\n" + + "For property: add -property"; } diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index ae87713ff..8ee9e9807 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -2,6 +2,7 @@ import seedu.duke.command.Command; import seedu.duke.command.CommandAddClient; +import seedu.duke.command.CommandDeleteClient; import seedu.duke.command.CommandUndefined; import java.util.ArrayList; @@ -15,7 +16,7 @@ public class Parser { public Command parseCommand(String input) throws EmptyCommandAddDetailException, UndefinedSubCommandAddTypeException, EmptyClientDetailException, MissingClientFlagException, IncorrectAddClientFlagOrderException, MissingClientDetailException, InvalidContactNumberException, - InvalidEmailException, InvalidBudgetFormatException { + InvalidEmailException, InvalidBudgetFormatException, UndefinedSubCommandDeleteTypeException { ArrayList processedCommandDetails = partitionCommandTypeAndDetails(input); String commandType = processedCommandDetails.get(0); String commandDetails = processedCommandDetails.get(1); @@ -32,6 +33,16 @@ public Command parseCommand(String input) throws EmptyCommandAddDetailException, throw new UndefinedSubCommandAddTypeException(); } case ("delete"): + checkForEmptyCommandAddDetails(commandDetails); + ArrayList processedDeleteCommandDetails = partitionCommandTypeAndDetails(commandDetails); + String subDeleteCommandType = processedDeleteCommandDetails.get(0); + int clientIndexToDelete = getClientIndex(processedDeleteCommandDetails.get(1)); + + if (subDeleteCommandType.equals("-client")) { + return prepareForCommandDeleteClient(clientIndexToDelete); + } else { + throw new UndefinedSubCommandDeleteTypeException(); + } default: return new CommandUndefined(); } @@ -215,4 +226,12 @@ private static String extractDetail(String rawClientDetails, int beginIndex, int private boolean checkForEmptyDetail(String commandDetails) { return commandDetails.trim().isEmpty(); } + + private int getClientIndex(String commandDetails) { + return Integer.parseInt(commandDetails.trim()); + } + + private Command prepareForCommandDeleteClient(int clientIndex) { + return new CommandDeleteClient(clientIndex); + } } diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index 808ad92fa..2f3220085 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -2,16 +2,7 @@ import java.util.Scanner; -import static seedu.duke.Messages.MESSAGE_CLIENT_ADDED; -import static seedu.duke.Messages.MESSAGE_EMPTY_ADD_DESCRIPTION; -import static seedu.duke.Messages.MESSAGE_MISSING_SUB_COMMAND_TYPE_FOR_ADD; -import static seedu.duke.Messages.MESSAGE_EMPTY_CLIENT_DESCRIPTION; -import static seedu.duke.Messages.MESSAGE_ADD_CLIENT_WRONG_FORMAT; -import static seedu.duke.Messages.MESSAGE_CLIENT_INPUT_EXAMPLE; -import static seedu.duke.Messages.MESSAGE_TRY_AGAIN; -import static seedu.duke.Messages.MESSAGE_INVALID_CONTACT_NUMBER; -import static seedu.duke.Messages.MESSAGE_INVALID_EMAIL; -import static seedu.duke.Messages.MESSAGE_INVALID_BUDGET_FORMAT; +import static seedu.duke.Messages.*; public class Ui { @@ -42,6 +33,11 @@ public void showClientAddedConfirmationMessage(ClientList clientList) { showToUser(" " + clientList.getClientList().get(currentListSize - 1)); } + public void showClientDeletedConfirmationMessage(Client deletedClient) { + showToUser(MESSAGE_CLIENT_DELETED); + showToUser(" " + deletedClient); + } + /* Add Client Related Exceptions */ public void showMissingCommandAddDetailMessage() { showToUser(MESSAGE_EMPTY_ADD_DESCRIPTION); @@ -74,4 +70,7 @@ public void showInvalidBudgetFormatMessage() { } /* Delete Client Related Exceptions */ + public void showUndefinedSubCommandDeleteTypeMessage() { + showToUser(MESSAGE_MISSING_SUB_COMMAND_TYPE_FOR_DELETE); + } } diff --git a/src/main/java/seedu/duke/UndefinedSubCommandDeleteTypeException.java b/src/main/java/seedu/duke/UndefinedSubCommandDeleteTypeException.java new file mode 100644 index 000000000..58dfc4983 --- /dev/null +++ b/src/main/java/seedu/duke/UndefinedSubCommandDeleteTypeException.java @@ -0,0 +1,7 @@ +package seedu.duke; + +/** + * Represents exception when sub command type required for command delete is missing (-property/-client). + */ +public class UndefinedSubCommandDeleteTypeException extends DukeException { +} diff --git a/src/main/java/seedu/duke/command/CommandDeleteClient.java b/src/main/java/seedu/duke/command/CommandDeleteClient.java index 36ff61370..c660037f0 100644 --- a/src/main/java/seedu/duke/command/CommandDeleteClient.java +++ b/src/main/java/seedu/duke/command/CommandDeleteClient.java @@ -15,7 +15,7 @@ public CommandDeleteClient(int clientIndex) { } @Override - public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList) { + public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList){ Client deletedClient = clientList.deleteClient(clientIndex); ui.showClientDeletedConfirmationMessage(deletedClient); //Update Storage From 3949f56ae98f69630efb310a3c06ec5d552801be Mon Sep 17 00:00:00 2001 From: FeliciaBeatrice Date: Mon, 10 Oct 2022 15:43:57 +0800 Subject: [PATCH 028/325] Delete Client Feature Implemented --- src/main/java/seedu/duke/Duke.java | 6 +++- .../EmptyCommandDeleteDetailException.java | 7 ++++ src/main/java/seedu/duke/Messages.java | 4 +++ src/main/java/seedu/duke/Parser.java | 32 +++++++++++++++---- src/main/java/seedu/duke/Ui.java | 8 +++++ 5 files changed, 49 insertions(+), 8 deletions(-) create mode 100644 src/main/java/seedu/duke/EmptyCommandDeleteDetailException.java diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index d99273d08..04bae1528 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -26,7 +26,7 @@ public void run() throws IOException { do { try { String userInputText = ui.readCommand(); - command = parser.parseCommand(userInputText); + command = parser.parseCommand(userInputText, clientList); command.execute(ui, storage, propertyList, clientList); isCommandBye = (command instanceof CommandBye); } catch (EmptyCommandAddDetailException e) { @@ -44,8 +44,12 @@ public void run() throws IOException { ui.showInvalidEmailMessage(); } catch (InvalidBudgetFormatException e) { ui.showInvalidBudgetFormatMessage(); + } catch (EmptyCommandDeleteDetailException e) { + ui.showMissingCommandDeleteDetailMessage(); } catch (UndefinedSubCommandDeleteTypeException e) { ui.showUndefinedSubCommandDeleteTypeMessage(); + } catch (InvalidClientIndexDeleteException e) { + ui.showInvalidClientIndexDeleteMessage(); } } while (!isCommandBye); } diff --git a/src/main/java/seedu/duke/EmptyCommandDeleteDetailException.java b/src/main/java/seedu/duke/EmptyCommandDeleteDetailException.java new file mode 100644 index 000000000..8a2555ce0 --- /dev/null +++ b/src/main/java/seedu/duke/EmptyCommandDeleteDetailException.java @@ -0,0 +1,7 @@ +package seedu.duke; + +/** + * Represents exception when no information is provided when deleting (property/client). + */ +public class EmptyCommandDeleteDetailException extends DukeException { +} diff --git a/src/main/java/seedu/duke/Messages.java b/src/main/java/seedu/duke/Messages.java index 020eba0b0..4c81f7133 100644 --- a/src/main/java/seedu/duke/Messages.java +++ b/src/main/java/seedu/duke/Messages.java @@ -39,4 +39,8 @@ public class Messages { + "please specify sub-command type.\n" + "For client: add -client\n" + "For property: add -property"; + + public static final String MESSAGE_EMPTY_DELETE_DESCRIPTION = "OOPS!!! The index for delete cannot be empty."; + + public static final String MESSAGE_INVALID_CLIENT_INDEX = "OOPS!!! Please enter a valid client index."; } diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 8ee9e9807..bdb67e6fa 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -13,10 +13,11 @@ public class Parser { public static final int ADD_CLIENT_FLAG_SIZE = 4; - public Command parseCommand(String input) throws EmptyCommandAddDetailException, + public Command parseCommand(String input, ClientList clientList) throws EmptyCommandAddDetailException, UndefinedSubCommandAddTypeException, EmptyClientDetailException, MissingClientFlagException, IncorrectAddClientFlagOrderException, MissingClientDetailException, InvalidContactNumberException, - InvalidEmailException, InvalidBudgetFormatException, UndefinedSubCommandDeleteTypeException { + InvalidEmailException, InvalidBudgetFormatException, UndefinedSubCommandDeleteTypeException, + EmptyCommandDeleteDetailException, InvalidClientIndexDeleteException { ArrayList processedCommandDetails = partitionCommandTypeAndDetails(input); String commandType = processedCommandDetails.get(0); String commandDetails = processedCommandDetails.get(1); @@ -33,13 +34,13 @@ public Command parseCommand(String input) throws EmptyCommandAddDetailException, throw new UndefinedSubCommandAddTypeException(); } case ("delete"): - checkForEmptyCommandAddDetails(commandDetails); + checkForEmptyCommandDeleteDetails(commandDetails); ArrayList processedDeleteCommandDetails = partitionCommandTypeAndDetails(commandDetails); String subDeleteCommandType = processedDeleteCommandDetails.get(0); - int clientIndexToDelete = getClientIndex(processedDeleteCommandDetails.get(1)); + int clientIndexToDelete = getClientIndex(processedDeleteCommandDetails.get(1)) - 1; if (subDeleteCommandType.equals("-client")) { - return prepareForCommandDeleteClient(clientIndexToDelete); + return prepareForCommandDeleteClient(clientIndexToDelete, clientList); } else { throw new UndefinedSubCommandDeleteTypeException(); } @@ -66,6 +67,13 @@ private void checkForEmptyCommandAddDetails(String commandAddDetails) throws Emp } } + private void checkForEmptyCommandDeleteDetails(String commandAddDetails) throws EmptyCommandDeleteDetailException { + boolean isEmptyCommandAddDetail = checkForEmptyDetail(commandAddDetails); + if (isEmptyCommandAddDetail) { + throw new EmptyCommandDeleteDetailException(); + } + } + private Command prepareForCommandAddClient(String rawClientDescriptions) throws EmptyClientDetailException, MissingClientFlagException, IncorrectAddClientFlagOrderException, MissingClientDetailException, InvalidContactNumberException, InvalidEmailException, InvalidBudgetFormatException { @@ -231,7 +239,17 @@ private int getClientIndex(String commandDetails) { return Integer.parseInt(commandDetails.trim()); } - private Command prepareForCommandDeleteClient(int clientIndex) { + private Command prepareForCommandDeleteClient(int clientIndex, ClientList clientList) + throws InvalidClientIndexDeleteException { + checkForInvalidClientIndexDelete(clientIndex, clientList); return new CommandDeleteClient(clientIndex); } -} + + private void checkForInvalidClientIndexDelete(int clientIndex, ClientList clientList) + throws InvalidClientIndexDeleteException { + int currentListSize = clientList.getCurrentListSize(); + if (clientIndex < 0 || clientIndex >= currentListSize) { + throw new InvalidClientIndexDeleteException(); + } + } +} \ No newline at end of file diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index 2f3220085..c0cd94c76 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -73,4 +73,12 @@ public void showInvalidBudgetFormatMessage() { public void showUndefinedSubCommandDeleteTypeMessage() { showToUser(MESSAGE_MISSING_SUB_COMMAND_TYPE_FOR_DELETE); } + + public void showMissingCommandDeleteDetailMessage() { + showToUser(MESSAGE_EMPTY_DELETE_DESCRIPTION); + } + + public void showInvalidClientIndexDeleteMessage() { + showToUser(MESSAGE_INVALID_CLIENT_INDEX); + } } From ed9dfa14a794d950f88446200af70e89cb3ce458 Mon Sep 17 00:00:00 2001 From: FeliciaBeatrice Date: Mon, 10 Oct 2022 16:20:04 +0800 Subject: [PATCH 029/325] Added more exceptions --- src/main/java/seedu/duke/Duke.java | 2 ++ .../java/seedu/duke/EmptyClientIndexDeleteException.java | 7 +++++++ src/main/java/seedu/duke/Messages.java | 2 ++ src/main/java/seedu/duke/Parser.java | 7 +++++-- src/main/java/seedu/duke/Ui.java | 4 ++++ 5 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 src/main/java/seedu/duke/EmptyClientIndexDeleteException.java diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 04bae1528..b1c94d5d5 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -50,6 +50,8 @@ public void run() throws IOException { ui.showUndefinedSubCommandDeleteTypeMessage(); } catch (InvalidClientIndexDeleteException e) { ui.showInvalidClientIndexDeleteMessage(); + } catch (EmptyClientIndexDeleteException e) { + ui.showEmptyClientIndexDeleteMessage(); } } while (!isCommandBye); } diff --git a/src/main/java/seedu/duke/EmptyClientIndexDeleteException.java b/src/main/java/seedu/duke/EmptyClientIndexDeleteException.java new file mode 100644 index 000000000..c7d511d35 --- /dev/null +++ b/src/main/java/seedu/duke/EmptyClientIndexDeleteException.java @@ -0,0 +1,7 @@ +package seedu.duke; + +/** + * Represents exception when client index to delete is empty. + */ +public class EmptyClientIndexDeleteException extends DukeException { +} diff --git a/src/main/java/seedu/duke/Messages.java b/src/main/java/seedu/duke/Messages.java index 4c81f7133..656c9873e 100644 --- a/src/main/java/seedu/duke/Messages.java +++ b/src/main/java/seedu/duke/Messages.java @@ -43,4 +43,6 @@ public class Messages { public static final String MESSAGE_EMPTY_DELETE_DESCRIPTION = "OOPS!!! The index for delete cannot be empty."; public static final String MESSAGE_INVALID_CLIENT_INDEX = "OOPS!!! Please enter a valid client index."; + + public static final String MESSAGE_EMPTY_CLIENT_INDEX = "OOPS!!! The client index to delete cannot be empty."; } diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index bdb67e6fa..a03dc6f2e 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -17,7 +17,7 @@ public Command parseCommand(String input, ClientList clientList) throws EmptyCom UndefinedSubCommandAddTypeException, EmptyClientDetailException, MissingClientFlagException, IncorrectAddClientFlagOrderException, MissingClientDetailException, InvalidContactNumberException, InvalidEmailException, InvalidBudgetFormatException, UndefinedSubCommandDeleteTypeException, - EmptyCommandDeleteDetailException, InvalidClientIndexDeleteException { + EmptyCommandDeleteDetailException, InvalidClientIndexDeleteException, EmptyClientIndexDeleteException { ArrayList processedCommandDetails = partitionCommandTypeAndDetails(input); String commandType = processedCommandDetails.get(0); String commandDetails = processedCommandDetails.get(1); @@ -235,7 +235,10 @@ private boolean checkForEmptyDetail(String commandDetails) { return commandDetails.trim().isEmpty(); } - private int getClientIndex(String commandDetails) { + private int getClientIndex(String commandDetails) throws EmptyClientIndexDeleteException { + if (commandDetails.isEmpty()) { + throw new EmptyClientIndexDeleteException(); + } return Integer.parseInt(commandDetails.trim()); } diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index c0cd94c76..a8592de28 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -81,4 +81,8 @@ public void showMissingCommandDeleteDetailMessage() { public void showInvalidClientIndexDeleteMessage() { showToUser(MESSAGE_INVALID_CLIENT_INDEX); } + + public void showEmptyClientIndexDeleteMessage() { + showToUser(MESSAGE_EMPTY_CLIENT_INDEX); + } } From 558ee7bc0b31dd87530191def8506934d3592e69 Mon Sep 17 00:00:00 2001 From: FeliciaBeatrice Date: Mon, 10 Oct 2022 16:29:41 +0800 Subject: [PATCH 030/325] Fixed coding standard violation --- src/main/java/seedu/duke/ClientList.java | 2 +- src/main/java/seedu/duke/Ui.java | 16 +++++++++++++++- .../seedu/duke/command/CommandDeleteClient.java | 10 ++++++---- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/main/java/seedu/duke/ClientList.java b/src/main/java/seedu/duke/ClientList.java index 93b3b0a04..6457b992a 100644 --- a/src/main/java/seedu/duke/ClientList.java +++ b/src/main/java/seedu/duke/ClientList.java @@ -42,7 +42,7 @@ public void addClient(String clientName, String clientContactNumber, String clie * @param clientIndex Index of client to be deleted. * @return Client deleted. */ - public Client deleteClient(int clientIndex){ + public Client deleteClient(int clientIndex) { Client deletedClient = clientList.get(clientIndex); clientList.remove(clientIndex); currentListSize--; diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index a8592de28..facee841c 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -2,7 +2,21 @@ import java.util.Scanner; -import static seedu.duke.Messages.*; +import static seedu.duke.Messages.MESSAGE_ADD_CLIENT_WRONG_FORMAT; +import static seedu.duke.Messages.MESSAGE_CLIENT_ADDED; +import static seedu.duke.Messages.MESSAGE_CLIENT_DELETED; +import static seedu.duke.Messages.MESSAGE_CLIENT_INPUT_EXAMPLE; +import static seedu.duke.Messages.MESSAGE_EMPTY_ADD_DESCRIPTION; +import static seedu.duke.Messages.MESSAGE_EMPTY_CLIENT_DESCRIPTION; +import static seedu.duke.Messages.MESSAGE_EMPTY_CLIENT_INDEX; +import static seedu.duke.Messages.MESSAGE_EMPTY_DELETE_DESCRIPTION; +import static seedu.duke.Messages.MESSAGE_INVALID_BUDGET_FORMAT; +import static seedu.duke.Messages.MESSAGE_INVALID_CLIENT_INDEX; +import static seedu.duke.Messages.MESSAGE_INVALID_CONTACT_NUMBER; +import static seedu.duke.Messages.MESSAGE_INVALID_EMAIL; +import static seedu.duke.Messages.MESSAGE_MISSING_SUB_COMMAND_TYPE_FOR_ADD; +import static seedu.duke.Messages.MESSAGE_MISSING_SUB_COMMAND_TYPE_FOR_DELETE; +import static seedu.duke.Messages.MESSAGE_TRY_AGAIN; public class Ui { diff --git a/src/main/java/seedu/duke/command/CommandDeleteClient.java b/src/main/java/seedu/duke/command/CommandDeleteClient.java index c660037f0..224902f4d 100644 --- a/src/main/java/seedu/duke/command/CommandDeleteClient.java +++ b/src/main/java/seedu/duke/command/CommandDeleteClient.java @@ -1,8 +1,10 @@ package seedu.duke.command; -import seedu.duke.*; - -import java.util.ArrayList; +import seedu.duke.Client; +import seedu.duke.ClientList; +import seedu.duke.PropertyList; +import seedu.duke.Storage; +import seedu.duke.Ui; /** * Deletes a client from the client list. @@ -15,7 +17,7 @@ public CommandDeleteClient(int clientIndex) { } @Override - public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList){ + public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList) { Client deletedClient = clientList.deleteClient(clientIndex); ui.showClientDeletedConfirmationMessage(deletedClient); //Update Storage From 35f5c393d32d0beaf72bbb764308caefed2fc17f Mon Sep 17 00:00:00 2001 From: ngdeqi Date: Mon, 10 Oct 2022 18:05:11 +0800 Subject: [PATCH 031/325] Add some documentation, more exception handling for (non)existing pairs for Pair/Unpair feature --- src/main/java/seedu/duke/Duke.java | 8 +++- src/main/java/seedu/duke/Messages.java | 10 ++++ src/main/java/seedu/duke/PairingList.java | 28 +++++++++++ src/main/java/seedu/duke/Parser.java | 46 ++++++++++++++----- src/main/java/seedu/duke/Ui.java | 24 +++++++++- .../seedu/duke/command/CommandUnpair.java | 1 + .../duke/exception/ExistingPairException.java | 4 ++ .../exception/NoExistingPairException.java | 4 ++ 8 files changed, 111 insertions(+), 14 deletions(-) create mode 100644 src/main/java/seedu/duke/exception/ExistingPairException.java create mode 100644 src/main/java/seedu/duke/exception/NoExistingPairException.java diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 445165d82..7296b6e1f 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -5,6 +5,7 @@ import seedu.duke.exception.EmptyClientDetailException; import seedu.duke.exception.EmptyCommandAddDetailException; import seedu.duke.exception.EmptyCommandPairUnpairDetailsException; +import seedu.duke.exception.ExistingPairException; import seedu.duke.exception.IncorrectAddClientFlagOrderException; import seedu.duke.exception.IncorrectPairUnpairFlagOrderException; import seedu.duke.exception.InvalidBudgetFormatException; @@ -13,6 +14,7 @@ import seedu.duke.exception.MissingClientDetailException; import seedu.duke.exception.MissingClientFlagException; import seedu.duke.exception.MissingPairUnpairFlagException; +import seedu.duke.exception.NoExistingPairException; import seedu.duke.exception.NotIntegerException; import seedu.duke.exception.NotValidIndexException; import seedu.duke.exception.UndefinedSubCommandAddTypeException; @@ -33,7 +35,7 @@ public void run() throws IOException { this.storage = new Storage(); this.propertyList = new PropertyList(); this.clientList = new ClientList(); - this.parser = new Parser(clientList, propertyList); + this.parser = new Parser(clientList, propertyList, pairingList); this.pairingList = new PairingList(); Command command; @@ -71,6 +73,10 @@ public void run() throws IOException { ui.showNotValidIndexMessage(); } catch (NotIntegerException e) { ui.showNotIntegerMessage(); + } catch (ExistingPairException e) { + ui.showExistingPairMessage(); + } catch (NoExistingPairException e) { + ui.showNoExistingPairMessage(); } } while (!isCommandBye); } diff --git a/src/main/java/seedu/duke/Messages.java b/src/main/java/seedu/duke/Messages.java index 548da3175..a70fd2fc6 100644 --- a/src/main/java/seedu/duke/Messages.java +++ b/src/main/java/seedu/duke/Messages.java @@ -37,6 +37,8 @@ public class Messages { public static final String MESSAGE_PAIRED = "Pairing the following client and property: "; + public static final String MESSAGE_UNPAIRED = "Unpairing the following client and property: "; + public static final String MESSAGE_EMPTY_COMMAND_PAIR_UNPAIR = "OOPS!!! The description of a pair/unpair message " + "cannot be empty"; @@ -54,4 +56,12 @@ public class Messages { + "Examples:\n" + " pair ip/1 ic/5\n" + " unpair ip/2 ic/1"; + + public static final String MESSAGE_EXISTING_PAIR = "OOPS!! This property is currently rented by a tenant, " + + "try pairing with another property"; + + public static final String MESSAGE_NO_EXISTING_PAIR = "OOPS!! This property is not being rented by a tenant. " + + "Unpair unsuccessful"; + + } diff --git a/src/main/java/seedu/duke/PairingList.java b/src/main/java/seedu/duke/PairingList.java index 74d4373ae..c009ed44e 100644 --- a/src/main/java/seedu/duke/PairingList.java +++ b/src/main/java/seedu/duke/PairingList.java @@ -2,6 +2,9 @@ import java.util.HashMap; +/** + * Stores information on which the property each client is renting. + */ public class PairingList { private static final String SEPARATOR = " | "; @@ -11,6 +14,11 @@ public PairingList() { } + /** + * Records which property a client is renting. + * @param client Client renting the property. + * @param property Property being rented. + */ public void addPairing(Client client, Property property) { String clientPairingData = convertToPairingData(client); String propertyPairingData = convertToPairingData(property); @@ -18,6 +26,11 @@ public void addPairing(Client client, Property property) { clientPropertyPairs.put(clientPairingData, propertyPairingData); } + /** + * Removes a client-property pair to indicate that the client is no longer renting that property. + * @param client Client who is no longer renting the property. + * @param property Property that is no loner being rented. + */ public void deletePairing(Client client, Property property) { String clientPairingData = convertToPairingData(client); @@ -26,10 +39,25 @@ public void deletePairing(Client client, Property property) { clientPropertyPairs.remove(clientPairingData, propertyPairingData); } + public boolean isClientPairedWithProperty(Client client) { + String clientPairingData = convertToPairingData(client); + return clientPropertyPairs.containsKey(clientPairingData); + } + + /** + * Overloaded method to convert client pairing data to a suitable string format. + * @param client Client whose data is to be converted. + * @return Pairing data in a suitable string format. + */ private String convertToPairingData(Client client) { return client.getClientName() + SEPARATOR + client.getClientContactNumber(); } + /** + * Overloaded method to convert property pairing data to a suitable string format. + * @param property Property whose data is to be converted. + * @return Pairing data in a suitable string format. + */ private String convertToPairingData(Property property) { return property.getLandlordName() + SEPARATOR diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 054838e78..73c1953ac 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -8,6 +8,7 @@ import seedu.duke.exception.EmptyClientDetailException; import seedu.duke.exception.EmptyCommandAddDetailException; import seedu.duke.exception.EmptyCommandPairUnpairDetailsException; +import seedu.duke.exception.ExistingPairException; import seedu.duke.exception.IncorrectAddClientFlagOrderException; import seedu.duke.exception.IncorrectFlagOrderException; import seedu.duke.exception.IncorrectPairUnpairFlagOrderException; @@ -18,6 +19,7 @@ import seedu.duke.exception.MissingClientFlagException; import seedu.duke.exception.MissingFlagException; import seedu.duke.exception.MissingPairUnpairFlagException; +import seedu.duke.exception.NoExistingPairException; import seedu.duke.exception.NotIntegerException; import seedu.duke.exception.NotValidIndexException; import seedu.duke.exception.UndefinedSubCommandAddTypeException; @@ -30,13 +32,15 @@ public class Parser { private static ClientList clientList; private static PropertyList propertyList; + private static PairingList pairingList; public static final int ADD_CLIENT_FLAG_SIZE = 4; public static final int PAIR_UNPAIR_FLAG_SIZE = 2; - public Parser(ClientList cl, PropertyList pl) { - clientList = cl; - propertyList = pl; + public Parser(ClientList clientL, PropertyList propertyL, PairingList pairingL) { + clientList = clientL; + propertyList = propertyL; + pairingList = pairingL; } public Command parseCommand(String input) throws EmptyCommandAddDetailException, @@ -44,7 +48,7 @@ public Command parseCommand(String input) throws EmptyCommandAddDetailException, IncorrectAddClientFlagOrderException, MissingClientDetailException, InvalidContactNumberException, InvalidEmailException, InvalidBudgetFormatException, EmptyCommandPairUnpairDetailsException, MissingPairUnpairFlagException, IncorrectPairUnpairFlagOrderException, NotValidIndexException, - NotIntegerException { + NotIntegerException, ExistingPairException, NoExistingPairException { ArrayList processedCommandDetails = partitionCommandTypeAndDetails(input); String commandType = processedCommandDetails.get(0); String commandDetails = processedCommandDetails.get(1); @@ -260,17 +264,18 @@ private void checkForEmptyCommandPairUnpairDetails(String commandPairUnpairDetai } private Command prepareForCommandPair(String rawPairDescriptions) throws NotIntegerException, - NotValidIndexException, MissingPairUnpairFlagException, IncorrectPairUnpairFlagOrderException { + NotValidIndexException, MissingPairUnpairFlagException, IncorrectPairUnpairFlagOrderException, + ExistingPairException { ArrayList pairDetails = processPairUnpairDetails(rawPairDescriptions); - validatePairUnpairDetails(pairDetails); + validatePairDetails(pairDetails); return new CommandPair(pairDetails); } private Command prepareForCommandUnpair(String rawUnpairDescriptions) throws NotIntegerException, - NotValidIndexException, MissingPairUnpairFlagException, IncorrectPairUnpairFlagOrderException { - + NotValidIndexException, MissingPairUnpairFlagException, IncorrectPairUnpairFlagOrderException, + NoExistingPairException { ArrayList unpairDetails = processPairUnpairDetails(rawUnpairDescriptions); - validatePairUnpairDetails(unpairDetails); + validateUnpairDetails(unpairDetails); return new CommandUnpair(unpairDetails); } @@ -329,15 +334,34 @@ private ArrayList extractPairUnpairDetails(String rawPairUnpairDetails, } ArrayList processedPairUnpairDetails = new ArrayList<>(); - processedPairUnpairDetails.add(clientIndex - 1); + processedPairUnpairDetails.add(clientIndex - 1); // convert to 0-index processedPairUnpairDetails.add(propertyIndex - 1); return processedPairUnpairDetails; } - private void validatePairUnpairDetails(ArrayList pairUnpairDetails) throws NotValidIndexException { + private void validatePairDetails(ArrayList pairUnpairDetails) throws NotValidIndexException, + ExistingPairException { + int clientIndex = pairUnpairDetails.get(0); + int propertyIndex = pairUnpairDetails.get(1); + checkForListIndexOutOfBounds(clientIndex, propertyIndex); + Client client = clientList.getClientList().get(clientIndex); + if (pairingList.isClientPairedWithProperty(client)) { + throw new ExistingPairException(); + } + } + + private void validateUnpairDetails(ArrayList pairUnpairDetails) throws NotValidIndexException, + NoExistingPairException { int clientIndex = pairUnpairDetails.get(0); int propertyIndex = pairUnpairDetails.get(1); + checkForListIndexOutOfBounds(clientIndex, propertyIndex); + Client client = clientList.getClientList().get(clientIndex); + if (!pairingList.isClientPairedWithProperty(client)) { + throw new NoExistingPairException(); + } + } + private void checkForListIndexOutOfBounds(int clientIndex, int propertyIndex) throws NotValidIndexException { if (clientIndex < 0 || clientIndex > clientList.getCurrentListSize() - 1 || propertyIndex < 0 || propertyIndex > propertyList.getCurrentListSize() - 1) { throw new NotValidIndexException(); diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index 8a80c0477..94c12cf7e 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -8,18 +8,24 @@ import static seedu.duke.Messages.MESSAGE_EMPTY_ADD_DESCRIPTION; import static seedu.duke.Messages.MESSAGE_EMPTY_CLIENT_DESCRIPTION; import static seedu.duke.Messages.MESSAGE_EMPTY_COMMAND_PAIR_UNPAIR; +import static seedu.duke.Messages.MESSAGE_EXISTING_PAIR; import static seedu.duke.Messages.MESSAGE_INVALID_BUDGET_FORMAT; import static seedu.duke.Messages.MESSAGE_INVALID_CONTACT_NUMBER; import static seedu.duke.Messages.MESSAGE_INVALID_EMAIL; import static seedu.duke.Messages.MESSAGE_MISSING_SUB_COMMAND_TYPE_FOR_ADD; import static seedu.duke.Messages.MESSAGE_NOT_INTEGER; import static seedu.duke.Messages.MESSAGE_NOT_VALID_INDEX; +import static seedu.duke.Messages.MESSAGE_NO_EXISTING_PAIR; +import static seedu.duke.Messages.MESSAGE_PAIRED; import static seedu.duke.Messages.MESSAGE_PAIR_UNPAIR_INPUT_EXAMPLE; import static seedu.duke.Messages.MESSAGE_PAIR_UNPAIR_WRONG_FORMAT; import static seedu.duke.Messages.MESSAGE_TRY_AGAIN; +import static seedu.duke.Messages.MESSAGE_UNPAIRED; import static seedu.duke.Messages.MESSAGE_WELCOME; - +/** + * Handler for all interactions between the user and the command line. + */ public class Ui { private static boolean inputIsEmpty(String rawInput) { @@ -85,7 +91,12 @@ public void showInvalidBudgetFormatMessage() { } public void showPairedConfirmationMessage(Client client, Property property) { - showToUser(Messages.MESSAGE_PAIRED); + showToUser(MESSAGE_PAIRED); + showToUser(" " + client.getClientName() + " and " + property.getPropertyAddress()); + } + + public void showUnpairedConfirmationMessage(Client client, Property property) { + showToUser(MESSAGE_UNPAIRED); showToUser(" " + client.getClientName() + " and " + property.getPropertyAddress()); } @@ -106,4 +117,13 @@ public void showPairUnpairWrongFormatMessage() { showToUser(MESSAGE_PAIR_UNPAIR_INPUT_EXAMPLE); showToUser(MESSAGE_TRY_AGAIN); } + + public void showExistingPairMessage() { + showToUser(MESSAGE_EXISTING_PAIR); + } + + public void showNoExistingPairMessage() { + showToUser(MESSAGE_NO_EXISTING_PAIR); + } + } diff --git a/src/main/java/seedu/duke/command/CommandUnpair.java b/src/main/java/seedu/duke/command/CommandUnpair.java index 92cca1355..59a106bfa 100644 --- a/src/main/java/seedu/duke/command/CommandUnpair.java +++ b/src/main/java/seedu/duke/command/CommandUnpair.java @@ -28,5 +28,6 @@ public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientLis Property property = propertyList.getPropertyList().get(propertyIndex); pairingList.deletePairing(client, property); + ui.showUnpairedConfirmationMessage(client, property); } } diff --git a/src/main/java/seedu/duke/exception/ExistingPairException.java b/src/main/java/seedu/duke/exception/ExistingPairException.java new file mode 100644 index 000000000..a378fc6ff --- /dev/null +++ b/src/main/java/seedu/duke/exception/ExistingPairException.java @@ -0,0 +1,4 @@ +package seedu.duke.exception; + +public class ExistingPairException extends DukeException { +} diff --git a/src/main/java/seedu/duke/exception/NoExistingPairException.java b/src/main/java/seedu/duke/exception/NoExistingPairException.java new file mode 100644 index 000000000..13d470ba5 --- /dev/null +++ b/src/main/java/seedu/duke/exception/NoExistingPairException.java @@ -0,0 +1,4 @@ +package seedu.duke.exception; + +public class NoExistingPairException extends DukeException { +} From e902113457b60fc2af92960aa6e77f7c1b68361d Mon Sep 17 00:00:00 2001 From: Wilson Ng Jing An <31720838+wilsonngja@users.noreply.github.com> Date: Mon, 10 Oct 2022 22:35:58 +0800 Subject: [PATCH 032/325] Update Parser.java --- src/main/java/seedu/duke/Parser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index e84dd000c..94d84bd98 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -295,7 +295,7 @@ private void checkForInvalidClientIndexDelete(int clientIndex, ClientList client throw new InvalidClientIndexDeleteException(); } } -} + private void checkForEmptyCommandPairUnpairDetails(String commandPairUnpairDetails) throws EmptyCommandPairUnpairDetailsException { From 1253e265b6f82f63052ca301aa5921a2a9b76bc9 Mon Sep 17 00:00:00 2001 From: "MSI\\User" Date: Tue, 11 Oct 2022 00:30:53 +0800 Subject: [PATCH 033/325] Implement function to store added client to text file. --- src/main/java/seedu/duke/Storage.java | 13 ++++++------- .../java/seedu/duke/command/CommandAddClient.java | 2 ++ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/main/java/seedu/duke/Storage.java b/src/main/java/seedu/duke/Storage.java index fe484591e..f801dc496 100644 --- a/src/main/java/seedu/duke/Storage.java +++ b/src/main/java/seedu/duke/Storage.java @@ -1,10 +1,8 @@ package seedu.duke; import java.io.File; -import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; -import java.util.Scanner; public class Storage { private static final String DIRECTORY = "./data/"; @@ -12,7 +10,7 @@ public class Storage { private static final String CLIENT_PATH = "./data/client.txt"; private static final String PAIR_PATH = "./data/pair.txt"; private static final String SEPARATOR = " | "; - private static final String DOLLAR_SIGN = "$"; + private static final String CURRENCY = "SGD"; private static final String OPEN_BRACKET = "["; private static final String CLOSE_BRACKET = "]"; private static final String COLON = " : "; @@ -123,7 +121,7 @@ public void loadPair(File pairFile) { public void addToPropertyFile(String landlord, String address, int price, String unitType) { try { FileWriter fw = new FileWriter(PROPERTY_PATH, true); - String rentalPrice = DOLLAR_SIGN + price; + String rentalPrice = CURRENCY + price; String newText = landlord + SEPARATOR + address + SEPARATOR + rentalPrice + SEPARATOR + unitType + System.lineSeparator(); @@ -146,8 +144,9 @@ public void addToPropertyFile(String landlord, String address, int price, String public void addToClientFile(String name, String contact, String email, int budget) { try { FileWriter fw = new FileWriter(CLIENT_PATH, true); - String budgetPrice = DOLLAR_SIGN + budget; - String newText = name + SEPARATOR + contact + SEPARATOR + email + SEPARATOR + budgetPrice; + String budgetPrice = CURRENCY + budget; + String newText = name + SEPARATOR + contact + SEPARATOR + email + SEPARATOR + + budgetPrice + System.lineSeparator(); fw.write(newText); fw.close(); @@ -171,7 +170,7 @@ public void addToPairFile(String client, String contact, String landlord, String address, int price, String type) { try { FileWriter fw = new FileWriter(PAIR_PATH, true); - String monthlyPrice = DOLLAR_SIGN + price; + String monthlyPrice = CURRENCY + price; String clientPortion = OPEN_BRACKET + client + SEPARATOR + contact + CLOSE_BRACKET; String propertyPortion = OPEN_BRACKET + landlord + SEPARATOR + address + SEPARATOR + monthlyPrice + SEPARATOR + type + CLOSE_BRACKET; diff --git a/src/main/java/seedu/duke/command/CommandAddClient.java b/src/main/java/seedu/duke/command/CommandAddClient.java index 87b647100..d6414b600 100644 --- a/src/main/java/seedu/duke/command/CommandAddClient.java +++ b/src/main/java/seedu/duke/command/CommandAddClient.java @@ -36,5 +36,7 @@ public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientLis clientList.addClient(clientName, clientContactNumber, clientEmail, clientBudgetPerMonth); ui.showClientAddedConfirmationMessage(clientList); //Update Storage + storage.addToClientFile(this.clientName, this.clientContactNumber, + this.clientEmail, Integer.parseInt(this.clientBudgetPerMonth)); } } From 00f1bd9ea19a14e8ee803e945113dbb100069ce4 Mon Sep 17 00:00:00 2001 From: "MSI\\User" Date: Tue, 11 Oct 2022 13:24:21 +0800 Subject: [PATCH 034/325] Implement function to load client into client list --- src/main/java/seedu/duke/Duke.java | 4 +- src/main/java/seedu/duke/Storage.java | 57 +++++++++++++++++++-------- 2 files changed, 42 insertions(+), 19 deletions(-) diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index aadc9b79a..0a45903e3 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -34,11 +34,11 @@ public class Duke { public void run() throws IOException { this.ui = new Ui(); - this.storage = new Storage(); this.propertyList = new PropertyList(); this.clientList = new ClientList(); this.parser = new Parser(clientList, propertyList); this.pairingList = new PairingList(); + this.storage = new Storage(clientList, propertyList, pairingList); Command command; boolean isCommandBye = false; @@ -47,7 +47,7 @@ public void run() throws IOException { do { try { - System.exit(0); //to pass CI +// System.exit(0); //to pass CI String userInputText = ui.readCommand(); command = parser.parseCommand(userInputText); command.execute(ui, storage, propertyList, clientList, pairingList); diff --git a/src/main/java/seedu/duke/Storage.java b/src/main/java/seedu/duke/Storage.java index f801dc496..cc93d6706 100644 --- a/src/main/java/seedu/duke/Storage.java +++ b/src/main/java/seedu/duke/Storage.java @@ -1,8 +1,10 @@ package seedu.duke; import java.io.File; +import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; +import java.util.Scanner; public class Storage { private static final String DIRECTORY = "./data/"; @@ -14,20 +16,21 @@ public class Storage { private static final String OPEN_BRACKET = "["; private static final String CLOSE_BRACKET = "]"; private static final String COLON = " : "; + private static final String EMPTY_STRING = ""; - public Storage() { - checkFile(); + public Storage(ClientList clientList, PropertyList propertyList, PairingList pairingList) { + checkFile(clientList, propertyList, pairingList); } /** * Checks if all the file exist. */ - public void checkFile() { + public void checkFile(ClientList clientList, PropertyList propertyList, PairingList pairingList) { checkDirectory(); - checkPropertyFile(); - checkClientFile(); - checkPair(); + checkPropertyFile(propertyList); + checkClientFile(clientList); + checkPair(pairingList); } /** @@ -46,66 +49,86 @@ public void checkDirectory() { /** * Checks if the property file exist. */ - public void checkPropertyFile() { + public void checkPropertyFile(PropertyList propertyList) { File propertyFile = new File(PROPERTY_PATH); boolean hasPropertyFile = propertyFile.exists(); if (hasPropertyFile) { // Load property into the array list - loadProperty(propertyFile); + loadProperty(propertyList, propertyFile); } } /** * Checks if the client file exist. */ - public void checkClientFile() { + public void checkClientFile(ClientList clientList) { File clientFile = new File(CLIENT_PATH); boolean hasClientFile = clientFile.exists(); - if (!hasClientFile) { + if (hasClientFile) { // Load client into the array list - loadClient(clientFile); + loadClient(clientList, clientFile); } } /** * Checks if the pair file exit. + * + * @param pairingList Paring List object that contains the hash map of pair */ - public void checkPair() { + public void checkPair(PairingList pairingList) { File pairFile = new File(PAIR_PATH); boolean hasPairFile = pairFile.exists(); if (!hasPairFile) { // Load pair into the hash map - loadPair(pairFile); + loadPair(pairingList, pairFile); } } /** * Adds the client list in the text file to the array list. * + * @param clientList Client List object that contains client's array list * @param clientFile The file that stores the list of client. */ - public void loadClient(File clientFile) { + public void loadClient(ClientList clientList, File clientFile) { + + try { + Scanner scanner = new Scanner(clientFile); + while (scanner.hasNext()) { + String[] clientParameters = scanner.nextLine().split("\\s\\|\\s"); + String clientName = clientParameters[0]; + String clientContact = clientParameters[1]; + String clientEmail = clientParameters[2]; + String clientBudget = clientParameters[3].replace(CURRENCY, EMPTY_STRING).trim(); + clientList.addClient(clientName, clientContact, clientEmail, clientBudget); + } + } catch (FileNotFoundException e) { + System.out.println("File is not found..."); + } + } /** * Loads the stored property file into the property array list. * + * @param propertyList Property List object that contains property's array list. * @param propertyFile The file that stores the list of property. */ - public void loadProperty(File propertyFile) { + public void loadProperty(PropertyList propertyList, File propertyFile) { } /** * Loads the stored pair file into the pair hash map. * - * @param pairFile The file that stores all the pairs. + * @param pairingList Paring List object that contains the hash map for pairings. + * @param pairFile The file that contains the pairing file. */ - public void loadPair(File pairFile) { + public void loadPair(PairingList pairingList, File pairFile) { } From 0c5222022244f6026981ee18c7e4a35e9acc80d1 Mon Sep 17 00:00:00 2001 From: "MSI\\User" Date: Tue, 11 Oct 2022 13:28:18 +0800 Subject: [PATCH 035/325] Fix styling errors --- src/main/java/seedu/duke/Duke.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 0a45903e3..8714bd254 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -47,7 +47,7 @@ public void run() throws IOException { do { try { -// System.exit(0); //to pass CI + System.exit(0); //to pass CI String userInputText = ui.readCommand(); command = parser.parseCommand(userInputText); command.execute(ui, storage, propertyList, clientList, pairingList); From d02f856b198e81020e82348fbb517cf044f477ee Mon Sep 17 00:00:00 2001 From: "MSI\\User" Date: Tue, 11 Oct 2022 14:49:07 +0800 Subject: [PATCH 036/325] Improve SLAP in Storage.java --- src/main/java/seedu/duke/Storage.java | 98 +++++++++++++++++++-------- 1 file changed, 69 insertions(+), 29 deletions(-) diff --git a/src/main/java/seedu/duke/Storage.java b/src/main/java/seedu/duke/Storage.java index cc93d6706..3e686dcca 100644 --- a/src/main/java/seedu/duke/Storage.java +++ b/src/main/java/seedu/duke/Storage.java @@ -20,70 +20,110 @@ public class Storage { public Storage(ClientList clientList, PropertyList propertyList, PairingList pairingList) { - checkFile(clientList, propertyList, pairingList); + boolean hasDirectory = checkDirectory(); + boolean hasPropertyFile = checkPropertyFile(); + boolean hasClientFile = checkClientFile(); + boolean hasPairingFile = checkPair(); + + loadFiles(hasDirectory, hasPropertyFile, hasClientFile, hasPairingFile, clientList, propertyList, pairingList); + } /** - * Checks if all the file exist. + * Checks if the data directory exist. + * + * @return true if data directory exist and false if it does not */ - public void checkFile(ClientList clientList, PropertyList propertyList, PairingList pairingList) { - checkDirectory(); - checkPropertyFile(propertyList); - checkClientFile(clientList); - checkPair(pairingList); + public boolean checkDirectory() { + File dir = new File(DIRECTORY); + boolean hasDirectory = dir.exists(); + + return hasDirectory; } /** - * Checks if the data directory exist. + * Creates a data directory. */ - public void checkDirectory() { + public void makeDirectory() { File dir = new File(DIRECTORY); - boolean hasDirectory = dir.exists(); - // Create a directory if the directory does not exist. - if (!hasDirectory) { - dir.mkdir(); - } + // Creates a directory + dir.mkdir(); } /** * Checks if the property file exist. + * + * @return true if the property text file exist and false if it does not */ - public void checkPropertyFile(PropertyList propertyList) { + public boolean checkPropertyFile() { File propertyFile = new File(PROPERTY_PATH); boolean hasPropertyFile = propertyFile.exists(); - if (hasPropertyFile) { - // Load property into the array list - loadProperty(propertyList, propertyFile); - } + + return hasPropertyFile; } + + /** * Checks if the client file exist. + * + * @return true if the client text file exist and false if it does not */ - public void checkClientFile(ClientList clientList) { + public boolean checkClientFile() { File clientFile = new File(CLIENT_PATH); boolean hasClientFile = clientFile.exists(); - if (hasClientFile) { - // Load client into the array list - loadClient(clientList, clientFile); - } + + return hasClientFile; } /** * Checks if the pair file exit. * - * @param pairingList Paring List object that contains the hash map of pair + * @return true if pairing file exist and false if it does not */ - public void checkPair(PairingList pairingList) { + public boolean checkPair() { File pairFile = new File(PAIR_PATH); boolean hasPairFile = pairFile.exists(); - if (!hasPairFile) { - // Load pair into the hash map - loadPair(pairingList, pairFile); + + return hasPairFile; + } + + /** + * Creates a directory if it does not already exist then load the file into the relevant array list and + * hash table if the text file exist. + * + * @param hasDirectory boolean value on whether directory exist + * @param hasPropertyFile boolean value on whether property text file exist + * @param hasClientFile boolean value on whether client text file exist + * @param hasPairingFile boolean value on whether pairing text file exist + * @param clientList the array list containing the list of client + * @param propertyList the array list containing the list of property + * @param pairingList the hash map containing the pairing between client and property + */ + public void loadFiles(boolean hasDirectory, boolean hasPropertyFile, boolean hasClientFile, + boolean hasPairingFile, ClientList clientList, PropertyList propertyList, + PairingList pairingList) { + if (!hasDirectory) { + makeDirectory(); + } + + if (hasClientFile) { + File clientFile = new File(CLIENT_PATH); + loadClient(clientList, clientFile); + } + + if (hasPropertyFile) { + File propertyFile = new File(PROPERTY_PATH); + loadProperty(propertyList, propertyFile); + } + + if (hasPairingFile) { + File pairingFile = new File(PAIR_PATH); + loadPair(pairingList, pairingFile); } } From 70ada0d3bb5316c7ac70027dc7a230b73d192c80 Mon Sep 17 00:00:00 2001 From: "MSI\\User" Date: Tue, 11 Oct 2022 17:25:26 +0800 Subject: [PATCH 037/325] Add update file function for Client --- src/main/java/seedu/duke/Storage.java | 36 +++++++++++++++++++ .../duke/command/CommandDeleteClient.java | 1 + 2 files changed, 37 insertions(+) diff --git a/src/main/java/seedu/duke/Storage.java b/src/main/java/seedu/duke/Storage.java index 3e686dcca..d533895f5 100644 --- a/src/main/java/seedu/duke/Storage.java +++ b/src/main/java/seedu/duke/Storage.java @@ -4,6 +4,7 @@ import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; +import java.util.ArrayList; import java.util.Scanner; public class Storage { @@ -244,5 +245,40 @@ public void addToPairFile(String client, String contact, String landlord, } catch (IOException e) { System.out.println("Pairing file does not exist."); } + } + + /** + * Updates the client list when entry in client list is deleted. + * @param clientList The array list containing all the clients. + */ + public void updateClient(ClientList clientList) { + try { + FileWriter clientFile = new FileWriter(CLIENT_PATH); + ArrayList clientLists = clientList.getClientList(); + + // clientText will initially be empty and will be appended in subsequent iterations of the client list. + String clientText = ""; + for (int i = 0; i < clientLists.size(); i += 1) { + // Concatenate the string variables into clientText + String budgetPrice = CURRENCY + clientLists.get(i).getClientBudgetPerMonth(); + String name = clientLists.get(i).getClientName(); + String contact = clientLists.get(i).getClientContactNumber(); + String email = clientLists.get(i).getClientEmail(); + String finalText = name + SEPARATOR + contact + SEPARATOR + email + SEPARATOR + + budgetPrice + System.lineSeparator(); + clientText = clientText.concat(finalText); + } + + // Write the client list into a file. + clientFile.write(clientText); + clientFile.close(); + + } catch (IOException e) { + System.out.println("Client file does not exist."); + } + + + + } } diff --git a/src/main/java/seedu/duke/command/CommandDeleteClient.java b/src/main/java/seedu/duke/command/CommandDeleteClient.java index 3dd9babf5..ccf8aab30 100644 --- a/src/main/java/seedu/duke/command/CommandDeleteClient.java +++ b/src/main/java/seedu/duke/command/CommandDeleteClient.java @@ -24,5 +24,6 @@ public void execute(Ui ui, Storage storage, PropertyList propertyList, Client deletedClient = clientList.deleteClient(clientIndex); ui.showClientDeletedConfirmationMessage(deletedClient); //Update Storage + storage.updateClient(clientList); } } From f8c81954577e67855b3822e89ed18f5c7a08c5a3 Mon Sep 17 00:00:00 2001 From: ngdeqi Date: Tue, 11 Oct 2022 18:29:38 +0800 Subject: [PATCH 038/325] Make PairingList addPairing compatible with Storage, add assertions and edit documentation --- src/main/java/seedu/duke/Duke.java | 2 +- src/main/java/seedu/duke/PairingList.java | 57 ++++++++++++++++------- 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 2c2127cc4..11807e956 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -49,7 +49,7 @@ public void run() throws IOException { do { try { -// System.exit(0); //to pass CI + System.exit(0); //to pass CI String userInputText = ui.readCommand(); command = parser.parseCommand(userInputText); command.execute(ui, storage, propertyList, clientList, pairingList); diff --git a/src/main/java/seedu/duke/PairingList.java b/src/main/java/seedu/duke/PairingList.java index c009ed44e..a5605790e 100644 --- a/src/main/java/seedu/duke/PairingList.java +++ b/src/main/java/seedu/duke/PairingList.java @@ -7,65 +7,86 @@ */ public class PairingList { private static final String SEPARATOR = " | "; + private static final String CURRENCY = "SGD"; + private static final String OPEN_BRACKET = "["; + private static final String CLOSE_BRACKET = "]"; private static final HashMap clientPropertyPairs = new HashMap<>(); + /** + * Default Constructor. + */ public PairingList() { } /** - * Records which property a client is renting. + * Records which property a client is renting, with Client and Property objects as parameters. * @param client Client renting the property. * @param property Property being rented. */ public void addPairing(Client client, Property property) { String clientPairingData = convertToPairingData(client); String propertyPairingData = convertToPairingData(property); + addPairing(clientPairingData, propertyPairingData); + } + /** + * Records which property a client is renting, with the client and property in the appropriate pairing formats as + * parameters. This is used to load the pairings from the pairing data file into the class variable. + * @param clientPairingData Pairing data of client that is renting the property. + * @param propertyPairingData Pairing data of property that is being rented. + */ + public void addPairing(String clientPairingData, String propertyPairingData) { + assert !clientPropertyPairs.containsKey(clientPairingData) : "CommandPair: client is already renting property"; clientPropertyPairs.put(clientPairingData, propertyPairingData); } /** - * Removes a client-property pair to indicate that the client is no longer renting that property. + * Deletes client-property pair to indicate that the client is no longer renting that property. * @param client Client who is no longer renting the property. - * @param property Property that is no loner being rented. + * @param property Property that is no longer being rented. */ public void deletePairing(Client client, Property property) { - String clientPairingData = convertToPairingData(client); String propertyPairingData = convertToPairingData(property); + assert clientPropertyPairs.containsKey(clientPairingData) : "CommandUnpair: client is not renting property"; clientPropertyPairs.remove(clientPairingData, propertyPairingData); } + /** + * Returns true if the client is paired with a property. + * @param client Client whose pairing status is being checked. + * @return True if the client is currently paired with a property. False if not paired with a property + */ public boolean isClientPairedWithProperty(Client client) { String clientPairingData = convertToPairingData(client); return clientPropertyPairs.containsKey(clientPairingData); } /** - * Overloaded method to convert client pairing data to a suitable string format. + * Converts client pairing data to a suitable string format. * @param client Client whose data is to be converted. - * @return Pairing data in a suitable string format. + * @return Client pairing data in a suitable string format. */ - private String convertToPairingData(Client client) { - return client.getClientName() + SEPARATOR + client.getClientContactNumber(); + public String convertToPairingData(Client client) { + return OPEN_BRACKET + client.getClientName() + + SEPARATOR + client.getClientContactNumber() + + CLOSE_BRACKET; } /** - * Overloaded method to convert property pairing data to a suitable string format. + * Converts property pairing data to a suitable string format. * @param property Property whose data is to be converted. - * @return Pairing data in a suitable string format. + * @return Property pairing data in a suitable string format. */ - private String convertToPairingData(Property property) { - return property.getLandlordName() - + SEPARATOR - + property.getPropertyAddress() - + SEPARATOR - + property.getRentingPrice() - + SEPARATOR - + property.getUnitType(); + public String convertToPairingData(Property property) { + return OPEN_BRACKET + property.getLandlordName() + + SEPARATOR + property.getPropertyAddress() + + SEPARATOR + CURRENCY + property.getRentingPrice() + + SEPARATOR + property.getUnitType() + + CLOSE_BRACKET; } } From d25b7b573d1bdb7fbf6c117d3f279ca0d38d4265 Mon Sep 17 00:00:00 2001 From: "LAPTOP-S1RS66RO\\marcu" Date: Tue, 11 Oct 2022 19:31:54 +0800 Subject: [PATCH 039/325] Implementation of Add Property with Singapore Address and Renting Price Validation --- src/main/java/seedu/duke/Client.java | 9 +- src/main/java/seedu/duke/Duke.java | 9 + .../duke/EmptyPropertyDetailException.java | 7 + ...ncorrectAddPropertyFlagOrderException.java | 7 + .../duke/InvalidPriceFormatException.java | 7 + .../InvalidSingaporeAddressException.java | 7 + src/main/java/seedu/duke/Messages.java | 30 ++ .../duke/MissingPropertyDetailException.java | 7 + .../duke/MissingPropertyFlagException.java | 7 + src/main/java/seedu/duke/Parser.java | 298 ++++++++++++++---- src/main/java/seedu/duke/Property.java | 22 ++ src/main/java/seedu/duke/PropertyList.java | 32 +- src/main/java/seedu/duke/Ui.java | 35 +- .../seedu/duke/command/CommandAddClient.java | 1 + .../duke/command/CommandAddProperty.java | 38 +++ 15 files changed, 440 insertions(+), 76 deletions(-) create mode 100644 src/main/java/seedu/duke/EmptyPropertyDetailException.java create mode 100644 src/main/java/seedu/duke/IncorrectAddPropertyFlagOrderException.java create mode 100644 src/main/java/seedu/duke/InvalidPriceFormatException.java create mode 100644 src/main/java/seedu/duke/InvalidSingaporeAddressException.java create mode 100644 src/main/java/seedu/duke/MissingPropertyDetailException.java create mode 100644 src/main/java/seedu/duke/MissingPropertyFlagException.java create mode 100644 src/main/java/seedu/duke/command/CommandAddProperty.java diff --git a/src/main/java/seedu/duke/Client.java b/src/main/java/seedu/duke/Client.java index 5d24b44af..51a98def2 100644 --- a/src/main/java/seedu/duke/Client.java +++ b/src/main/java/seedu/duke/Client.java @@ -19,13 +19,14 @@ public Client(String clientName, String clientContactNumber, String clientEmail, @Override public String toString() { StringBuilder clientDetails = new StringBuilder(); - clientDetails.append(" Client: " + clientName).append(System.lineSeparator()); - clientDetails.append(" Contact Number: " + clientContactNumber).append(System.lineSeparator()); + clientDetails.append(" Client: ").append(clientName).append(System.lineSeparator()); + clientDetails.append(" Contact Number: ").append(clientContactNumber).append(System.lineSeparator()); boolean hasEmail = (!clientEmail.isEmpty()); if (hasEmail) { - clientDetails.append(" Email: " + clientEmail).append(System.lineSeparator()); + clientDetails.append(" Email: ").append(clientEmail).append(System.lineSeparator()); } - clientDetails.append(" Budget: SGD" + clientBudgetPerMonth + "/month").append(System.lineSeparator()); + clientDetails.append(" Budget: SGD").append(clientBudgetPerMonth).append("/month") + .append(System.lineSeparator()); return clientDetails.toString().trim(); } } diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 6e556cffb..68339fca9 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -33,6 +33,15 @@ public void run() throws IOException { ui.showMissingCommandAddDetailMessage(); } catch (UndefinedSubCommandAddTypeException e) { ui.showUndefinedSubCommandAddTypeMessage(); + } catch (EmptyPropertyDetailException e) { + ui.showEmptyPropertyDetailMessage(); + } catch (MissingPropertyFlagException | IncorrectAddPropertyFlagOrderException + | MissingPropertyDetailException e) { + ui.showAddPropertyWrongFormatMessage(); + } catch (InvalidSingaporeAddressException e) { + ui.showInvalidSingaporeAddressMessage(); + } catch (InvalidPriceFormatException e) { + ui.showInvalidPriceFormatMessage(); } catch (EmptyClientDetailException e) { ui.showEmptyClientDetailMessage(); } catch (MissingClientFlagException | IncorrectAddClientFlagOrderException diff --git a/src/main/java/seedu/duke/EmptyPropertyDetailException.java b/src/main/java/seedu/duke/EmptyPropertyDetailException.java new file mode 100644 index 000000000..3480c62ef --- /dev/null +++ b/src/main/java/seedu/duke/EmptyPropertyDetailException.java @@ -0,0 +1,7 @@ +package seedu.duke; + +/** + * Represents exception when no property description is given when adding property. + */ +public class EmptyPropertyDetailException extends DukeException { +} diff --git a/src/main/java/seedu/duke/IncorrectAddPropertyFlagOrderException.java b/src/main/java/seedu/duke/IncorrectAddPropertyFlagOrderException.java new file mode 100644 index 000000000..2f1784747 --- /dev/null +++ b/src/main/java/seedu/duke/IncorrectAddPropertyFlagOrderException.java @@ -0,0 +1,7 @@ +package seedu.duke; + +/** + * Represents exception when incorrect flag order is given when adding property. + */ +public class IncorrectAddPropertyFlagOrderException extends IncorrectFlagOrderException { +} diff --git a/src/main/java/seedu/duke/InvalidPriceFormatException.java b/src/main/java/seedu/duke/InvalidPriceFormatException.java new file mode 100644 index 000000000..375e1fb60 --- /dev/null +++ b/src/main/java/seedu/duke/InvalidPriceFormatException.java @@ -0,0 +1,7 @@ +package seedu.duke; + +/** + * Represents exception when incorrect format for renting_price/month is given when adding property. + */ +public class InvalidPriceFormatException extends DukeException { +} diff --git a/src/main/java/seedu/duke/InvalidSingaporeAddressException.java b/src/main/java/seedu/duke/InvalidSingaporeAddressException.java new file mode 100644 index 000000000..c32617733 --- /dev/null +++ b/src/main/java/seedu/duke/InvalidSingaporeAddressException.java @@ -0,0 +1,7 @@ +package seedu.duke; + +/** + * Represents exception when invalid Singapore Address is provided when adding property. + */ +public class InvalidSingaporeAddressException extends DukeException { +} diff --git a/src/main/java/seedu/duke/Messages.java b/src/main/java/seedu/duke/Messages.java index d9c8ede50..27ab004d1 100644 --- a/src/main/java/seedu/duke/Messages.java +++ b/src/main/java/seedu/duke/Messages.java @@ -4,6 +4,8 @@ * Container for user visible messages. */ public class Messages { + public static final String MESSAGE_PROPERTY_ADDED = "Adding a property with the following information:"; + public static final String MESSAGE_CLIENT_ADDED = "Adding a client with the following information:"; public static final String MESSAGE_EMPTY_ADD_DESCRIPTION = "OOPS!!! The description for add cannot be empty."; @@ -13,8 +15,18 @@ public class Messages { + "For client: add -client\n" + "For property: add -property"; + public static final String MESSAGE_EMPTY_PROPERTY_DESCRIPTION = "OOPS!!! The description of property " + + "cannot be empty."; + public static final String MESSAGE_EMPTY_CLIENT_DESCRIPTION = "OOPS!!! The description of client cannot be empty."; + public static final String MESSAGE_ADD_PROPERTY_WRONG_FORMAT = "OOPS!!! To add a property, it requires " + + "the following format and details as shown below."; + + public static final String MESSAGE_PROPERTY_INPUT_EXAMPLE = "Format: add -property n/NAME a/ADDRESS p/PRICE t/TYPE" + + "\nExample: add -property n/Bob Tan Bee Bee a/25 Lower Kent Ridge Rd, Singapore 119081 " + + "p/1000 t/HDB 3 Room"; + public static final String MESSAGE_ADD_CLIENT_WRONG_FORMAT = "OOPS!!! To add a client, it requires " + "the following format and details as shown below."; @@ -25,6 +37,24 @@ public class Messages { public static final String MESSAGE_TRY_AGAIN = "Please try again."; + public static final String MESSAGE_INVALID_SINGAPORE_ADDRESS = "OOPS!!! The address provided is invalid. " + + "To add a property, A valid Singapore address must be provided\nwith the following " + + "format and details as shown below."; + + public static final String MESSAGE_VALID_SINGAPORE_ADDRESS_EXAMPLE = "LANDED PROPERTY:\n Format: " + + "[Unit Number][Street Name],Singapore[Postal Code]\n" + + " Example: 60 Aria Street, Singapore 602580\n" + + "BUILDINGS (e.g. HDBs, apartments, condominiums):\n" + + " Format (Without Building Name):\n [Block Number][Street Name]" + + "#[Unit Level]-[Unit Number]{[Building Name]},Singapore[Postal Code]\n" + + " Example: 101 Marlow Street #12-05, Singapore 059020\n" + + " Example (With Building Name): 101 Marlow Street #12-05 Clife Parkview, Singapore 059020\n" + + "Note: Format is sensitive; [Detail] must be provided; {Detail} is optional\n" + + "Any deviation from format will lead to invalid address."; + + public static final String MESSAGE_INVALID_PRICE_FORMAT = "OOPS!!! Please enter positive number " + + "(No letter/symbols, etc) for renting price per month for property"; + public static final String MESSAGE_INVALID_CONTACT_NUMBER = "OOPS!!! Please enter a valid Singapore Contact Number " + "(No extension)"; diff --git a/src/main/java/seedu/duke/MissingPropertyDetailException.java b/src/main/java/seedu/duke/MissingPropertyDetailException.java new file mode 100644 index 000000000..1e7d7cae2 --- /dev/null +++ b/src/main/java/seedu/duke/MissingPropertyDetailException.java @@ -0,0 +1,7 @@ +package seedu.duke; + +/** + * Represents exception when there is missing property details when adding property. + */ +public class MissingPropertyDetailException extends DukeException { +} diff --git a/src/main/java/seedu/duke/MissingPropertyFlagException.java b/src/main/java/seedu/duke/MissingPropertyFlagException.java new file mode 100644 index 000000000..fd2f793f3 --- /dev/null +++ b/src/main/java/seedu/duke/MissingPropertyFlagException.java @@ -0,0 +1,7 @@ +package seedu.duke; + +/** + * Represents exception when there is missing property flags when adding property. + */ +public class MissingPropertyFlagException extends MissingFlagException { +} diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index f67eeffe4..401c2a92f 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -1,6 +1,7 @@ package seedu.duke; import seedu.duke.command.Command; +import seedu.duke.command.CommandAddProperty; import seedu.duke.command.CommandAddClient; import seedu.duke.command.CommandUndefined; @@ -8,12 +9,15 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; - public class Parser { public static final int ADD_CLIENT_FLAG_SIZE = 4; + public static final int ADD_PROPERTY_FLAG_SIZE = 4; + public Command parseCommand(String input) throws EmptyCommandAddDetailException, - UndefinedSubCommandAddTypeException, EmptyClientDetailException, MissingClientFlagException, + UndefinedSubCommandAddTypeException, EmptyPropertyDetailException, MissingPropertyFlagException, + IncorrectAddPropertyFlagOrderException, MissingPropertyDetailException, InvalidSingaporeAddressException, + InvalidPriceFormatException, EmptyClientDetailException, MissingClientFlagException, IncorrectAddClientFlagOrderException, MissingClientDetailException, InvalidContactNumberException, InvalidEmailException, InvalidBudgetFormatException { ArrayList processedCommandDetails = partitionCommandTypeAndDetails(input); @@ -26,7 +30,9 @@ public Command parseCommand(String input) throws EmptyCommandAddDetailException, String subCommandType = processedAddCommandDetails.get(0); String clientOrPropertyDescriptions = processedAddCommandDetails.get(1); - if (subCommandType.equals("-client")) { + if (subCommandType.equals("-property")) { + return prepareForCommandAddProperty(clientOrPropertyDescriptions); + } else if (subCommandType.equals("-client")) { return prepareForCommandAddClient(clientOrPropertyDescriptions); } else { throw new UndefinedSubCommandAddTypeException(); @@ -55,6 +61,21 @@ private void checkForEmptyCommandAddDetails(String commandAddDetails) throws Emp } } + private Command prepareForCommandAddProperty(String rawPropertyDescriptions) throws EmptyPropertyDetailException, + MissingPropertyFlagException, IncorrectAddPropertyFlagOrderException, MissingPropertyDetailException, + InvalidSingaporeAddressException, InvalidPriceFormatException { + checkForEmptyAddPropertyDetails(rawPropertyDescriptions); + try { + ArrayList propertyDetails = processPropertyDetails(rawPropertyDescriptions); + validatePropertyDetails(propertyDetails); + return new CommandAddProperty(propertyDetails); + } catch (MissingFlagException e) { + throw new MissingPropertyFlagException(); + } catch (IncorrectFlagOrderException e) { + throw new IncorrectAddPropertyFlagOrderException(); + } + } + private Command prepareForCommandAddClient(String rawClientDescriptions) throws EmptyClientDetailException, MissingClientFlagException, IncorrectAddClientFlagOrderException, MissingClientDetailException, InvalidContactNumberException, InvalidEmailException, InvalidBudgetFormatException { @@ -70,74 +91,37 @@ private Command prepareForCommandAddClient(String rawClientDescriptions) throws } } - private void validateClientDetails(ArrayList clientDetails) throws MissingClientDetailException, - InvalidContactNumberException, InvalidEmailException, InvalidBudgetFormatException { - //Checks for Missing Client Name, Contact Number, Budget Per Month (SGD) - checkForMissingClientDetails(clientDetails.get(0)); - checkForMissingClientDetails(clientDetails.get(1)); - checkForMissingClientDetails(clientDetails.get(3)); - - //Checks for Contact Number, Email and Budget Format - checkForValidSingaporeContactNumber(clientDetails.get(1)); - boolean hasEmail = !clientDetails.get(2).isEmpty(); - if (hasEmail) { - checkForValidEmail(clientDetails.get(2)); - } - checkForBudgetNumberFormat(clientDetails.get(3)); - } - - private void checkForValidSingaporeContactNumber(String clientContactNumber) throws InvalidContactNumberException { - boolean hasValidContactNumber = checkForDetailFormat("^[689]\\d{7}$", clientContactNumber); - if (!hasValidContactNumber) { - throw new InvalidContactNumberException(); - } - } - - private void checkForValidEmail(String clientEmail) throws InvalidEmailException { - //General Email Regex (RFC 5322 Official Standard) - String regex = "(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\" - + "x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-" - + "9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-" - + "9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0" - + "c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])"; - boolean hasValidContactNumber = checkForDetailFormat(regex, clientEmail); - if (!hasValidContactNumber) { - throw new InvalidEmailException(); + private void checkForEmptyAddPropertyDetails(String commandAddDescriptions) throws EmptyPropertyDetailException { + boolean isEmptyCommandAddDetail = checkForEmptyDetail(commandAddDescriptions); + if (isEmptyCommandAddDetail) { + throw new EmptyPropertyDetailException(); } } - private void checkForBudgetNumberFormat(String budget) throws InvalidBudgetFormatException { - //Accepts only positive whole number - String regex = "^[1-9]\\d*$"; - boolean hasValidBudgetNumberFormat = checkForDetailFormat(regex, budget); - if (!hasValidBudgetNumberFormat) { - throw new InvalidBudgetFormatException(); + private void checkForEmptyAddClientDetails(String commandAddDescriptions) throws EmptyClientDetailException { + boolean isEmptyCommandAddDetail = checkForEmptyDetail(commandAddDescriptions); + if (isEmptyCommandAddDetail) { + throw new EmptyClientDetailException(); } } - private boolean checkForDetailFormat(String regex, String detail) { - Pattern pattern = Pattern.compile(regex); - Matcher matcher = pattern.matcher(detail); - return matcher.matches(); - } + private ArrayList processPropertyDetails(String rawPropertyDetails) throws MissingFlagException, + IncorrectFlagOrderException { + String[] addPropertyFlags = {"n/", "a/", "p/", "t/"}; + int[] addPropertyFlagIndexPositions = new int[ADD_PROPERTY_FLAG_SIZE]; - private void checkForMissingClientDetails(String clientDetail) throws MissingClientDetailException { - boolean isEmptyDetail = checkForEmptyDetail(clientDetail); - if (isEmptyDetail) { - throw new MissingClientDetailException(); + for (int i = 0; i < addPropertyFlags.length; i++) { + addPropertyFlagIndexPositions[i] = rawPropertyDetails.indexOf(addPropertyFlags[i]); } - } - private void checkForEmptyAddClientDetails(String commandAddDescriptions) throws EmptyClientDetailException { - boolean isEmptyCommandAddDetail = checkForEmptyDetail(commandAddDescriptions); - if (isEmptyCommandAddDetail) { - throw new EmptyClientDetailException(); - } + checkForMissingPropertyFlags(addPropertyFlagIndexPositions); + checkForPropertyFlagsOrder(addPropertyFlagIndexPositions); + return extractPropertyDetails(rawPropertyDetails, addPropertyFlagIndexPositions); } private ArrayList processClientDetails(String rawClientDetails) throws MissingFlagException, IncorrectFlagOrderException { - String[] addClientFlags = {"n/", "c/", "e/", "b/"}; + String[] addClientFlags = {"n/", "c/", "e/", "b/"}; int[] addClientFlagIndexPositions = new int[ADD_CLIENT_FLAG_SIZE]; for (int i = 0; i < addClientFlags.length; i++) { @@ -149,12 +133,32 @@ private ArrayList processClientDetails(String rawClientDetails) throws M return extractClientDetails(rawClientDetails, addClientFlagIndexPositions); } + private void checkForMissingPropertyFlags(int[] addPropertyFlagIndexPositions) throws MissingFlagException { + for (int propertyFlagIndex : addPropertyFlagIndexPositions) { + checkForEssentialAddFlag(propertyFlagIndex); + } + } + private void checkForMissingClientFlags(int[] addClientFlagIndexPositions) throws MissingFlagException { checkForEssentialAddFlag(addClientFlagIndexPositions[0]); checkForEssentialAddFlag(addClientFlagIndexPositions[1]); checkForEssentialAddFlag(addClientFlagIndexPositions[3]); } + private void checkForEssentialAddFlag(int addClientFlagIndexes) throws MissingFlagException { + boolean hasFlag = (addClientFlagIndexes != -1); + if (!hasFlag) { + throw new MissingFlagException(); + } + } + + private void checkForPropertyFlagsOrder(int[] addPropertyFlagIndexPositions) throws IncorrectFlagOrderException { + for (int propertyFlagIndex = 0; propertyFlagIndex < ADD_PROPERTY_FLAG_SIZE - 1; propertyFlagIndex++) { + checkForCorrectFlagOrder(addPropertyFlagIndexPositions[propertyFlagIndex], + addPropertyFlagIndexPositions[propertyFlagIndex + 1]); + } + } + private void checkForClientFlagsOrder(int[] addClientFlagIndexPositions) throws IncorrectFlagOrderException { boolean hasEmail = (addClientFlagIndexPositions[2] != -1); checkForCorrectFlagOrder(addClientFlagIndexPositions[0], addClientFlagIndexPositions[1]); @@ -165,6 +169,30 @@ private void checkForClientFlagsOrder(int[] addClientFlagIndexPositions) throws } } + private void checkForCorrectFlagOrder(int flagPosition, int nextFlagPosition) throws IncorrectFlagOrderException { + boolean hasCorrectOrder = (flagPosition < nextFlagPosition); + if (!hasCorrectOrder) { + throw new IncorrectFlagOrderException(); + } + } + + private ArrayList extractPropertyDetails(String rawPropertyDetails, int[] addPropertyFlagIndexPositions) { + String landlordName = extractDetail(rawPropertyDetails, addPropertyFlagIndexPositions[0] + 2, + addPropertyFlagIndexPositions[1]); + String propertyAddress = extractDetail(rawPropertyDetails, addPropertyFlagIndexPositions[1] + 2, + addPropertyFlagIndexPositions[2]); + String rentingPrice = extractDetail(rawPropertyDetails, addPropertyFlagIndexPositions[2] + 2, + addPropertyFlagIndexPositions[3]); + String unitType = extractDetail(rawPropertyDetails, addPropertyFlagIndexPositions[3] + 2); + + ArrayList processedPropertyDetails = new ArrayList<>(); + processedPropertyDetails.add(landlordName.trim()); + processedPropertyDetails.add(propertyAddress.trim()); + processedPropertyDetails.add(rentingPrice.trim()); + processedPropertyDetails.add(unitType.trim()); + return processedPropertyDetails; + } + private ArrayList extractClientDetails(String rawClientDetails, int[] addClientFlagIndexPositions) { boolean hasEmail = (addClientFlagIndexPositions[2] != -1); String clientContactNumber; @@ -190,29 +218,159 @@ private ArrayList extractClientDetails(String rawClientDetails, int[] ad return processedClientDetails; } - private void checkForEssentialAddFlag(int addClientFlagIndexes) throws MissingFlagException { - boolean hasFlag = (addClientFlagIndexes != -1); - if (!hasFlag) { - throw new MissingFlagException(); + private static String extractDetail(String rawDetails, int beginIndex) { + return rawDetails.substring(beginIndex).trim(); + } + + private static String extractDetail(String rawDetails, int beginIndex, int endIndex) { + return rawDetails.substring(beginIndex, endIndex).trim(); + } + + private void validatePropertyDetails(ArrayList propertyDetails) throws MissingPropertyDetailException, + InvalidSingaporeAddressException, InvalidPriceFormatException { + //Checks for Missing Landlord Name, Property Address, Renting Price (SGD/month) and Unit-Type + for (String propertyDetail : propertyDetails) { + checkForMissingPropertyDetails(propertyDetail); } + + //Checks Format for Address (Singapore) and Renting Price + checkForValidSingaporeAddress(propertyDetails.get(1)); + checkForPriceNumberFormat(propertyDetails.get(2)); } - private void checkForCorrectFlagOrder(int flagPosition, int nextFlagPosition) throws IncorrectFlagOrderException { - boolean hasCorrectOrder = (flagPosition < nextFlagPosition); - if (!hasCorrectOrder) { - throw new IncorrectFlagOrderException(); + private void validateClientDetails(ArrayList clientDetails) throws MissingClientDetailException, + InvalidContactNumberException, InvalidEmailException, InvalidBudgetFormatException { + //Checks for Missing Client Name, Contact Number, Budget Per Month (SGD) + checkForMissingClientDetails(clientDetails.get(0)); + checkForMissingClientDetails(clientDetails.get(1)); + checkForMissingClientDetails(clientDetails.get(3)); + + //Checks for Contact Number, Email and Budget Format + checkForValidSingaporeContactNumber(clientDetails.get(1)); + boolean hasEmail = !clientDetails.get(2).isEmpty(); + if (hasEmail) { + checkForValidEmail(clientDetails.get(2)); } + checkForBudgetNumberFormat(clientDetails.get(3)); } - private static String extractDetail(String rawClientDetails, int beginIndex) { - return rawClientDetails.substring(beginIndex).trim(); + private void checkForMissingPropertyDetails(String propertyDetail) throws MissingPropertyDetailException { + boolean isEmptyDetail = checkForEmptyDetail(propertyDetail); + if (isEmptyDetail) { + throw new MissingPropertyDetailException(); + } } - private static String extractDetail(String rawClientDetails, int beginIndex, int endIndex) { - return rawClientDetails.substring(beginIndex, endIndex).trim(); + private void checkForMissingClientDetails(String clientDetail) throws MissingClientDetailException { + boolean isEmptyDetail = checkForEmptyDetail(clientDetail); + if (isEmptyDetail) { + throw new MissingClientDetailException(); + } } private boolean checkForEmptyDetail(String commandDetails) { return commandDetails.trim().isEmpty(); } + + private void checkForValidSingaporeAddress(String address) throws InvalidSingaporeAddressException { + boolean hasValidSingaporeLandedPropertyAddress = checkForValidSingaporeLandedPropertyAddress(address); + boolean hasValidSingaporeBuildingAddress = checkForValidSingaporeBuildingAddress(address); + + boolean hasValidSingaporeAddress = hasValidSingaporeLandedPropertyAddress || hasValidSingaporeBuildingAddress; + if (!hasValidSingaporeAddress) { + throw new InvalidSingaporeAddressException(); + } + } + + private boolean checkForValidSingaporeLandedPropertyAddress(String address) { + String landedPropertyUnitNumberRegex = "^([0-9]{1,4})([A-Z]?) "; + String streetNameRegex = "[^.!@#$%^&*()_+=<>\\s\\n?`~0-9,{}|-]([a-zA-Z\\s]+)[^.!@#$%^&*()_+=<>\\s\\n?`~0-9," + + "{}|-]"; + String streetNumberRegex = " ([1-9]{1}[0-9]{0,3})"; + String postalCodeRegex = ", (Singapore [0-9]{6})$"; + + String landedPropertyAddressRegex = landedPropertyUnitNumberRegex + streetNameRegex + postalCodeRegex; + String landedPropertyAddressWithStreetNumberRegex = landedPropertyUnitNumberRegex + streetNameRegex + + streetNumberRegex + postalCodeRegex; + + boolean hasValidLandedPropertyAddress = checkForDetailFormat(landedPropertyAddressRegex, address); + boolean hasValidLandedPropertyAddressWithStreetNumber + = checkForDetailFormat(landedPropertyAddressWithStreetNumberRegex, address); + return hasValidLandedPropertyAddress || hasValidLandedPropertyAddressWithStreetNumber; + } + + private boolean checkForValidSingaporeBuildingAddress(String address) { + String buildingBlockNumberRegex = "^([0-9]{1,4})([A-Z]?) "; + String streetNameRegex = "[^.!@#$%^&*()_+=<>\\s\\n?`~0-9,{}|-]([a-zA-Z\\s]+)[^.!@#$%^&*()_+=<>\\s\\n?`~0-9," + + "{}|-]"; + String streetNumberRegex = " ([1-9]{1}[0-9]{0,3})"; + String buildingUnitFloorAndNumberRegex = " #(([0]{1}[1-9]{1})|([1-9]{1}[0-9]{1,2}))-(([0]{1}[1-9]{1})|([1-9]" + + "{1}[0-9]{1,3}))([A-Z]?)"; + String buildingNameRegex = " [^.!@#$%^&*()_+=<>\\s\\n?`~0-9,{}|-]([a-zA-Z\\s]+)[^.!@#$%^&*()_+=<>\\s\\n?`~0-9" + + ",{}|-]"; + String postalCodeRegex = ", (Singapore [0-9]{6})$"; + + String buildingAddressRegex = buildingBlockNumberRegex + streetNameRegex + buildingUnitFloorAndNumberRegex + + postalCodeRegex; + String buildingAddressWithStreetNumberRegex = buildingBlockNumberRegex + streetNameRegex + streetNumberRegex + + buildingUnitFloorAndNumberRegex + postalCodeRegex; + String buildingAddressWithBuildingNameRegex = buildingBlockNumberRegex + streetNameRegex + + buildingUnitFloorAndNumberRegex + buildingNameRegex + postalCodeRegex; + String buildingAddressWithStreetNumberAndBuildingNameRegex = buildingBlockNumberRegex + streetNameRegex + + streetNumberRegex + buildingUnitFloorAndNumberRegex + buildingNameRegex + postalCodeRegex; + + boolean hasValidBuildingAddress = checkForDetailFormat(buildingAddressRegex, address); + boolean hasValidBuildingAddressWithStreetNumber + = checkForDetailFormat(buildingAddressWithStreetNumberRegex, address); + boolean hasValidBuildingAddressWithBuildingName + = checkForDetailFormat(buildingAddressWithBuildingNameRegex, address); + boolean hasValidBuildingAddressWithStreetNumberAndBuildingName + = checkForDetailFormat(buildingAddressWithStreetNumberAndBuildingNameRegex, address); + return hasValidBuildingAddress || hasValidBuildingAddressWithStreetNumber + || hasValidBuildingAddressWithBuildingName || hasValidBuildingAddressWithStreetNumberAndBuildingName; + } + + private void checkForPriceNumberFormat(String budget) throws InvalidPriceFormatException { + //Accepts only positive whole number + String regex = "^[1-9]\\d*$"; + boolean hasValidPriceNumberFormat = checkForDetailFormat(regex, budget); + if (!hasValidPriceNumberFormat) { + throw new InvalidPriceFormatException(); + } + } + + private void checkForValidSingaporeContactNumber(String clientContactNumber) throws InvalidContactNumberException { + boolean hasValidContactNumber = checkForDetailFormat("^[689]\\d{7}$", clientContactNumber); + if (!hasValidContactNumber) { + throw new InvalidContactNumberException(); + } + } + + private void checkForValidEmail(String clientEmail) throws InvalidEmailException { + //General Email Regex (RFC 5322 Official Standard) + String regex = "(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\" + + "x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-" + + "9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-" + + "9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0" + + "c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])"; + boolean hasValidContactNumber = checkForDetailFormat(regex, clientEmail); + if (!hasValidContactNumber) { + throw new InvalidEmailException(); + } + } + + private void checkForBudgetNumberFormat(String budget) throws InvalidBudgetFormatException { + //Accepts only positive whole number + String regex = "^[1-9]\\d*$"; + boolean hasValidBudgetNumberFormat = checkForDetailFormat(regex, budget); + if (!hasValidBudgetNumberFormat) { + throw new InvalidBudgetFormatException(); + } + } + + private boolean checkForDetailFormat(String regex, String detail) { + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(detail); + return matcher.matches(); + } } diff --git a/src/main/java/seedu/duke/Property.java b/src/main/java/seedu/duke/Property.java index 09e562999..a4c8224c7 100644 --- a/src/main/java/seedu/duke/Property.java +++ b/src/main/java/seedu/duke/Property.java @@ -1,4 +1,26 @@ package seedu.duke; +/** + * Represents a property. + */ public class Property { + private String landlordName; + private String propertyAddress; + private String rentingPrice; + private String unitType; + + public Property(String landlordName, String propertyAddress, String rentingPrice, String unitType) { + this.landlordName = landlordName; + this.propertyAddress = propertyAddress; + this.rentingPrice = rentingPrice; + this.unitType = unitType; + } + + public String toString() { + String propertyDetails = " Landlord: " + landlordName + System.lineSeparator() + + " Address: " + propertyAddress + System.lineSeparator() + + " Renting Price: SGD" + rentingPrice + "/month" + System.lineSeparator() + + " Unit Type: " + unitType + System.lineSeparator(); + return propertyDetails.trim(); + } } diff --git a/src/main/java/seedu/duke/PropertyList.java b/src/main/java/seedu/duke/PropertyList.java index aca4419c0..d1c206c06 100644 --- a/src/main/java/seedu/duke/PropertyList.java +++ b/src/main/java/seedu/duke/PropertyList.java @@ -2,6 +2,36 @@ import java.util.ArrayList; +/** + * Stores the list of properties. + */ public class PropertyList { - protected static ArrayList properties = new ArrayList<>(); + private static int currentListSize; + private static ArrayList propertyList; + + public PropertyList() { + propertyList = new ArrayList<>(); + currentListSize = 0; + } + + public int getCurrentListSize() { + return currentListSize; + } + + public ArrayList getPropertyList() { + return propertyList; + } + + /** + * Adds a property to property list and updates property list size. + * + * @param landlordName Name of landlord of property. + * @param propertyAddress Address of property. + * @param rentingPrice Renting price per month for property. + * @param unitType Unit type of property. + */ + public void addProperty(String landlordName, String propertyAddress, String rentingPrice, String unitType) { + propertyList.add(new Property(landlordName, propertyAddress, rentingPrice, unitType)); + currentListSize++; + } } diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index 16270a53f..226d3c8b2 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -2,13 +2,20 @@ import java.util.Scanner; +import static seedu.duke.Messages.MESSAGE_PROPERTY_ADDED; import static seedu.duke.Messages.MESSAGE_CLIENT_ADDED; import static seedu.duke.Messages.MESSAGE_EMPTY_ADD_DESCRIPTION; import static seedu.duke.Messages.MESSAGE_MISSING_SUB_COMMAND_TYPE_FOR_ADD; +import static seedu.duke.Messages.MESSAGE_EMPTY_PROPERTY_DESCRIPTION; import static seedu.duke.Messages.MESSAGE_EMPTY_CLIENT_DESCRIPTION; +import static seedu.duke.Messages.MESSAGE_ADD_PROPERTY_WRONG_FORMAT; +import static seedu.duke.Messages.MESSAGE_PROPERTY_INPUT_EXAMPLE; import static seedu.duke.Messages.MESSAGE_ADD_CLIENT_WRONG_FORMAT; import static seedu.duke.Messages.MESSAGE_CLIENT_INPUT_EXAMPLE; import static seedu.duke.Messages.MESSAGE_TRY_AGAIN; +import static seedu.duke.Messages.MESSAGE_INVALID_SINGAPORE_ADDRESS; +import static seedu.duke.Messages.MESSAGE_VALID_SINGAPORE_ADDRESS_EXAMPLE; +import static seedu.duke.Messages.MESSAGE_INVALID_PRICE_FORMAT; import static seedu.duke.Messages.MESSAGE_INVALID_CONTACT_NUMBER; import static seedu.duke.Messages.MESSAGE_INVALID_EMAIL; import static seedu.duke.Messages.MESSAGE_INVALID_BUDGET_FORMAT; @@ -36,13 +43,19 @@ public void showToUser(String message) { System.out.println(message); } + public void showPropertyAddedConfirmationMessage(PropertyList propertyList) { + int currentListSize = propertyList.getCurrentListSize(); + showToUser(MESSAGE_PROPERTY_ADDED); + showToUser(" " + propertyList.getPropertyList().get(currentListSize - 1)); + } + public void showClientAddedConfirmationMessage(ClientList clientList) { int currentListSize = clientList.getCurrentListSize(); showToUser(MESSAGE_CLIENT_ADDED); showToUser(" " + clientList.getClientList().get(currentListSize - 1)); } - /* Add Client Related Exceptions */ + /* Add Property/Client Related Exceptions */ public void showMissingCommandAddDetailMessage() { showToUser(MESSAGE_EMPTY_ADD_DESCRIPTION); } @@ -51,16 +64,36 @@ public void showUndefinedSubCommandAddTypeMessage() { showToUser(MESSAGE_MISSING_SUB_COMMAND_TYPE_FOR_ADD); } + public void showEmptyPropertyDetailMessage() { + showToUser(MESSAGE_EMPTY_PROPERTY_DESCRIPTION); + } + public void showEmptyClientDetailMessage() { showToUser(MESSAGE_EMPTY_CLIENT_DESCRIPTION); } + public void showAddPropertyWrongFormatMessage() { + showToUser(MESSAGE_ADD_PROPERTY_WRONG_FORMAT); + showToUser(MESSAGE_PROPERTY_INPUT_EXAMPLE); + showToUser(MESSAGE_TRY_AGAIN); + } + public void showAddClientWrongFormatMessage() { showToUser(MESSAGE_ADD_CLIENT_WRONG_FORMAT); showToUser(MESSAGE_CLIENT_INPUT_EXAMPLE); showToUser(MESSAGE_TRY_AGAIN); } + public void showInvalidSingaporeAddressMessage() { + showToUser(MESSAGE_INVALID_SINGAPORE_ADDRESS); + showToUser(MESSAGE_VALID_SINGAPORE_ADDRESS_EXAMPLE); + showToUser(MESSAGE_TRY_AGAIN); + } + + public void showInvalidPriceFormatMessage() { + showToUser(MESSAGE_INVALID_PRICE_FORMAT); + } + public void showInvalidContactNumberMessage() { showToUser(MESSAGE_INVALID_CONTACT_NUMBER); } diff --git a/src/main/java/seedu/duke/command/CommandAddClient.java b/src/main/java/seedu/duke/command/CommandAddClient.java index bd834363e..6176b5966 100644 --- a/src/main/java/seedu/duke/command/CommandAddClient.java +++ b/src/main/java/seedu/duke/command/CommandAddClient.java @@ -33,5 +33,6 @@ public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientLis clientList.addClient(clientName, clientContactNumber, clientEmail, clientBudgetPerMonth); ui.showClientAddedConfirmationMessage(clientList); //Update Storage + //storage.updateFile(parameter if any); } } diff --git a/src/main/java/seedu/duke/command/CommandAddProperty.java b/src/main/java/seedu/duke/command/CommandAddProperty.java new file mode 100644 index 000000000..e8dbe997b --- /dev/null +++ b/src/main/java/seedu/duke/command/CommandAddProperty.java @@ -0,0 +1,38 @@ +package seedu.duke.command; + +import seedu.duke.ClientList; +import seedu.duke.PropertyList; +import seedu.duke.Storage; +import seedu.duke.Ui; + +import java.util.ArrayList; + +/** + * Adds a property to the property list. + */ +public class CommandAddProperty extends CommandAdd { + private final String landlordName; + private final String propertyAddress; + private final String rentingPrice; + private final String unitType; + + /** + * Constructs constructor for Command Add Property which stores property's Landlord's Name, Address, RentPrice/month + * and Unit Type. + * + * @param propertyDetails Contains information relevant to property + */ + public CommandAddProperty(ArrayList propertyDetails) { + this.landlordName = propertyDetails.get(0); + this.propertyAddress = propertyDetails.get(1); + this.rentingPrice = propertyDetails.get(2); + this.unitType = propertyDetails.get(3); + } + + @Override + public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList) { + propertyList.addProperty(landlordName, propertyAddress, rentingPrice, unitType); + ui.showPropertyAddedConfirmationMessage(propertyList); + //Update Storage + } +} From 2e2e313f84f00274b73c7fa8f94cd16e0db90b78 Mon Sep 17 00:00:00 2001 From: ngdeqi Date: Tue, 11 Oct 2022 22:01:14 +0800 Subject: [PATCH 040/325] Add check property feature --- src/main/java/seedu/duke/Duke.java | 9 ++ src/main/java/seedu/duke/Messages.java | 14 +++ src/main/java/seedu/duke/PairingList.java | 14 +++ src/main/java/seedu/duke/Parser.java | 107 +++++++++++++++++- src/main/java/seedu/duke/Ui.java | 28 +++++ .../java/seedu/duke/command/CommandCheck.java | 7 ++ .../duke/command/CommandCheckProperty.java | 27 +++++ .../EmptyCommandCheckDetailException.java | 4 + .../MissingCheckPropertyFlagException.java | 4 + ...UndefinedSubCommandCheckTypeException.java | 4 + 10 files changed, 212 insertions(+), 6 deletions(-) create mode 100644 src/main/java/seedu/duke/command/CommandCheck.java create mode 100644 src/main/java/seedu/duke/command/CommandCheckProperty.java create mode 100644 src/main/java/seedu/duke/exception/EmptyCommandCheckDetailException.java create mode 100644 src/main/java/seedu/duke/exception/MissingCheckPropertyFlagException.java create mode 100644 src/main/java/seedu/duke/exception/UndefinedSubCommandCheckTypeException.java diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 11807e956..6d5033045 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -5,6 +5,7 @@ import seedu.duke.exception.EmptyClientDetailException; import seedu.duke.exception.EmptyClientIndexDeleteException; import seedu.duke.exception.EmptyCommandAddDetailException; +import seedu.duke.exception.EmptyCommandCheckDetailException; import seedu.duke.exception.EmptyCommandDeleteDetailException; import seedu.duke.exception.EmptyCommandPairUnpairDetailsException; import seedu.duke.exception.ExistingPairException; @@ -14,6 +15,7 @@ import seedu.duke.exception.InvalidClientIndexDeleteException; import seedu.duke.exception.InvalidContactNumberException; import seedu.duke.exception.InvalidEmailException; +import seedu.duke.exception.MissingCheckPropertyFlagException; import seedu.duke.exception.MissingClientDetailException; import seedu.duke.exception.MissingClientFlagException; import seedu.duke.exception.MissingPairUnpairFlagException; @@ -21,6 +23,7 @@ import seedu.duke.exception.NotIntegerException; import seedu.duke.exception.NotValidIndexException; import seedu.duke.exception.UndefinedSubCommandAddTypeException; +import seedu.duke.exception.UndefinedSubCommandCheckTypeException; import seedu.duke.exception.UndefinedSubCommandDeleteTypeException; import java.io.IOException; @@ -89,6 +92,12 @@ public void run() throws IOException { ui.showExistingPairMessage(); } catch (NoExistingPairException e) { ui.showNoExistingPairMessage(); + } catch (MissingCheckPropertyFlagException e) { + ui.showCheckPropertyWrongFormatMessage(); + } catch (UndefinedSubCommandCheckTypeException e) { + ui.showUndefinedSubCommandCheckTypeMessage(); + } catch (EmptyCommandCheckDetailException e) { + ui.showEmptyCommandCheckDetailException(); } } while (!isCommandBye); } diff --git a/src/main/java/seedu/duke/Messages.java b/src/main/java/seedu/duke/Messages.java index abe8e03d4..8dc25dd73 100644 --- a/src/main/java/seedu/duke/Messages.java +++ b/src/main/java/seedu/duke/Messages.java @@ -6,6 +6,8 @@ public class Messages { public static final String MESSAGE_WELCOME = "Welcome to Property Manager! How may I help you?"; + public static final String MESSAGE_NUMBER_OF_LIST_RESULTS = "Number of entries in the list: "; + public static final String MESSAGE_CLIENT_ADDED = "Adding a client with the following information:"; public static final String MESSAGE_EMPTY_ADD_DESCRIPTION = "OOPS!!! The description for add cannot be empty."; @@ -76,5 +78,17 @@ public class Messages { public static final String MESSAGE_NO_EXISTING_PAIR = "OOPS!! This property is not being rented by a tenant. " + "Unpair unsuccessful"; + public static final String MESSAGE_CHECK_PROPERTY_RESULT = "Here are the tenants renthing this property:\n"; + + public static final String MESSAGE_CHECK_PROPERTY_WRONG_FORMAT = "Format:\n" + + " check -property ip/INDEX\n" + + "Example:\n" + + " check -property ip/5"; + + public static final String MESSAGE_MISSING_SUB_COMMAND_TYPE_FOR_CHECK = "OOPS!!! To check, " + + "please specify sub-command type.\n" + + "For property: check -property"; + + public static final String MESSAGE_EMPTY_CHECK_DESCRIPTION = "OOPS!!! The description for check cannot be empty."; } diff --git a/src/main/java/seedu/duke/PairingList.java b/src/main/java/seedu/duke/PairingList.java index a5605790e..ebc2f5d69 100644 --- a/src/main/java/seedu/duke/PairingList.java +++ b/src/main/java/seedu/duke/PairingList.java @@ -1,5 +1,6 @@ package seedu.duke; +import java.util.ArrayList; import java.util.HashMap; /** @@ -65,6 +66,19 @@ public boolean isClientPairedWithProperty(Client client) { return clientPropertyPairs.containsKey(clientPairingData); } + public ArrayList getPropertyTenants(Property property) { + String propertyPairingData = convertToPairingData(property); + ArrayList tenants = new ArrayList<>(); + + for (String clientPairingData : clientPropertyPairs.keySet()) { + if (clientPropertyPairs.get(clientPairingData).equals(propertyPairingData)) { + tenants.add(clientPairingData); + } + } + return tenants; + } + + /** * Converts client pairing data to a suitable string format. * @param client Client whose data is to be converted. diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 5815293ac..364875a1a 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -2,6 +2,7 @@ import seedu.duke.command.Command; import seedu.duke.command.CommandAddClient; +import seedu.duke.command.CommandCheckProperty; import seedu.duke.command.CommandDeleteClient; import seedu.duke.command.CommandPair; import seedu.duke.command.CommandUnpair; @@ -9,6 +10,7 @@ import seedu.duke.exception.EmptyClientDetailException; import seedu.duke.exception.EmptyClientIndexDeleteException; import seedu.duke.exception.EmptyCommandAddDetailException; +import seedu.duke.exception.EmptyCommandCheckDetailException; import seedu.duke.exception.EmptyCommandDeleteDetailException; import seedu.duke.exception.EmptyCommandPairUnpairDetailsException; import seedu.duke.exception.ExistingPairException; @@ -19,6 +21,7 @@ import seedu.duke.exception.InvalidClientIndexDeleteException; import seedu.duke.exception.InvalidContactNumberException; import seedu.duke.exception.InvalidEmailException; +import seedu.duke.exception.MissingCheckPropertyFlagException; import seedu.duke.exception.MissingClientDetailException; import seedu.duke.exception.MissingClientFlagException; import seedu.duke.exception.MissingFlagException; @@ -27,6 +30,7 @@ import seedu.duke.exception.NotIntegerException; import seedu.duke.exception.NotValidIndexException; import seedu.duke.exception.UndefinedSubCommandAddTypeException; +import seedu.duke.exception.UndefinedSubCommandCheckTypeException; import seedu.duke.exception.UndefinedSubCommandDeleteTypeException; import java.util.ArrayList; @@ -41,6 +45,8 @@ public class Parser { public static final int ADD_CLIENT_FLAG_SIZE = 4; public static final int PAIR_UNPAIR_FLAG_SIZE = 2; + public static final int CHECK_PROPERTY_FLAG_SIZE = 1; + public Parser(ClientList clientL, PropertyList propertyL, PairingList pairingL) { clientList = clientL; @@ -55,7 +61,8 @@ public Command parseCommand(String input) throws EmptyCommandAddDetailException, EmptyCommandDeleteDetailException, InvalidClientIndexDeleteException, EmptyClientIndexDeleteException, EmptyCommandPairUnpairDetailsException, MissingPairUnpairFlagException, IncorrectPairUnpairFlagOrderException, NotValidIndexException, NotIntegerException, ExistingPairException, - NoExistingPairException { + NoExistingPairException, UndefinedSubCommandCheckTypeException, EmptyCommandCheckDetailException, + MissingCheckPropertyFlagException { ArrayList processedCommandDetails = partitionCommandTypeAndDetails(input); String commandType = processedCommandDetails.get(0); String commandDetails = processedCommandDetails.get(1); @@ -71,6 +78,7 @@ public Command parseCommand(String input) throws EmptyCommandAddDetailException, } else { throw new UndefinedSubCommandAddTypeException(); } + case "delete": checkForEmptyCommandDeleteDetails(commandDetails); ArrayList processedDeleteCommandDetails = partitionCommandTypeAndDetails(commandDetails); @@ -81,12 +89,26 @@ public Command parseCommand(String input) throws EmptyCommandAddDetailException, } else { throw new UndefinedSubCommandDeleteTypeException(); } + case "pair": checkForEmptyCommandPairUnpairDetails(commandDetails); return prepareForCommandPair(commandDetails); + case "unpair": checkForEmptyCommandPairUnpairDetails(commandDetails); return prepareForCommandUnpair(commandDetails); + + case "check": + checkForEmptyCommandCheckDetails(commandDetails); + ArrayList processedCheckCommandDetails = partitionCommandTypeAndDetails(commandDetails); + String subCommandCheckType = processedCheckCommandDetails.get(0); + String commandCheckClientOrPropertyDescriptions = processedCheckCommandDetails.get(1); + + if (subCommandCheckType.equals("-property")) { + return prepareForCommandCheckProperty(commandCheckClientOrPropertyDescriptions); + } else { + throw new UndefinedSubCommandCheckTypeException(); + } default: return new CommandUndefined(); } @@ -386,7 +408,7 @@ private void validatePairDetails(ArrayList pairUnpairDetails) throws No ExistingPairException { int clientIndex = pairUnpairDetails.get(0); int propertyIndex = pairUnpairDetails.get(1); - checkForListIndexOutOfBounds(clientIndex, propertyIndex); + checkForPairingListIndexOutOfBounds(clientIndex, propertyIndex); Client client = clientList.getClientList().get(clientIndex); if (pairingList.isClientPairedWithProperty(client)) { throw new ExistingPairException(); @@ -397,18 +419,91 @@ private void validateUnpairDetails(ArrayList pairUnpairDetails) throws NoExistingPairException { int clientIndex = pairUnpairDetails.get(0); int propertyIndex = pairUnpairDetails.get(1); - checkForListIndexOutOfBounds(clientIndex, propertyIndex); + checkForPairingListIndexOutOfBounds(clientIndex, propertyIndex); Client client = clientList.getClientList().get(clientIndex); if (!pairingList.isClientPairedWithProperty(client)) { throw new NoExistingPairException(); } } - private void checkForListIndexOutOfBounds(int clientIndex, int propertyIndex) throws NotValidIndexException { - if (clientIndex < 0 || clientIndex > clientList.getCurrentListSize() - 1 - || propertyIndex < 0 || propertyIndex > propertyList.getCurrentListSize() - 1) { + private void checkForPairingListIndexOutOfBounds(int clientIndex, int propertyIndex) throws NotValidIndexException { + checkForClientListIndexOutOfBounds(clientIndex); + checkForPropertyListIndexOutOfBounds(propertyIndex); + } + + private void checkForPropertyListIndexOutOfBounds(int propertyIndex) throws NotValidIndexException { + if (propertyIndex < 0 || propertyIndex > propertyList.getCurrentListSize() - 1) { throw new NotValidIndexException(); } } + private void checkForClientListIndexOutOfBounds(int clientIndex) throws NotValidIndexException { + if (clientIndex < 0 || clientIndex > clientList.getCurrentListSize() - 1) { + throw new NotValidIndexException(); + } + } + + private Command prepareForCommandCheckProperty(String rawPropertyDescriptions) throws NotIntegerException, + NotValidIndexException, MissingCheckPropertyFlagException { + try { + ArrayList checkPropertyDetails = processCheckPropertyDetails(rawPropertyDescriptions); + validateCheckPropertyDetails(checkPropertyDetails); + return new CommandCheckProperty(checkPropertyDetails); + } catch (MissingFlagException e) { + throw new MissingCheckPropertyFlagException(); + } + } + + private void checkForEmptyCommandCheckDetails(String commandCheckDetails) throws EmptyCommandCheckDetailException { + boolean isEmptyCommandCheckDetail = checkForEmptyDetail(commandCheckDetails); + if (isEmptyCommandCheckDetail) { + throw new EmptyCommandCheckDetailException(); + } + } + + private ArrayList processCheckPropertyDetails(String rawPropertyDetails) throws MissingFlagException, + NotIntegerException { + String[] checkPropertyFlags = {"ip/"}; + int[] checkPropertyFlagIndexPositions = new int[CHECK_PROPERTY_FLAG_SIZE]; + + for (int i = 0; i < checkPropertyFlags.length; i++) { + checkPropertyFlagIndexPositions[i] = rawPropertyDetails.indexOf(checkPropertyFlags[i]); + } + + checkForMissingCheckPropertyFlags(checkPropertyFlagIndexPositions); + return extractCheckPropertyDetails(rawPropertyDetails, checkPropertyFlagIndexPositions, checkPropertyFlags); + } + + private void checkForMissingCheckPropertyFlags(int[] checkPropertyFlagIndexPositions) throws MissingFlagException { + checkForEssentialCheckPropertyFlag(checkPropertyFlagIndexPositions[0]); + } + + private void checkForEssentialCheckPropertyFlag(int checkPropertyFlagIndexPosition) throws MissingFlagException { + boolean hasFlag = (checkPropertyFlagIndexPosition != -1); + if (!hasFlag) { + throw new MissingFlagException(); + } + } + + private ArrayList extractCheckPropertyDetails(String rawPropertyDetails, + int[] checkPropertyFlagIndexPositions, String[] checkFlags) throws NotIntegerException { + String propertyIndexString = extractDetail(rawPropertyDetails, + checkPropertyFlagIndexPositions[0] + checkFlags[0].length()); + + int propertyIndex; + try { + propertyIndex = Integer.parseInt(propertyIndexString); + } catch (NumberFormatException e) { + throw new NotIntegerException(); + } + ArrayList processedCheckPropertyDetails = new ArrayList<>(); + processedCheckPropertyDetails.add(propertyIndex - 1); + return processedCheckPropertyDetails; + } + + private void validateCheckPropertyDetails(ArrayList checkPropertyDetails) throws NotValidIndexException { + int propertyIndex = checkPropertyDetails.get(0); + checkForPropertyListIndexOutOfBounds(propertyIndex); + } + } diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index 8ad347055..7b0fe64b7 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -1,12 +1,16 @@ package seedu.duke; +import java.util.ArrayList; import java.util.Scanner; import static seedu.duke.Messages.MESSAGE_ADD_CLIENT_WRONG_FORMAT; +import static seedu.duke.Messages.MESSAGE_CHECK_PROPERTY_RESULT; +import static seedu.duke.Messages.MESSAGE_CHECK_PROPERTY_WRONG_FORMAT; import static seedu.duke.Messages.MESSAGE_CLIENT_ADDED; import static seedu.duke.Messages.MESSAGE_CLIENT_DELETED; import static seedu.duke.Messages.MESSAGE_CLIENT_INPUT_EXAMPLE; import static seedu.duke.Messages.MESSAGE_EMPTY_ADD_DESCRIPTION; +import static seedu.duke.Messages.MESSAGE_EMPTY_CHECK_DESCRIPTION; import static seedu.duke.Messages.MESSAGE_EMPTY_CLIENT_DESCRIPTION; import static seedu.duke.Messages.MESSAGE_EMPTY_COMMAND_PAIR_UNPAIR; import static seedu.duke.Messages.MESSAGE_EXISTING_PAIR; @@ -17,7 +21,9 @@ import static seedu.duke.Messages.MESSAGE_INVALID_CONTACT_NUMBER; import static seedu.duke.Messages.MESSAGE_INVALID_EMAIL; import static seedu.duke.Messages.MESSAGE_MISSING_SUB_COMMAND_TYPE_FOR_ADD; +import static seedu.duke.Messages.MESSAGE_MISSING_SUB_COMMAND_TYPE_FOR_CHECK; import static seedu.duke.Messages.MESSAGE_MISSING_SUB_COMMAND_TYPE_FOR_DELETE; +import static seedu.duke.Messages.MESSAGE_NUMBER_OF_LIST_RESULTS; import static seedu.duke.Messages.MESSAGE_TRY_AGAIN; import static seedu.duke.Messages.MESSAGE_NOT_INTEGER; import static seedu.duke.Messages.MESSAGE_NOT_VALID_INDEX; @@ -153,4 +159,26 @@ public void showNoExistingPairMessage() { showToUser(MESSAGE_NO_EXISTING_PAIR); } + public void showCheckPropertyWrongFormatMessage() { + showToUser(MESSAGE_CHECK_PROPERTY_WRONG_FORMAT); + } + + public void showUndefinedSubCommandCheckTypeMessage() { + showToUser(MESSAGE_MISSING_SUB_COMMAND_TYPE_FOR_CHECK); + } + + public void showEmptyCommandCheckDetailException() { + showToUser(MESSAGE_EMPTY_CHECK_DESCRIPTION); + } + + public void showCheckProperty(ArrayList tenants) { + showToUser(MESSAGE_CHECK_PROPERTY_RESULT); + int count = 0; + for (String tenant : tenants) { + // Remove brackets at first and last indexes of tenant(client) string + String tenantInfo = tenant.substring(1, tenant.length() - 1); + showToUser(String.format(" %d. %s", count++, tenantInfo)); + } + showToUser(MESSAGE_NUMBER_OF_LIST_RESULTS + count); + } } diff --git a/src/main/java/seedu/duke/command/CommandCheck.java b/src/main/java/seedu/duke/command/CommandCheck.java new file mode 100644 index 000000000..581293761 --- /dev/null +++ b/src/main/java/seedu/duke/command/CommandCheck.java @@ -0,0 +1,7 @@ +package seedu.duke.command; + +/** + * Represents a cbeck-type command. + */ +abstract class CommandCheck extends Command { +} diff --git a/src/main/java/seedu/duke/command/CommandCheckProperty.java b/src/main/java/seedu/duke/command/CommandCheckProperty.java new file mode 100644 index 000000000..b7c50bb8f --- /dev/null +++ b/src/main/java/seedu/duke/command/CommandCheckProperty.java @@ -0,0 +1,27 @@ +package seedu.duke.command; + +import seedu.duke.ClientList; +import seedu.duke.PairingList; +import seedu.duke.Property; +import seedu.duke.PropertyList; +import seedu.duke.Storage; +import seedu.duke.Ui; + +import java.util.ArrayList; + +public class CommandCheckProperty extends CommandCheck { + + private int propertyIndex; + + public CommandCheckProperty(ArrayList commandCheckPropertyDetails) { + this.propertyIndex = commandCheckPropertyDetails.get(0); + } + + @Override + public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, + PairingList pairingList) { + Property property = propertyList.getPropertyList().get(propertyIndex); + ArrayList tenants = pairingList.getPropertyTenants(property); + ui.showCheckProperty(tenants); + } +} diff --git a/src/main/java/seedu/duke/exception/EmptyCommandCheckDetailException.java b/src/main/java/seedu/duke/exception/EmptyCommandCheckDetailException.java new file mode 100644 index 000000000..eb36169a4 --- /dev/null +++ b/src/main/java/seedu/duke/exception/EmptyCommandCheckDetailException.java @@ -0,0 +1,4 @@ +package seedu.duke.exception; + +public class EmptyCommandCheckDetailException extends DukeException { +} diff --git a/src/main/java/seedu/duke/exception/MissingCheckPropertyFlagException.java b/src/main/java/seedu/duke/exception/MissingCheckPropertyFlagException.java new file mode 100644 index 000000000..f55c7614b --- /dev/null +++ b/src/main/java/seedu/duke/exception/MissingCheckPropertyFlagException.java @@ -0,0 +1,4 @@ +package seedu.duke.exception; + +public class MissingCheckPropertyFlagException extends DukeException { +} diff --git a/src/main/java/seedu/duke/exception/UndefinedSubCommandCheckTypeException.java b/src/main/java/seedu/duke/exception/UndefinedSubCommandCheckTypeException.java new file mode 100644 index 000000000..20b13c647 --- /dev/null +++ b/src/main/java/seedu/duke/exception/UndefinedSubCommandCheckTypeException.java @@ -0,0 +1,4 @@ +package seedu.duke.exception; + +public class UndefinedSubCommandCheckTypeException extends DukeException { +} From effd7320575980aac2c5fb8426792e3bdb3a8a71 Mon Sep 17 00:00:00 2001 From: ngdeqi Date: Tue, 11 Oct 2022 22:06:27 +0800 Subject: [PATCH 041/325] Add CommandUndefinedMessage --- src/main/java/seedu/duke/Messages.java | 2 ++ src/main/java/seedu/duke/Ui.java | 5 +++++ src/main/java/seedu/duke/command/CommandUndefined.java | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/duke/Messages.java b/src/main/java/seedu/duke/Messages.java index 8dc25dd73..50a3d42c4 100644 --- a/src/main/java/seedu/duke/Messages.java +++ b/src/main/java/seedu/duke/Messages.java @@ -6,6 +6,8 @@ public class Messages { public static final String MESSAGE_WELCOME = "Welcome to Property Manager! How may I help you?"; + public static final String MESSAGE_COMMAND_UNDEFINED = "OOPS!!! Command not recognised. Try again."; + public static final String MESSAGE_NUMBER_OF_LIST_RESULTS = "Number of entries in the list: "; public static final String MESSAGE_CLIENT_ADDED = "Adding a client with the following information:"; diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index 7b0fe64b7..d265d734c 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -9,6 +9,7 @@ import static seedu.duke.Messages.MESSAGE_CLIENT_ADDED; import static seedu.duke.Messages.MESSAGE_CLIENT_DELETED; import static seedu.duke.Messages.MESSAGE_CLIENT_INPUT_EXAMPLE; +import static seedu.duke.Messages.MESSAGE_COMMAND_UNDEFINED; import static seedu.duke.Messages.MESSAGE_EMPTY_ADD_DESCRIPTION; import static seedu.duke.Messages.MESSAGE_EMPTY_CHECK_DESCRIPTION; import static seedu.duke.Messages.MESSAGE_EMPTY_CLIENT_DESCRIPTION; @@ -64,6 +65,10 @@ public void showWelcomeMessage() { showToUser(MESSAGE_WELCOME); } + public void showCommandUndefinedMessage() { + showToUser(MESSAGE_COMMAND_UNDEFINED); + } + public void showClientAddedConfirmationMessage(ClientList clientList) { int currentListSize = clientList.getCurrentListSize(); showToUser(MESSAGE_CLIENT_ADDED); diff --git a/src/main/java/seedu/duke/command/CommandUndefined.java b/src/main/java/seedu/duke/command/CommandUndefined.java index 00dab02b8..859168fab 100644 --- a/src/main/java/seedu/duke/command/CommandUndefined.java +++ b/src/main/java/seedu/duke/command/CommandUndefined.java @@ -11,6 +11,6 @@ public class CommandUndefined extends Command { @Override public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, PairingList pairingList) { - //showCommandUndefinedMessage + ui.showCommandUndefinedMessage(); } } From 1f6e8791bbc47004b4a8899787d84a212fe7b354 Mon Sep 17 00:00:00 2001 From: FeliciaBeatrice Date: Tue, 11 Oct 2022 22:13:44 +0800 Subject: [PATCH 042/325] Fix Delete Client Feature --- src/main/java/seedu/duke/Duke.java | 6 +++++ src/main/java/seedu/duke/Messages.java | 7 +++++- src/main/java/seedu/duke/Parser.java | 23 ++++++++++++++++--- src/main/java/seedu/duke/Ui.java | 23 ++++++++++++++----- ...InvalidClientIndexFlagFormatException.java | 7 ++++++ .../MissingClientIndexFlagException.java | 7 ++++++ 6 files changed, 63 insertions(+), 10 deletions(-) create mode 100644 src/main/java/seedu/duke/exception/InvalidClientIndexFlagFormatException.java create mode 100644 src/main/java/seedu/duke/exception/MissingClientIndexFlagException.java diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 11807e956..f5944fba7 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -12,10 +12,12 @@ import seedu.duke.exception.IncorrectPairUnpairFlagOrderException; import seedu.duke.exception.InvalidBudgetFormatException; import seedu.duke.exception.InvalidClientIndexDeleteException; +import seedu.duke.exception.InvalidClientIndexFlagFormatException; import seedu.duke.exception.InvalidContactNumberException; import seedu.duke.exception.InvalidEmailException; import seedu.duke.exception.MissingClientDetailException; import seedu.duke.exception.MissingClientFlagException; +import seedu.duke.exception.MissingClientIndexFlagException; import seedu.duke.exception.MissingPairUnpairFlagException; import seedu.duke.exception.NoExistingPairException; import seedu.duke.exception.NotIntegerException; @@ -77,6 +79,10 @@ public void run() throws IOException { ui.showInvalidClientIndexDeleteMessage(); } catch (EmptyClientIndexDeleteException e) { ui.showEmptyClientIndexDeleteMessage(); + } catch (MissingClientIndexFlagException e) { + ui.showMissingClientIndexFlagMessage(); + } catch (InvalidClientIndexFlagFormatException e) { + ui.showInvalidClientIndexFlagFormatMessage(); } catch (EmptyCommandPairUnpairDetailsException e) { ui.showEmptyCommandPairUnpairDetailsMessage(); } catch (MissingPairUnpairFlagException | IncorrectPairUnpairFlagOrderException e) { diff --git a/src/main/java/seedu/duke/Messages.java b/src/main/java/seedu/duke/Messages.java index abe8e03d4..544d316ce 100644 --- a/src/main/java/seedu/duke/Messages.java +++ b/src/main/java/seedu/duke/Messages.java @@ -42,12 +42,17 @@ public class Messages { + "For client: add -client\n" + "For property: add -property"; - public static final String MESSAGE_EMPTY_DELETE_DESCRIPTION = "OOPS!!! The index for delete cannot be empty."; + public static final String MESSAGE_EMPTY_DELETE_DESCRIPTION = "OOPS!!! The description for delete cannot be empty."; public static final String MESSAGE_INVALID_CLIENT_INDEX = "OOPS!!! Please enter a valid client index."; public static final String MESSAGE_EMPTY_CLIENT_INDEX = "OOPS!!! The client index to delete cannot be empty."; + public static final String MESSAGE_MISSING_CLIENT_INDEX_FLAG = "OOPS!!! Please provide the client index flag."; + + public static final String MESSAGE_INVALID_CLIENT_INDEX_FLAG_FORMAT = "OOPS!!! Please use this format:\n" + + "delete -client ic/CLIENT_INDEX"; + public static final String MESSAGE_PAIRED = "Pairing the following client and property: "; public static final String MESSAGE_UNPAIRED = "Unpairing the following client and property: "; diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 5815293ac..0fa915590 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -17,10 +17,12 @@ import seedu.duke.exception.IncorrectPairUnpairFlagOrderException; import seedu.duke.exception.InvalidBudgetFormatException; import seedu.duke.exception.InvalidClientIndexDeleteException; +import seedu.duke.exception.InvalidClientIndexFlagFormatException; import seedu.duke.exception.InvalidContactNumberException; import seedu.duke.exception.InvalidEmailException; import seedu.duke.exception.MissingClientDetailException; import seedu.duke.exception.MissingClientFlagException; +import seedu.duke.exception.MissingClientIndexFlagException; import seedu.duke.exception.MissingFlagException; import seedu.duke.exception.MissingPairUnpairFlagException; import seedu.duke.exception.NoExistingPairException; @@ -53,6 +55,7 @@ public Command parseCommand(String input) throws EmptyCommandAddDetailException, IncorrectAddClientFlagOrderException, MissingClientDetailException, InvalidContactNumberException, InvalidEmailException, InvalidBudgetFormatException, UndefinedSubCommandDeleteTypeException, EmptyCommandDeleteDetailException, InvalidClientIndexDeleteException, EmptyClientIndexDeleteException, + MissingClientIndexFlagException, InvalidClientIndexFlagFormatException, EmptyCommandPairUnpairDetailsException, MissingPairUnpairFlagException, IncorrectPairUnpairFlagOrderException, NotValidIndexException, NotIntegerException, ExistingPairException, NoExistingPairException { @@ -75,8 +78,11 @@ public Command parseCommand(String input) throws EmptyCommandAddDetailException, checkForEmptyCommandDeleteDetails(commandDetails); ArrayList processedDeleteCommandDetails = partitionCommandTypeAndDetails(commandDetails); String subDeleteCommandType = processedDeleteCommandDetails.get(0); - int clientIndexToDelete = getClientIndex(processedDeleteCommandDetails.get(1)) - 1; + String indexDescription = processedDeleteCommandDetails.get(1).trim(); + if (subDeleteCommandType.equals("-client")) { + checkForClientIndexFlag(indexDescription); + int clientIndexToDelete = getClientIndexToDelete(indexDescription.substring(3)); return prepareForCommandDeleteClient(clientIndexToDelete, clientList); } else { throw new UndefinedSubCommandDeleteTypeException(); @@ -278,11 +284,22 @@ private boolean checkForEmptyDetail(String commandDetails) { return commandDetails.trim().isEmpty(); } - private int getClientIndex(String commandDetails) throws EmptyClientIndexDeleteException { + private int getClientIndexToDelete(String commandDetails) throws EmptyClientIndexDeleteException { if (commandDetails.isEmpty()) { throw new EmptyClientIndexDeleteException(); } - return Integer.parseInt(commandDetails.trim()); + return Integer.parseInt(commandDetails.trim()) - 1; + } + + private void checkForClientIndexFlag(String commandDetails) throws MissingClientIndexFlagException, InvalidClientIndexFlagFormatException { + if (!commandDetails.contains("ic/")) { + throw new MissingClientIndexFlagException(); + } else { + String clientIndexFlag = commandDetails.substring(0, 3); + if (!clientIndexFlag.equals("ic/")) { + throw new InvalidClientIndexFlagFormatException(); + } + } } private Command prepareForCommandDeleteClient(int clientIndex, ClientList clientList) diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index 8ad347055..534e6860a 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -14,8 +14,10 @@ import static seedu.duke.Messages.MESSAGE_EMPTY_DELETE_DESCRIPTION; import static seedu.duke.Messages.MESSAGE_INVALID_BUDGET_FORMAT; import static seedu.duke.Messages.MESSAGE_INVALID_CLIENT_INDEX; +import static seedu.duke.Messages.MESSAGE_INVALID_CLIENT_INDEX_FLAG_FORMAT; import static seedu.duke.Messages.MESSAGE_INVALID_CONTACT_NUMBER; import static seedu.duke.Messages.MESSAGE_INVALID_EMAIL; +import static seedu.duke.Messages.MESSAGE_MISSING_CLIENT_INDEX_FLAG; import static seedu.duke.Messages.MESSAGE_MISSING_SUB_COMMAND_TYPE_FOR_ADD; import static seedu.duke.Messages.MESSAGE_MISSING_SUB_COMMAND_TYPE_FOR_DELETE; import static seedu.duke.Messages.MESSAGE_TRY_AGAIN; @@ -69,6 +71,16 @@ public void showClientDeletedConfirmationMessage(Client deletedClient) { showToUser(" " + deletedClient); } + public void showPairedConfirmationMessage(Client client, Property property) { + showToUser(MESSAGE_PAIRED); + showToUser(" " + client.getClientName() + " and " + property.getPropertyAddress()); + } + + public void showUnpairedConfirmationMessage(Client client, Property property) { + showToUser(MESSAGE_UNPAIRED); + showToUser(" " + client.getClientName() + " and " + property.getPropertyAddress()); + } + /* Add Client Related Exceptions */ public void showMissingCommandAddDetailMessage() { showToUser(MESSAGE_EMPTY_ADD_DESCRIPTION); @@ -117,16 +129,15 @@ public void showEmptyClientIndexDeleteMessage() { showToUser(MESSAGE_EMPTY_CLIENT_INDEX); } - public void showPairedConfirmationMessage(Client client, Property property) { - showToUser(MESSAGE_PAIRED); - showToUser(" " + client.getClientName() + " and " + property.getPropertyAddress()); + public void showMissingClientIndexFlagMessage() { + showToUser(MESSAGE_MISSING_CLIENT_INDEX_FLAG); } - public void showUnpairedConfirmationMessage(Client client, Property property) { - showToUser(MESSAGE_UNPAIRED); - showToUser(" " + client.getClientName() + " and " + property.getPropertyAddress()); + public void showInvalidClientIndexFlagFormatMessage() { + showToUser(MESSAGE_INVALID_CLIENT_INDEX_FLAG_FORMAT); } + /* Pair Unpair Related Exceptions */ public void showEmptyCommandPairUnpairDetailsMessage() { showToUser(MESSAGE_EMPTY_COMMAND_PAIR_UNPAIR); } diff --git a/src/main/java/seedu/duke/exception/InvalidClientIndexFlagFormatException.java b/src/main/java/seedu/duke/exception/InvalidClientIndexFlagFormatException.java new file mode 100644 index 000000000..fcc292092 --- /dev/null +++ b/src/main/java/seedu/duke/exception/InvalidClientIndexFlagFormatException.java @@ -0,0 +1,7 @@ +package seedu.duke.exception; + +/** + * Represents exception when an invalid client index flag format is provided. + */ +public class InvalidClientIndexFlagFormatException extends DukeException { +} diff --git a/src/main/java/seedu/duke/exception/MissingClientIndexFlagException.java b/src/main/java/seedu/duke/exception/MissingClientIndexFlagException.java new file mode 100644 index 000000000..aedb3cef9 --- /dev/null +++ b/src/main/java/seedu/duke/exception/MissingClientIndexFlagException.java @@ -0,0 +1,7 @@ +package seedu.duke.exception; + +/** + * Represents exception when client index flag is missing. + */ +public class MissingClientIndexFlagException extends DukeException { +} From 9da819ebc94c1b1e4994cee51fe38808976678e4 Mon Sep 17 00:00:00 2001 From: FeliciaBeatrice Date: Tue, 11 Oct 2022 22:18:15 +0800 Subject: [PATCH 043/325] Fix coding standard violations --- src/main/java/seedu/duke/Parser.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 0fa915590..09007efee 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -291,7 +291,8 @@ private int getClientIndexToDelete(String commandDetails) throws EmptyClientInde return Integer.parseInt(commandDetails.trim()) - 1; } - private void checkForClientIndexFlag(String commandDetails) throws MissingClientIndexFlagException, InvalidClientIndexFlagFormatException { + private void checkForClientIndexFlag(String commandDetails) + throws MissingClientIndexFlagException, InvalidClientIndexFlagFormatException { if (!commandDetails.contains("ic/")) { throw new MissingClientIndexFlagException(); } else { From 8f34943542edbce6ef030ef19ecb635d09253767 Mon Sep 17 00:00:00 2001 From: FeliciaBeatrice Date: Tue, 11 Oct 2022 22:25:29 +0800 Subject: [PATCH 044/325] Fix Delete Client Exception Messages --- src/main/java/seedu/duke/Messages.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/duke/Messages.java b/src/main/java/seedu/duke/Messages.java index 544d316ce..d5679df7e 100644 --- a/src/main/java/seedu/duke/Messages.java +++ b/src/main/java/seedu/duke/Messages.java @@ -42,7 +42,9 @@ public class Messages { + "For client: add -client\n" + "For property: add -property"; - public static final String MESSAGE_EMPTY_DELETE_DESCRIPTION = "OOPS!!! The description for delete cannot be empty."; + public static final String MESSAGE_EMPTY_DELETE_DESCRIPTION = "OOPS!!! Please use this format to delete:\n" + + "Client: delete -client ic/CLIENT_INDEX\n" + + "Property: delete -property ip/PROPERTY_INDEX"; public static final String MESSAGE_INVALID_CLIENT_INDEX = "OOPS!!! Please enter a valid client index."; @@ -50,8 +52,8 @@ public class Messages { public static final String MESSAGE_MISSING_CLIENT_INDEX_FLAG = "OOPS!!! Please provide the client index flag."; - public static final String MESSAGE_INVALID_CLIENT_INDEX_FLAG_FORMAT = "OOPS!!! Please use this format:\n" - + "delete -client ic/CLIENT_INDEX"; + public static final String MESSAGE_INVALID_CLIENT_INDEX_FLAG_FORMAT = "OOPS!!! Please use this flag format:\n" + + "ic/CLIENT_INDEX"; public static final String MESSAGE_PAIRED = "Pairing the following client and property: "; From 0c5fcd7e8293acbf3190a4e1ea86da69bb701e2f Mon Sep 17 00:00:00 2001 From: ngdeqi Date: Tue, 11 Oct 2022 22:27:56 +0800 Subject: [PATCH 045/325] Add some documentation --- src/main/java/seedu/duke/exception/AddPairException.java | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 src/main/java/seedu/duke/exception/AddPairException.java diff --git a/src/main/java/seedu/duke/exception/AddPairException.java b/src/main/java/seedu/duke/exception/AddPairException.java deleted file mode 100644 index 0d1f5c2a3..000000000 --- a/src/main/java/seedu/duke/exception/AddPairException.java +++ /dev/null @@ -1,4 +0,0 @@ -package seedu.duke.exception; - -public class AddPairException extends DukeException{ -} From c908835282646240357bb34a19089a1b2f6ab314 Mon Sep 17 00:00:00 2001 From: ngdeqi Date: Tue, 11 Oct 2022 22:29:31 +0800 Subject: [PATCH 046/325] Add even more documentation --- src/main/java/seedu/duke/PairingList.java | 7 ++++++- src/main/java/seedu/duke/command/Command.java | 8 ++++++++ src/main/java/seedu/duke/command/CommandCheck.java | 2 +- .../java/seedu/duke/command/CommandCheckProperty.java | 10 ++++++++++ src/main/java/seedu/duke/command/CommandPair.java | 11 +++++++++++ .../java/seedu/duke/command/CommandUndefined.java | 7 +++++++ src/main/java/seedu/duke/command/CommandUnpair.java | 10 ++++++++++ 7 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/duke/PairingList.java b/src/main/java/seedu/duke/PairingList.java index ebc2f5d69..06688202d 100644 --- a/src/main/java/seedu/duke/PairingList.java +++ b/src/main/java/seedu/duke/PairingList.java @@ -15,7 +15,7 @@ public class PairingList { private static final HashMap clientPropertyPairs = new HashMap<>(); /** - * Default Constructor. + * Constructs the PairingList object. */ public PairingList() { @@ -66,6 +66,11 @@ public boolean isClientPairedWithProperty(Client client) { return clientPropertyPairs.containsKey(clientPairingData); } + /** + * Fetches a list of tenants that is renting the property. + * @param property Property being queried. + * @return List of tenants occupying the property, along with their data. + */ public ArrayList getPropertyTenants(Property property) { String propertyPairingData = convertToPairingData(property); ArrayList tenants = new ArrayList<>(); diff --git a/src/main/java/seedu/duke/command/Command.java b/src/main/java/seedu/duke/command/Command.java index 46810ce4a..f4331f264 100644 --- a/src/main/java/seedu/duke/command/Command.java +++ b/src/main/java/seedu/duke/command/Command.java @@ -11,6 +11,14 @@ * Represents an executable command. */ public abstract class Command { + + /** + * Executes the command. + * @param ui User interface object that handles interactions between user and the app. + * @param storage Storage object that is responsible for storing and loading the app data. + * @param propertyList PropertyList object that handles all app interactions with the list clients. + * @param pairingList PairingList object that handles all interactions with the list clients paired with properties. + */ public abstract void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, PairingList pairingList); } diff --git a/src/main/java/seedu/duke/command/CommandCheck.java b/src/main/java/seedu/duke/command/CommandCheck.java index 581293761..59a7c9b05 100644 --- a/src/main/java/seedu/duke/command/CommandCheck.java +++ b/src/main/java/seedu/duke/command/CommandCheck.java @@ -1,7 +1,7 @@ package seedu.duke.command; /** - * Represents a cbeck-type command. + * Represents a check-type command. */ abstract class CommandCheck extends Command { } diff --git a/src/main/java/seedu/duke/command/CommandCheckProperty.java b/src/main/java/seedu/duke/command/CommandCheckProperty.java index b7c50bb8f..bd0c41e9f 100644 --- a/src/main/java/seedu/duke/command/CommandCheckProperty.java +++ b/src/main/java/seedu/duke/command/CommandCheckProperty.java @@ -9,14 +9,24 @@ import java.util.ArrayList; +/** + * Represents a check property command. + */ public class CommandCheckProperty extends CommandCheck { private int propertyIndex; + /** + * Constructs an instance of CommandCheckProperty. + * @param commandCheckPropertyDetails Parsed property index from the user's input. + */ public CommandCheckProperty(ArrayList commandCheckPropertyDetails) { this.propertyIndex = commandCheckPropertyDetails.get(0); } + /** + * {@inheritDoc} + */ @Override public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, PairingList pairingList) { diff --git a/src/main/java/seedu/duke/command/CommandPair.java b/src/main/java/seedu/duke/command/CommandPair.java index dc801c250..f59982513 100644 --- a/src/main/java/seedu/duke/command/CommandPair.java +++ b/src/main/java/seedu/duke/command/CommandPair.java @@ -11,16 +11,27 @@ import java.util.ArrayList; +/** + * Represents a pair-type command. + */ public class CommandPair extends Command { private int clientIndex; private int propertyIndex; + + /** + * Constructs CommandPair object. + * @param commandPairDetails Parsed client and property indexes from the user's input. + */ public CommandPair(ArrayList commandPairDetails) { this.clientIndex = commandPairDetails.get(0); this.propertyIndex = commandPairDetails.get(1); } + /** + * {@inheritDoc} + */ @Override public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, PairingList pairingList) { diff --git a/src/main/java/seedu/duke/command/CommandUndefined.java b/src/main/java/seedu/duke/command/CommandUndefined.java index 859168fab..f303c6c5d 100644 --- a/src/main/java/seedu/duke/command/CommandUndefined.java +++ b/src/main/java/seedu/duke/command/CommandUndefined.java @@ -7,7 +7,14 @@ import seedu.duke.Storage; import seedu.duke.Ui; +/** + * Represents a command that the app does not recognise. + */ public class CommandUndefined extends Command { + + /** + * {@inheritDoc} + */ @Override public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, PairingList pairingList) { diff --git a/src/main/java/seedu/duke/command/CommandUnpair.java b/src/main/java/seedu/duke/command/CommandUnpair.java index 59a106bfa..b0e1cb1e1 100644 --- a/src/main/java/seedu/duke/command/CommandUnpair.java +++ b/src/main/java/seedu/duke/command/CommandUnpair.java @@ -11,16 +11,26 @@ import java.util.ArrayList; +/** + * Represents an unpair-type command. + */ public class CommandUnpair extends Command { private int clientIndex; private int propertyIndex; + /** + * Constructs an instance of CommandCheckProperty. + * @param commandUnpairDetails Parsed client and property indexes from the user's input. + */ public CommandUnpair(ArrayList commandUnpairDetails) { this.clientIndex = commandUnpairDetails.get(0); this.propertyIndex = commandUnpairDetails.get(1); } + /** + * {@inheritDoc} + */ @Override public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, PairingList pairingList) { From c947804441b3a02a402e427124e0cda9c894d35a Mon Sep 17 00:00:00 2001 From: Lish <88262276+FeliciaBeatrice@users.noreply.github.com> Date: Tue, 11 Oct 2022 23:03:10 +0800 Subject: [PATCH 047/325] Fix Messages error --- src/main/java/seedu/duke/Messages.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/seedu/duke/Messages.java b/src/main/java/seedu/duke/Messages.java index c66c882bf..8c149b68d 100644 --- a/src/main/java/seedu/duke/Messages.java +++ b/src/main/java/seedu/duke/Messages.java @@ -99,8 +99,6 @@ public class Messages { public static final String MESSAGE_INVALID_CLIENT_INDEX_FLAG_FORMAT = "OOPS!!! Please use this flag format:\n" + "ic/CLIENT_INDEX"; - public static final String MESSAGE_PAIRED = "Pairing the following client and property: "; - /* Pair/Unpair Related Error Messages */ public static final String MESSAGE_EMPTY_COMMAND_PAIR_UNPAIR = "OOPS!!! The description of a pair/unpair message " From fe2d2539fd2b8fabc77222efcfdd8c7bcbd416aa Mon Sep 17 00:00:00 2001 From: FeliciaBeatrice Date: Wed, 12 Oct 2022 02:53:34 +0800 Subject: [PATCH 048/325] Add Delete Property feature and exceptions --- src/main/java/seedu/duke/Duke.java | 14 ++++- src/main/java/seedu/duke/Messages.java | 13 ++++- src/main/java/seedu/duke/Parser.java | 57 ++++++++++++++++--- src/main/java/seedu/duke/PropertyList.java | 7 +++ src/main/java/seedu/duke/Ui.java | 31 +++++++++- .../duke/command/CommandDeleteProperty.java | 29 ++++++++++ .../EmptyPropertyIndexDeleteException.java | 7 +++ .../InvalidClientIndexDeleteException.java | 2 +- .../InvalidPropertyIndexDeleteException.java | 7 +++ ...validPropertyIndexFlagFormatException.java | 7 +++ .../MissingPropertyIndexFlagException.java | 7 +++ 11 files changed, 167 insertions(+), 14 deletions(-) create mode 100644 src/main/java/seedu/duke/command/CommandDeleteProperty.java create mode 100644 src/main/java/seedu/duke/exception/EmptyPropertyIndexDeleteException.java create mode 100644 src/main/java/seedu/duke/exception/InvalidPropertyIndexDeleteException.java create mode 100644 src/main/java/seedu/duke/exception/InvalidPropertyIndexFlagFormatException.java create mode 100644 src/main/java/seedu/duke/exception/MissingPropertyIndexFlagException.java diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index d64830eb1..338c48f27 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -9,6 +9,7 @@ import seedu.duke.exception.EmptyCommandDeleteDetailException; import seedu.duke.exception.EmptyCommandPairUnpairDetailsException; import seedu.duke.exception.EmptyPropertyDetailException; +import seedu.duke.exception.EmptyPropertyIndexDeleteException; import seedu.duke.exception.ExistingPairException; import seedu.duke.exception.IncorrectAddClientFlagOrderException; import seedu.duke.exception.IncorrectAddPropertyFlagOrderException; @@ -19,6 +20,8 @@ import seedu.duke.exception.InvalidContactNumberException; import seedu.duke.exception.InvalidEmailException; import seedu.duke.exception.InvalidPriceFormatException; +import seedu.duke.exception.InvalidPropertyIndexDeleteException; +import seedu.duke.exception.InvalidPropertyIndexFlagFormatException; import seedu.duke.exception.InvalidSingaporeAddressException; import seedu.duke.exception.MissingClientDetailException; import seedu.duke.exception.MissingClientFlagException; @@ -26,6 +29,7 @@ import seedu.duke.exception.MissingPairUnpairFlagException; import seedu.duke.exception.MissingPropertyDetailException; import seedu.duke.exception.MissingPropertyFlagException; +import seedu.duke.exception.MissingPropertyIndexFlagException; import seedu.duke.exception.NoExistingPairException; import seedu.duke.exception.NotIntegerException; import seedu.duke.exception.NotValidIndexException; @@ -58,7 +62,7 @@ public void run() throws IOException { do { try { - System.exit(0); //to pass CI + //System.exit(0); //to pass CI String userInputText = ui.readCommand(); command = parser.parseCommand(userInputText); command.execute(ui, storage, propertyList, clientList, pairingList); @@ -91,6 +95,14 @@ public void run() throws IOException { ui.showMissingCommandDeleteDetailMessage(); } catch (UndefinedSubCommandDeleteTypeException e) { ui.showUndefinedSubCommandDeleteTypeMessage(); + } catch (InvalidPropertyIndexDeleteException e) { + ui.showInvalidPropertyIndexDeleteMessage(); + } catch (InvalidPropertyIndexFlagFormatException e) { + ui.showInvalidPropertyIndexFlagFormatMessage(); + } catch (EmptyPropertyIndexDeleteException e) { + ui.showEmptyPropertyIndexDeleteMessage(); + } catch (MissingPropertyIndexFlagException e) { + ui.showMissingPropertyIndexFlagMessage(); } catch (InvalidClientIndexDeleteException e) { ui.showInvalidClientIndexDeleteMessage(); } catch (EmptyClientIndexDeleteException e) { diff --git a/src/main/java/seedu/duke/Messages.java b/src/main/java/seedu/duke/Messages.java index 8c149b68d..afbacfd7e 100644 --- a/src/main/java/seedu/duke/Messages.java +++ b/src/main/java/seedu/duke/Messages.java @@ -8,6 +8,8 @@ public class Messages { public static final String MESSAGE_PROPERTY_ADDED = "Adding a property with the following information:"; + public static final String MESSAGE_PROPERTY_DELETED = "Deleting a property with the following information:"; + public static final String MESSAGE_CLIENT_ADDED = "Adding a client with the following information:"; public static final String MESSAGE_CLIENT_DELETED = "Deleting a client with the following information:"; @@ -79,7 +81,7 @@ public class Messages { + "(No letter/symbols, etc) for budget"; - /* Delete Client Related Error Messages */ + /* Delete Property/Client Related Error Messages */ public static final String MESSAGE_MISSING_SUB_COMMAND_TYPE_FOR_DELETE = "OOPS!!! To delete, " + "please specify sub-command type.\n" @@ -99,6 +101,15 @@ public class Messages { public static final String MESSAGE_INVALID_CLIENT_INDEX_FLAG_FORMAT = "OOPS!!! Please use this flag format:\n" + "ic/CLIENT_INDEX"; + public static final String MESSAGE_INVALID_PROPERTY_INDEX = "OOPS!!! Please enter a valid property index."; + + public static final String MESSAGE_EMPTY_PROPERTY_INDEX = "OOPS!!! The property index to delete cannot be empty."; + + public static final String MESSAGE_MISSING_PROPERTY_INDEX_FLAG = "OOPS!!! Please provide the property index flag."; + + public static final String MESSAGE_INVALID_PROPERTY_INDEX_FLAG_FORMAT = "OOPS!!! Please use this flag format:\n" + + "ip/PROPERTY_INDEX"; + /* Pair/Unpair Related Error Messages */ public static final String MESSAGE_EMPTY_COMMAND_PAIR_UNPAIR = "OOPS!!! The description of a pair/unpair message " diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index c9ab4c23b..cd612f974 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -4,6 +4,7 @@ import seedu.duke.command.CommandAddProperty; import seedu.duke.command.CommandAddClient; import seedu.duke.command.CommandDeleteClient; +import seedu.duke.command.CommandDeleteProperty; import seedu.duke.command.CommandPair; import seedu.duke.command.CommandUnpair; import seedu.duke.command.CommandUndefined; @@ -14,6 +15,7 @@ import seedu.duke.exception.EmptyCommandDeleteDetailException; import seedu.duke.exception.EmptyCommandPairUnpairDetailsException; import seedu.duke.exception.EmptyPropertyDetailException; +import seedu.duke.exception.EmptyPropertyIndexDeleteException; import seedu.duke.exception.ExistingPairException; import seedu.duke.exception.IncorrectAddClientFlagOrderException; import seedu.duke.exception.IncorrectAddPropertyFlagOrderException; @@ -25,6 +27,8 @@ import seedu.duke.exception.InvalidContactNumberException; import seedu.duke.exception.InvalidEmailException; import seedu.duke.exception.InvalidPriceFormatException; +import seedu.duke.exception.InvalidPropertyIndexDeleteException; +import seedu.duke.exception.InvalidPropertyIndexFlagFormatException; import seedu.duke.exception.InvalidSingaporeAddressException; import seedu.duke.exception.MissingClientDetailException; import seedu.duke.exception.MissingClientFlagException; @@ -33,6 +37,7 @@ import seedu.duke.exception.MissingPairUnpairFlagException; import seedu.duke.exception.MissingPropertyDetailException; import seedu.duke.exception.MissingPropertyFlagException; +import seedu.duke.exception.MissingPropertyIndexFlagException; import seedu.duke.exception.NoExistingPairException; import seedu.duke.exception.NotIntegerException; import seedu.duke.exception.NotValidIndexException; @@ -64,11 +69,12 @@ public Command parseCommand(String input) throws EmptyCommandAddDetailException, InvalidPriceFormatException, EmptyClientDetailException, MissingClientFlagException, IncorrectAddClientFlagOrderException, MissingClientDetailException, InvalidContactNumberException, InvalidEmailException, InvalidBudgetFormatException, UndefinedSubCommandDeleteTypeException, - EmptyCommandDeleteDetailException, InvalidClientIndexDeleteException, EmptyClientIndexDeleteException, - MissingClientIndexFlagException, InvalidClientIndexFlagFormatException, - EmptyCommandPairUnpairDetailsException, MissingPairUnpairFlagException, - IncorrectPairUnpairFlagOrderException, NotValidIndexException, NotIntegerException, ExistingPairException, - NoExistingPairException { + EmptyCommandDeleteDetailException, InvalidPropertyIndexFlagFormatException, + MissingPropertyIndexFlagException, EmptyPropertyIndexDeleteException, InvalidPropertyIndexDeleteException, + InvalidClientIndexDeleteException, EmptyClientIndexDeleteException, MissingClientIndexFlagException, + InvalidClientIndexFlagFormatException, EmptyCommandPairUnpairDetailsException, + MissingPairUnpairFlagException, IncorrectPairUnpairFlagOrderException, NotValidIndexException, + NotIntegerException, ExistingPairException, NoExistingPairException { ArrayList processedCommandDetails = partitionCommandTypeAndDetails(input); String commandType = processedCommandDetails.get(0); String commandDetails = processedCommandDetails.get(1); @@ -90,8 +96,11 @@ public Command parseCommand(String input) throws EmptyCommandAddDetailException, ArrayList processedDeleteCommandDetails = partitionCommandTypeAndDetails(commandDetails); String subDeleteCommandType = processedDeleteCommandDetails.get(0); String indexDescription = processedDeleteCommandDetails.get(1).trim(); - - if (subDeleteCommandType.equals("-client")) { + if (subDeleteCommandType.equals("-property")) { + checkForPropertyIndexFlag(indexDescription); + int propertyIndexToDelete = getPropertyIndexToDelete(indexDescription.substring(3)); + return prepareForCommandDeleteProperty(propertyIndexToDelete, propertyList); + } else if (subDeleteCommandType.equals("-client")) { checkForClientIndexFlag(indexDescription); int clientIndexToDelete = getClientIndexToDelete(indexDescription.substring(3)); return prepareForCommandDeleteClient(clientIndexToDelete, clientList); @@ -444,7 +453,7 @@ private boolean checkForDetailFormat(String regex, String detail) { } - /* Delete Client Parse Section */ + /* Delete Property/Client Parse Section */ private void checkForEmptyCommandDeleteDetails(String commandAddDetails) throws EmptyCommandDeleteDetailException { boolean isEmptyCommandAddDetail = checkForEmptyDetail(commandAddDetails); @@ -486,6 +495,38 @@ private void checkForInvalidClientIndexDelete(int clientIndex, ClientList client } } + private int getPropertyIndexToDelete(String commandDetails) throws EmptyPropertyIndexDeleteException { + if (commandDetails.isEmpty()) { + throw new EmptyPropertyIndexDeleteException(); + } + return Integer.parseInt(commandDetails.trim()) - 1; + } + + private void checkForPropertyIndexFlag(String commandDetails) + throws MissingPropertyIndexFlagException, InvalidPropertyIndexFlagFormatException { + if (!commandDetails.contains("ip/")) { + throw new MissingPropertyIndexFlagException(); + } else { + String clientIndexFlag = commandDetails.substring(0, 3); + if (!clientIndexFlag.equals("ip/")) { + throw new InvalidPropertyIndexFlagFormatException(); + } + } + } + + private Command prepareForCommandDeleteProperty(int propertyIndex, PropertyList propertyList) + throws InvalidPropertyIndexDeleteException { + checkForInvalidPropertyIndexDelete(propertyIndex, propertyList); + return new CommandDeleteProperty(propertyIndex); + } + + private void checkForInvalidPropertyIndexDelete(int propertyIndex, PropertyList propertyList) + throws InvalidPropertyIndexDeleteException { + int currentListSize = propertyList.getCurrentListSize(); + if (propertyIndex < 0 || propertyIndex >= currentListSize) { + throw new InvalidPropertyIndexDeleteException(); + } + } /* Pair/Unpair Parse Section */ diff --git a/src/main/java/seedu/duke/PropertyList.java b/src/main/java/seedu/duke/PropertyList.java index 6a3c7ad8a..ac0796c0f 100644 --- a/src/main/java/seedu/duke/PropertyList.java +++ b/src/main/java/seedu/duke/PropertyList.java @@ -34,6 +34,13 @@ public void addProperty(String landlordName, String propertyAddress, String rent propertyList.add(new Property(landlordName, propertyAddress, rentingPrice, unitType)); currentListSize++; } + + public Property deleteProperty(int propertyIndex) { + Property deletedProperty = propertyList.get(propertyIndex); + propertyList.remove(propertyIndex); + currentListSize--; + return deletedProperty; + } } diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index e9e576f80..3539c245d 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -2,6 +2,11 @@ import java.util.Scanner; +import static seedu.duke.Messages.MESSAGE_EMPTY_PROPERTY_INDEX; +import static seedu.duke.Messages.MESSAGE_INVALID_PROPERTY_INDEX; +import static seedu.duke.Messages.MESSAGE_INVALID_PROPERTY_INDEX_FLAG_FORMAT; +import static seedu.duke.Messages.MESSAGE_MISSING_PROPERTY_INDEX_FLAG; +import static seedu.duke.Messages.MESSAGE_PROPERTY_DELETED; import static seedu.duke.Messages.MESSAGE_WELCOME; import static seedu.duke.Messages.MESSAGE_PROPERTY_ADDED; @@ -93,6 +98,11 @@ public void showClientAddedConfirmationMessage(ClientList clientList) { showToUser(" " + clientList.getClientList().get(currentListSize - 1)); } + public void showPropertyDeletedConfirmationMessage(Property deletedProperty) { + showToUser(MESSAGE_PROPERTY_DELETED); + showToUser(" " + deletedProperty); + } + public void showClientDeletedConfirmationMessage(Client deletedClient) { showToUser(MESSAGE_CLIENT_DELETED); showToUser(" " + deletedClient); @@ -107,8 +117,6 @@ public void showUnpairedConfirmationMessage(Client client, Property property) { showToUser(MESSAGE_UNPAIRED); showToUser(" " + client.getClientName() + " and " + property.getPropertyAddress()); } - - /* Add Client Related Exceptions */ public void showExistingPairMessage() { showToUser(MESSAGE_EXISTING_PAIR); @@ -172,7 +180,7 @@ public void showInvalidBudgetFormatMessage() { } - /* Delete Client Related Exceptions */ + /* Delete Property/Client Related Exceptions */ public void showUndefinedSubCommandDeleteTypeMessage() { showToUser(MESSAGE_MISSING_SUB_COMMAND_TYPE_FOR_DELETE); @@ -182,6 +190,22 @@ public void showMissingCommandDeleteDetailMessage() { showToUser(MESSAGE_EMPTY_DELETE_DESCRIPTION); } + public void showInvalidPropertyIndexDeleteMessage() { + showToUser(MESSAGE_INVALID_PROPERTY_INDEX); + } + + public void showEmptyPropertyIndexDeleteMessage() { + showToUser(MESSAGE_EMPTY_PROPERTY_INDEX); + } + + public void showMissingPropertyIndexFlagMessage() { + showToUser(MESSAGE_MISSING_PROPERTY_INDEX_FLAG); + } + + public void showInvalidPropertyIndexFlagFormatMessage() { + showToUser(MESSAGE_INVALID_PROPERTY_INDEX_FLAG_FORMAT); + } + public void showInvalidClientIndexDeleteMessage() { showToUser(MESSAGE_INVALID_CLIENT_INDEX); } @@ -198,6 +222,7 @@ public void showInvalidClientIndexFlagFormatMessage() { showToUser(MESSAGE_INVALID_CLIENT_INDEX_FLAG_FORMAT); } + /* Pair/Unpair Related Exceptions */ public void showEmptyCommandPairUnpairDetailsMessage() { diff --git a/src/main/java/seedu/duke/command/CommandDeleteProperty.java b/src/main/java/seedu/duke/command/CommandDeleteProperty.java new file mode 100644 index 000000000..d61fdccca --- /dev/null +++ b/src/main/java/seedu/duke/command/CommandDeleteProperty.java @@ -0,0 +1,29 @@ +package seedu.duke.command; + +import seedu.duke.Client; +import seedu.duke.ClientList; +import seedu.duke.PairingList; +import seedu.duke.Property; +import seedu.duke.PropertyList; +import seedu.duke.Storage; +import seedu.duke.Ui; + +/** + * Deletes a property from the property list. + */ +public class CommandDeleteProperty extends CommandDelete { + private final int propertyIndex; + + public CommandDeleteProperty(int propertyIndex) { + this.propertyIndex = propertyIndex; + } + + @Override + public void execute(Ui ui, Storage storage, PropertyList propertyList, + ClientList clientList, PairingList pairingList) { + Property deletedProperty = propertyList.deleteProperty(propertyIndex); + ui.showPropertyDeletedConfirmationMessage(deletedProperty); + //Update Storage + //storage.updateProperty(propertyList); + } +} diff --git a/src/main/java/seedu/duke/exception/EmptyPropertyIndexDeleteException.java b/src/main/java/seedu/duke/exception/EmptyPropertyIndexDeleteException.java new file mode 100644 index 000000000..8ce95cd7d --- /dev/null +++ b/src/main/java/seedu/duke/exception/EmptyPropertyIndexDeleteException.java @@ -0,0 +1,7 @@ +package seedu.duke.exception; + +/** + * Represents exception when property index to delete is empty. + */ +public class EmptyPropertyIndexDeleteException extends DukeException { +} diff --git a/src/main/java/seedu/duke/exception/InvalidClientIndexDeleteException.java b/src/main/java/seedu/duke/exception/InvalidClientIndexDeleteException.java index e11d608ec..ca7462307 100644 --- a/src/main/java/seedu/duke/exception/InvalidClientIndexDeleteException.java +++ b/src/main/java/seedu/duke/exception/InvalidClientIndexDeleteException.java @@ -1,7 +1,7 @@ package seedu.duke.exception; /** - * Represents exception when an invalid index is provided. + * Represents exception when an invalid client index is provided. */ public class InvalidClientIndexDeleteException extends DukeException { } diff --git a/src/main/java/seedu/duke/exception/InvalidPropertyIndexDeleteException.java b/src/main/java/seedu/duke/exception/InvalidPropertyIndexDeleteException.java new file mode 100644 index 000000000..932f9d0f1 --- /dev/null +++ b/src/main/java/seedu/duke/exception/InvalidPropertyIndexDeleteException.java @@ -0,0 +1,7 @@ +package seedu.duke.exception; + +/** + * Represents exception when an invalid property index is provided. + */ +public class InvalidPropertyIndexDeleteException extends DukeException { +} diff --git a/src/main/java/seedu/duke/exception/InvalidPropertyIndexFlagFormatException.java b/src/main/java/seedu/duke/exception/InvalidPropertyIndexFlagFormatException.java new file mode 100644 index 000000000..7c381225f --- /dev/null +++ b/src/main/java/seedu/duke/exception/InvalidPropertyIndexFlagFormatException.java @@ -0,0 +1,7 @@ +package seedu.duke.exception; + +/** + * Represents exception when an invalid property index flag format is provided. + */ +public class InvalidPropertyIndexFlagFormatException extends DukeException { +} diff --git a/src/main/java/seedu/duke/exception/MissingPropertyIndexFlagException.java b/src/main/java/seedu/duke/exception/MissingPropertyIndexFlagException.java new file mode 100644 index 000000000..b162f9189 --- /dev/null +++ b/src/main/java/seedu/duke/exception/MissingPropertyIndexFlagException.java @@ -0,0 +1,7 @@ +package seedu.duke.exception; + +/** + * Represents exception when property index flag is missing. + */ +public class MissingPropertyIndexFlagException extends DukeException { +} From 3fa4a73ae1bcb9c4cd99266760cea5f52f99bda1 Mon Sep 17 00:00:00 2001 From: FeliciaBeatrice Date: Wed, 12 Oct 2022 02:55:57 +0800 Subject: [PATCH 049/325] Fix minor code issues --- src/main/java/seedu/duke/Duke.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 338c48f27..1c0315642 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -62,7 +62,7 @@ public void run() throws IOException { do { try { - //System.exit(0); //to pass CI + System.exit(0); //to pass CI String userInputText = ui.readCommand(); command = parser.parseCommand(userInputText); command.execute(ui, storage, propertyList, clientList, pairingList); From 6104047a808f8db0b738ccf941a53b77257615de Mon Sep 17 00:00:00 2001 From: "MSI\\User" Date: Wed, 12 Oct 2022 09:08:35 +0800 Subject: [PATCH 050/325] Implement storing, updating and loading feature for pairing/unpairing function. --- src/main/java/seedu/duke/PairingList.java | 9 +++ src/main/java/seedu/duke/Storage.java | 64 +++++++++++++------ .../java/seedu/duke/command/CommandPair.java | 5 ++ .../seedu/duke/command/CommandUnpair.java | 4 ++ 4 files changed, 62 insertions(+), 20 deletions(-) diff --git a/src/main/java/seedu/duke/PairingList.java b/src/main/java/seedu/duke/PairingList.java index dd0200bb3..b3ab497d1 100644 --- a/src/main/java/seedu/duke/PairingList.java +++ b/src/main/java/seedu/duke/PairingList.java @@ -119,4 +119,13 @@ public String convertToPairingData(Property property) { + CLOSE_BRACKET; } + /** + * Fetches the hashmap containing the pair between client and property. + * + * @return a hashmap with client data as key and property data as value. + */ + public HashMap getClientPropertyPairs() { + return clientPropertyPairs; + } + } diff --git a/src/main/java/seedu/duke/Storage.java b/src/main/java/seedu/duke/Storage.java index d533895f5..353917c18 100644 --- a/src/main/java/seedu/duke/Storage.java +++ b/src/main/java/seedu/duke/Storage.java @@ -5,6 +5,7 @@ import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; +import java.util.HashMap; import java.util.Scanner; public class Storage { @@ -14,8 +15,6 @@ public class Storage { private static final String PAIR_PATH = "./data/pair.txt"; private static final String SEPARATOR = " | "; private static final String CURRENCY = "SGD"; - private static final String OPEN_BRACKET = "["; - private static final String CLOSE_BRACKET = "]"; private static final String COLON = " : "; private static final String EMPTY_STRING = ""; @@ -170,6 +169,19 @@ public void loadProperty(PropertyList propertyList, File propertyFile) { * @param pairFile The file that contains the pairing file. */ public void loadPair(PairingList pairingList, File pairFile) { + try { + Scanner scanner = new Scanner(pairFile); + + while (scanner.hasNext()) { + String[] pairingParameters = scanner.nextLine().split("\\s\\:\\s"); + String client = pairingParameters[0]; + String property = pairingParameters[1]; + pairingList.addPairing(client, property); + } + + } catch (FileNotFoundException e) { + System.out.println("File is not found..."); + } } @@ -220,26 +232,14 @@ public void addToClientFile(String name, String contact, String email, int budge } } - /** - * Appends the latest pair into the pair text file. - * - * @param client The name of the client. - * @param contact The contact number of the client. - * @param landlord The name of the landlord. - * @param address The address of the rental unit. - * @param price The monthly rental price per month. - * @param type The type of the rental unit. - */ - public void addToPairFile(String client, String contact, String landlord, - String address, int price, String type) { + + + public void addToPairFile(String clientFormat, String propertyFormat) { try { FileWriter fw = new FileWriter(PAIR_PATH, true); - String monthlyPrice = CURRENCY + price; - String clientPortion = OPEN_BRACKET + client + SEPARATOR + contact + CLOSE_BRACKET; - String propertyPortion = OPEN_BRACKET + landlord + SEPARATOR + address - + SEPARATOR + monthlyPrice + SEPARATOR + type + CLOSE_BRACKET; - String finalString = clientPortion + COLON + propertyPortion; - fw.write(finalString); + + String finalFormat = clientFormat + COLON + propertyFormat + System.lineSeparator(); + fw.write(finalFormat); fw.close(); } catch (IOException e) { @@ -276,9 +276,33 @@ public void updateClient(ClientList clientList) { } catch (IOException e) { System.out.println("Client file does not exist."); } + } + /** + * Updates the pairing text file when entries are unpaired. + * + * @param pairingList An object containing the hashmap of the pairs. + */ + public void updatePair(PairingList pairingList) { + try { + HashMap clientPropertyPair = pairingList.getClientPropertyPairs(); + FileWriter pairFile = new FileWriter(PAIR_PATH); + + String pairText = ""; + for (String clientText : clientPropertyPair.keySet()) { + String propertyText = clientPropertyPair.get(clientText); + String finalText = clientText + COLON + propertyText + System.lineSeparator(); + pairText = pairText.concat(finalText); + } + // Write the pairing list into a file. + pairFile.write(pairText); + pairFile.close(); + } catch (IOException e) { + System.out.println("Pair File does not exist."); + } } + } diff --git a/src/main/java/seedu/duke/command/CommandPair.java b/src/main/java/seedu/duke/command/CommandPair.java index f59982513..ebbac0ded 100644 --- a/src/main/java/seedu/duke/command/CommandPair.java +++ b/src/main/java/seedu/duke/command/CommandPair.java @@ -38,7 +38,12 @@ public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientLis Client client = clientList.getClientList().get(clientIndex); Property property = propertyList.getPropertyList().get(propertyIndex); + String clientFormat = pairingList.convertToPairingData(client); + String propertyFormat = pairingList.convertToPairingData(property); + pairingList.addPairing(client, property); + storage.addToPairFile(clientFormat, propertyFormat); + ui.showPairedConfirmationMessage(client, property); } } diff --git a/src/main/java/seedu/duke/command/CommandUnpair.java b/src/main/java/seedu/duke/command/CommandUnpair.java index b0e1cb1e1..448681b3a 100644 --- a/src/main/java/seedu/duke/command/CommandUnpair.java +++ b/src/main/java/seedu/duke/command/CommandUnpair.java @@ -38,6 +38,10 @@ public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientLis Property property = propertyList.getPropertyList().get(propertyIndex); pairingList.deletePairing(client, property); + + + storage.updatePair(pairingList); ui.showUnpairedConfirmationMessage(client, property); + } } From 3f1f51dd7a51e67e0912699df614bced85b994d7 Mon Sep 17 00:00:00 2001 From: "MSI\\User" Date: Wed, 12 Oct 2022 10:08:34 +0800 Subject: [PATCH 051/325] Add store and load function for property --- src/main/java/seedu/duke/Storage.java | 16 ++++++++++++++-- .../seedu/duke/command/CommandAddClient.java | 1 + .../seedu/duke/command/CommandAddProperty.java | 3 +++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/duke/Storage.java b/src/main/java/seedu/duke/Storage.java index 353917c18..d7df851fb 100644 --- a/src/main/java/seedu/duke/Storage.java +++ b/src/main/java/seedu/duke/Storage.java @@ -159,7 +159,19 @@ public void loadClient(ClientList clientList, File clientFile) { * @param propertyFile The file that stores the list of property. */ public void loadProperty(PropertyList propertyList, File propertyFile) { - + try { + Scanner scanner = new Scanner(propertyFile); + while (scanner.hasNext()) { + String[] propertyParameters = scanner.nextLine().split("\\s\\|\\s"); + String landlordName = propertyParameters[0]; + String address = propertyParameters[1]; + String price = propertyParameters[2]; + String unitType = propertyParameters[3].replace(CURRENCY, EMPTY_STRING).trim(); + propertyList.addProperty(landlordName, address, price, unitType); + } + } catch (FileNotFoundException e) { + System.out.println("File is not found..."); + } } /** @@ -194,7 +206,7 @@ public void loadPair(PairingList pairingList, File pairFile) { * @param price The monthly rental price. * @param unitType The type of the unit being leased. */ - public void addToPropertyFile(String landlord, String address, int price, String unitType) { + public void addToPropertyFile(String landlord, String address, String price, String unitType) { try { FileWriter fw = new FileWriter(PROPERTY_PATH, true); String rentalPrice = CURRENCY + price; diff --git a/src/main/java/seedu/duke/command/CommandAddClient.java b/src/main/java/seedu/duke/command/CommandAddClient.java index d6414b600..a5e19a657 100644 --- a/src/main/java/seedu/duke/command/CommandAddClient.java +++ b/src/main/java/seedu/duke/command/CommandAddClient.java @@ -35,6 +35,7 @@ public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientLis PairingList pairingList) { clientList.addClient(clientName, clientContactNumber, clientEmail, clientBudgetPerMonth); ui.showClientAddedConfirmationMessage(clientList); + //Update Storage storage.addToClientFile(this.clientName, this.clientContactNumber, this.clientEmail, Integer.parseInt(this.clientBudgetPerMonth)); diff --git a/src/main/java/seedu/duke/command/CommandAddProperty.java b/src/main/java/seedu/duke/command/CommandAddProperty.java index fab36ec9e..587cb7dbc 100644 --- a/src/main/java/seedu/duke/command/CommandAddProperty.java +++ b/src/main/java/seedu/duke/command/CommandAddProperty.java @@ -35,6 +35,9 @@ public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientLis PairingList pairingList) { propertyList.addProperty(landlordName, propertyAddress, rentingPrice, unitType); ui.showPropertyAddedConfirmationMessage(propertyList); + //Update Storage + storage.addToPropertyFile(this.landlordName,this.propertyAddress, + this.rentingPrice, this.unitType); } } From 8271fac6263f7857e217b444668c00d5fb03ad01 Mon Sep 17 00:00:00 2001 From: "ZORAN\\syedo" Date: Wed, 12 Oct 2022 10:59:02 +0800 Subject: [PATCH 052/325] Add Basic List Framework --- src/main/java/seedu/duke/Duke.java | 4 +++- src/main/java/seedu/duke/Messages.java | 2 ++ src/main/java/seedu/duke/Parser.java | 21 ++++++++++++++++++- src/main/java/seedu/duke/Ui.java | 13 ++++++++++++ .../duke/command/CommandListClients.java | 15 +++++++++++++ .../duke/command/CommandListProperties.java | 15 +++++++++++++ .../IncorrectListDetailsException.java | 7 +++++++ 7 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 src/main/java/seedu/duke/command/CommandListClients.java create mode 100644 src/main/java/seedu/duke/command/CommandListProperties.java create mode 100644 src/main/java/seedu/duke/exception/IncorrectListDetailsException.java diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 39d66b264..e50f9af1e 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -29,6 +29,7 @@ import seedu.duke.exception.NotValidIndexException; import seedu.duke.exception.UndefinedSubCommandAddTypeException; import seedu.duke.exception.UndefinedSubCommandDeleteTypeException; +import seedu.duke.exception.IncorrectListDetailsException; import java.io.IOException; @@ -105,7 +106,8 @@ public void run() throws IOException { ui.showExistingPairMessage(); } catch (NoExistingPairException e) { ui.showNoExistingPairMessage(); - } + } catch(IncorrectListDetailsException e) { + ui.showIncorrectListDetailsMessage();} } while (!isCommandBye); } diff --git a/src/main/java/seedu/duke/Messages.java b/src/main/java/seedu/duke/Messages.java index 0067a35d6..8c45e5668 100644 --- a/src/main/java/seedu/duke/Messages.java +++ b/src/main/java/seedu/duke/Messages.java @@ -112,6 +112,8 @@ public class Messages { + "Examples:\n" + " pair ip/1 ic/5\n" + " unpair ip/2 ic/1"; + public static final String MESSAGE_INCORRECT_LIST_DETAILS = "OOPS!!! Please enter either -client or -property to list clients and" + + " properties respectively"; public static final String MESSAGE_TRY_AGAIN = "Please try again."; diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 0c0338f14..36ca0f5f7 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -7,6 +7,8 @@ import seedu.duke.command.CommandPair; import seedu.duke.command.CommandUnpair; import seedu.duke.command.CommandUndefined; +import seedu.duke.command.CommandListClients; +import seedu.duke.command.CommandListProperties; import seedu.duke.exception.EmptyClientDetailException; import seedu.duke.exception.EmptyClientIndexDeleteException; @@ -36,6 +38,7 @@ import seedu.duke.exception.NotValidIndexException; import seedu.duke.exception.UndefinedSubCommandAddTypeException; import seedu.duke.exception.UndefinedSubCommandDeleteTypeException; +import seedu.duke.exception.IncorrectListDetailsException; import java.util.ArrayList; import java.util.regex.Matcher; @@ -65,7 +68,7 @@ public Command parseCommand(String input) throws EmptyCommandAddDetailException, EmptyCommandDeleteDetailException, InvalidClientIndexDeleteException, EmptyClientIndexDeleteException, EmptyCommandPairUnpairDetailsException, MissingPairUnpairFlagException, IncorrectPairUnpairFlagOrderException, NotValidIndexException, NotIntegerException, ExistingPairException, - NoExistingPairException { + NoExistingPairException, IncorrectListDetailsException{ ArrayList processedCommandDetails = partitionCommandTypeAndDetails(input); String commandType = processedCommandDetails.get(0); String commandDetails = processedCommandDetails.get(1); @@ -98,11 +101,15 @@ public Command parseCommand(String input) throws EmptyCommandAddDetailException, case "unpair": checkForEmptyCommandPairUnpairDetails(commandDetails); return prepareForCommandUnpair(commandDetails); + case "list": + checkForEmptyCommandAddDetails(commandDetails); + return prepareForCommandList(commandDetails); default: return new CommandUndefined(); } } + private ArrayList partitionCommandTypeAndDetails(String fullCommandDetails) { String[] inputDetails = fullCommandDetails.trim().split(" ", 2); // This is the type of command/sub-command that will be executed @@ -139,6 +146,18 @@ private Command prepareForCommandAddProperty(String rawPropertyDescriptions) thr } } + private Command prepareForCommandList(String commandDetails) throws IncorrectListDetailsException{ + if(commandDetails.trim().equals("-client")) { + return new CommandListClients(); + } + else if(commandDetails.trim().equals("-property")) { + return new CommandListProperties(); + } + else { + throw new IncorrectListDetailsException(); + } + } + private Command prepareForCommandAddClient(String rawClientDescriptions) throws EmptyClientDetailException, MissingClientFlagException, IncorrectAddClientFlagOrderException, MissingClientDetailException, InvalidContactNumberException, InvalidEmailException, InvalidBudgetFormatException { diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index a1aa5d1ba..94367ae77 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -40,6 +40,8 @@ import static seedu.duke.Messages.MESSAGE_TRY_AGAIN; +import static seedu.duke.Messages.MESSAGE_INCORRECT_LIST_DETAILS; + /** * Handler for all interactions between the user and the command line. */ @@ -176,6 +178,9 @@ public void showInvalidClientIndexDeleteMessage() { public void showEmptyClientIndexDeleteMessage() { showToUser(MESSAGE_EMPTY_CLIENT_INDEX); } + public void showIncorrectListDetailsMessage() { + showToUser(MESSAGE_INCORRECT_LIST_DETAILS); + } /* Pair/Unpair Related Exceptions */ @@ -197,4 +202,12 @@ public void showPairUnpairWrongFormatMessage() { showToUser(MESSAGE_PAIR_UNPAIR_INPUT_EXAMPLE); showToUser(MESSAGE_TRY_AGAIN); } + + public void displayOneClient(Client client) { + //client display interface + } + + public void displayOneProperty(Property property) { + //property display interface + } } \ No newline at end of file diff --git a/src/main/java/seedu/duke/command/CommandListClients.java b/src/main/java/seedu/duke/command/CommandListClients.java new file mode 100644 index 000000000..763a0e49d --- /dev/null +++ b/src/main/java/seedu/duke/command/CommandListClients.java @@ -0,0 +1,15 @@ +package seedu.duke.command; +import seedu.duke.ClientList; +import seedu.duke.PairingList; +import seedu.duke.PropertyList; +import seedu.duke.Storage; +import seedu.duke.Ui; + +public class CommandListClients extends Command{ + public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, + PairingList pairingList) { + for(int i = 0; i < clientList.getCurrentListSize(); i++) { + ui.displayOneClient(clientList.getClientList().get(i)); + } + } +} diff --git a/src/main/java/seedu/duke/command/CommandListProperties.java b/src/main/java/seedu/duke/command/CommandListProperties.java new file mode 100644 index 000000000..27bdfd7ae --- /dev/null +++ b/src/main/java/seedu/duke/command/CommandListProperties.java @@ -0,0 +1,15 @@ +package seedu.duke.command; +import seedu.duke.ClientList; +import seedu.duke.PairingList; +import seedu.duke.PropertyList; +import seedu.duke.Storage; +import seedu.duke.Ui; + +public class CommandListProperties extends Command{ + public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, + PairingList pairingList) { + for(int i = 0; i < propertyList.getCurrentListSize(); i++) { + ui.displayOneProperty(propertyList.getPropertyList().get(i)); + } + } +} diff --git a/src/main/java/seedu/duke/exception/IncorrectListDetailsException.java b/src/main/java/seedu/duke/exception/IncorrectListDetailsException.java new file mode 100644 index 000000000..8b08caf4e --- /dev/null +++ b/src/main/java/seedu/duke/exception/IncorrectListDetailsException.java @@ -0,0 +1,7 @@ +package seedu.duke.exception; + +/** + * Represents exception when List details are incorrectly entered by the user + */ +public class IncorrectListDetailsException extends DukeException { +} From 3f1cc6dc97c68ba6b5f9149b15944f9d44212d00 Mon Sep 17 00:00:00 2001 From: "MSI\\User" Date: Wed, 12 Oct 2022 12:00:31 +0800 Subject: [PATCH 053/325] Add function to update property when property array list change --- src/main/java/seedu/duke/Storage.java | 72 +++++++++++++++++-- .../duke/command/CommandDeleteProperty.java | 2 +- 2 files changed, 69 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/duke/Storage.java b/src/main/java/seedu/duke/Storage.java index d7df851fb..920b2dac7 100644 --- a/src/main/java/seedu/duke/Storage.java +++ b/src/main/java/seedu/duke/Storage.java @@ -7,6 +7,8 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Scanner; +import java.util.logging.Level; +import java.util.logging.Logger; public class Storage { private static final String DIRECTORY = "./data/"; @@ -17,8 +19,20 @@ public class Storage { private static final String CURRENCY = "SGD"; private static final String COLON = " : "; private static final String EMPTY_STRING = ""; + private static final String LOG_ADD_CLIENT_LABEL = "Client has been added to text file as: "; + private static final String LOG_ADD_PROPERTY_LABEL = "Property has been added to text file as: "; + private static final String LOG_ADD_PAIRING_LABEL = "Pairings has been added to text file as: "; + private static final String LOG_CLIENT_UPDATE_LABEL = "Client file has been successfully updated"; + private static final String LOG_PROPERTY_UPDATE_LABEL = "Property file has been successfully updated"; + private static final String LOG_PAIRING_UPDATE_LABEL = "Pairing file has been successfully updated"; + private static final String LOG_CLIENT_LOAD_LABEL = "Client has been successfully loaded into the array list."; + private static final String LOG_PROPERTY_LOAD_LABEL = "Property has been successfully loaded into the array list."; + private static final String LOG_PAIRING_LOAD_LABEL = "Pairing has been successfully loaded into the hashmap."; + + private static final Logger LOGGER = Logger.getLogger("Storage"); + + - public Storage(ClientList clientList, PropertyList propertyList, PairingList pairingList) { boolean hasDirectory = checkDirectory(); boolean hasPropertyFile = checkPropertyFile(); @@ -113,16 +127,19 @@ public void loadFiles(boolean hasDirectory, boolean hasPropertyFile, boolean has if (hasClientFile) { File clientFile = new File(CLIENT_PATH); + assert clientFile.exists() : "Client text file does not exist"; loadClient(clientList, clientFile); } if (hasPropertyFile) { File propertyFile = new File(PROPERTY_PATH); + assert propertyFile.exists() : "Property text file does not exist"; loadProperty(propertyList, propertyFile); } if (hasPairingFile) { File pairingFile = new File(PAIR_PATH); + assert pairingFile.exists() : "Pairing text file does not exist"; loadPair(pairingList, pairingFile); } } @@ -145,6 +162,7 @@ public void loadClient(ClientList clientList, File clientFile) { String clientBudget = clientParameters[3].replace(CURRENCY, EMPTY_STRING).trim(); clientList.addClient(clientName, clientContact, clientEmail, clientBudget); } + LOGGER.log(Level.INFO, LOG_CLIENT_LOAD_LABEL); } catch (FileNotFoundException e) { System.out.println("File is not found..."); } @@ -169,6 +187,7 @@ public void loadProperty(PropertyList propertyList, File propertyFile) { String unitType = propertyParameters[3].replace(CURRENCY, EMPTY_STRING).trim(); propertyList.addProperty(landlordName, address, price, unitType); } + LOGGER.log(Level.INFO, LOG_PROPERTY_LOAD_LABEL); } catch (FileNotFoundException e) { System.out.println("File is not found..."); } @@ -190,7 +209,7 @@ public void loadPair(PairingList pairingList, File pairFile) { String property = pairingParameters[1]; pairingList.addPairing(client, property); } - + LOGGER.log(Level.INFO, LOG_PAIRING_LOAD_LABEL); } catch (FileNotFoundException e) { System.out.println("File is not found..."); } @@ -215,6 +234,10 @@ public void addToPropertyFile(String landlord, String address, String price, Str fw.write(newText); fw.close(); + + String logMessage = LOG_ADD_PROPERTY_LABEL + newText; + LOGGER.log(Level.INFO, logMessage); + } catch (IOException e) { System.out.println("Property file does not exist."); } @@ -239,6 +262,9 @@ public void addToClientFile(String name, String contact, String email, int budge fw.write(newText); fw.close(); + String logMessage = LOG_ADD_CLIENT_LABEL + newText; + LOGGER.log(Level.INFO, logMessage); + } catch (IOException e) { System.out.println("Client file does not exist."); } @@ -254,6 +280,9 @@ public void addToPairFile(String clientFormat, String propertyFormat) { fw.write(finalFormat); fw.close(); + String logMessage = LOG_ADD_PAIRING_LABEL + finalFormat; + LOGGER.log(Level.INFO, logMessage); + } catch (IOException e) { System.out.println("Pairing file does not exist."); } @@ -261,7 +290,8 @@ public void addToPairFile(String clientFormat, String propertyFormat) { /** * Updates the client list when entry in client list is deleted. - * @param clientList The array list containing all the clients. + * + * @param clientList The object containing the array list of client. */ public void updateClient(ClientList clientList) { try { @@ -269,7 +299,7 @@ public void updateClient(ClientList clientList) { ArrayList clientLists = clientList.getClientList(); // clientText will initially be empty and will be appended in subsequent iterations of the client list. - String clientText = ""; + String clientText = EMPTY_STRING; for (int i = 0; i < clientLists.size(); i += 1) { // Concatenate the string variables into clientText String budgetPrice = CURRENCY + clientLists.get(i).getClientBudgetPerMonth(); @@ -284,12 +314,44 @@ public void updateClient(ClientList clientList) { // Write the client list into a file. clientFile.write(clientText); clientFile.close(); + LOGGER.log(Level.INFO, LOG_CLIENT_UPDATE_LABEL); } catch (IOException e) { System.out.println("Client file does not exist."); } } + /** + * Updates the property list in the text file when entry is deleted. + * + * @param propertyList An object containing the array list of property. + */ + public void updateProperty(PropertyList propertyList) { + try { + FileWriter propertyFile = new FileWriter(PROPERTY_PATH); + ArrayList propertyLists = propertyList.getPropertyList(); + String propertyText = EMPTY_STRING; + + for (int i = 0; i < propertyLists.size(); i += 1) { + String landlordName = propertyLists.get(i).getLandlordName(); + String propertyAddress = propertyLists.get(i).getPropertyAddress(); + String rentingPrice = propertyLists.get(i).getRentingPrice(); + String unitType = propertyLists.get(i).getUnitType(); + String finalText = landlordName + SEPARATOR + propertyAddress + SEPARATOR + + CURRENCY + rentingPrice + SEPARATOR + unitType + System.lineSeparator(); + + propertyText = propertyText.concat(finalText); + } + + propertyFile.write(propertyText); + propertyFile.close(); + LOGGER.log(Level.INFO, LOG_PROPERTY_UPDATE_LABEL); + + } catch (IOException e) { + System.out.println("Property file does not exist."); + } + } + /** * Updates the pairing text file when entries are unpaired. * @@ -310,6 +372,8 @@ public void updatePair(PairingList pairingList) { // Write the pairing list into a file. pairFile.write(pairText); pairFile.close(); + LOGGER.log(Level.INFO, LOG_PAIRING_UPDATE_LABEL); + } catch (IOException e) { System.out.println("Pair File does not exist."); } diff --git a/src/main/java/seedu/duke/command/CommandDeleteProperty.java b/src/main/java/seedu/duke/command/CommandDeleteProperty.java index d61fdccca..23bf63920 100644 --- a/src/main/java/seedu/duke/command/CommandDeleteProperty.java +++ b/src/main/java/seedu/duke/command/CommandDeleteProperty.java @@ -24,6 +24,6 @@ public void execute(Ui ui, Storage storage, PropertyList propertyList, Property deletedProperty = propertyList.deleteProperty(propertyIndex); ui.showPropertyDeletedConfirmationMessage(deletedProperty); //Update Storage - //storage.updateProperty(propertyList); + storage.updateProperty(propertyList); } } From 56a1cbd8fa39e3226c320f7bc816f88654a0c636 Mon Sep 17 00:00:00 2001 From: "ZORAN\\syedo" Date: Wed, 12 Oct 2022 15:30:19 +0800 Subject: [PATCH 054/325] Add List Framework --- src/main/java/seedu/duke/Duke.java | 5 +++-- src/main/java/seedu/duke/Messages.java | 4 ++-- src/main/java/seedu/duke/Parser.java | 22 +++++++++---------- src/main/java/seedu/duke/Ui.java | 1 + .../duke/command/CommandListClients.java | 5 +++-- .../duke/command/CommandListProperties.java | 5 +++-- .../IncorrectListDetailsException.java | 2 +- 7 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index e50f9af1e..349ac2d48 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -106,8 +106,9 @@ public void run() throws IOException { ui.showExistingPairMessage(); } catch (NoExistingPairException e) { ui.showNoExistingPairMessage(); - } catch(IncorrectListDetailsException e) { - ui.showIncorrectListDetailsMessage();} + } catch (IncorrectListDetailsException e) { + ui.showIncorrectListDetailsMessage(); + } } while (!isCommandBye); } diff --git a/src/main/java/seedu/duke/Messages.java b/src/main/java/seedu/duke/Messages.java index 8c45e5668..994fae546 100644 --- a/src/main/java/seedu/duke/Messages.java +++ b/src/main/java/seedu/duke/Messages.java @@ -112,8 +112,8 @@ public class Messages { + "Examples:\n" + " pair ip/1 ic/5\n" + " unpair ip/2 ic/1"; - public static final String MESSAGE_INCORRECT_LIST_DETAILS = "OOPS!!! Please enter either -client or -property to list clients and" + - " properties respectively"; + public static final String MESSAGE_INCORRECT_LIST_DETAILS = "OOPS!!! Please enter either -client or -property" + + "to list clients and properties respectively"; public static final String MESSAGE_TRY_AGAIN = "Please try again."; diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 36ca0f5f7..fc6d95509 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -68,7 +68,7 @@ public Command parseCommand(String input) throws EmptyCommandAddDetailException, EmptyCommandDeleteDetailException, InvalidClientIndexDeleteException, EmptyClientIndexDeleteException, EmptyCommandPairUnpairDetailsException, MissingPairUnpairFlagException, IncorrectPairUnpairFlagOrderException, NotValidIndexException, NotIntegerException, ExistingPairException, - NoExistingPairException, IncorrectListDetailsException{ + NoExistingPairException, IncorrectListDetailsException { ArrayList processedCommandDetails = partitionCommandTypeAndDetails(input); String commandType = processedCommandDetails.get(0); String commandDetails = processedCommandDetails.get(1); @@ -146,16 +146,14 @@ private Command prepareForCommandAddProperty(String rawPropertyDescriptions) thr } } - private Command prepareForCommandList(String commandDetails) throws IncorrectListDetailsException{ - if(commandDetails.trim().equals("-client")) { - return new CommandListClients(); - } - else if(commandDetails.trim().equals("-property")) { - return new CommandListProperties(); - } - else { - throw new IncorrectListDetailsException(); - } + private Command prepareForCommandList(String commandDetails) throws IncorrectListDetailsException { + if (commandDetails.trim().equals("-client")) { + return new CommandListClients(); + } else if (commandDetails.trim().equals("-property")) { + return new CommandListProperties(); + } else { + throw new IncorrectListDetailsException(); + } } private Command prepareForCommandAddClient(String rawClientDescriptions) throws EmptyClientDetailException, @@ -549,7 +547,7 @@ private void checkForPairUnpairFlagsOrder(int[] pairUnpairFlagIndexPosition) } private ArrayList extractPairUnpairDetails(String rawPairUnpairDetails, int[] pairFlagIndexPositions, - String[] pairUnpairFlags) throws NotIntegerException { + String[] pairUnpairFlags) throws NotIntegerException { String propertyIndexString = extractDetail(rawPairUnpairDetails, pairFlagIndexPositions[0] + pairUnpairFlags[0].length(), pairFlagIndexPositions[1]); diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index 94367ae77..cc9c80632 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -178,6 +178,7 @@ public void showInvalidClientIndexDeleteMessage() { public void showEmptyClientIndexDeleteMessage() { showToUser(MESSAGE_EMPTY_CLIENT_INDEX); } + public void showIncorrectListDetailsMessage() { showToUser(MESSAGE_INCORRECT_LIST_DETAILS); } diff --git a/src/main/java/seedu/duke/command/CommandListClients.java b/src/main/java/seedu/duke/command/CommandListClients.java index 763a0e49d..eec0f1f78 100644 --- a/src/main/java/seedu/duke/command/CommandListClients.java +++ b/src/main/java/seedu/duke/command/CommandListClients.java @@ -1,14 +1,15 @@ package seedu.duke.command; + import seedu.duke.ClientList; import seedu.duke.PairingList; import seedu.duke.PropertyList; import seedu.duke.Storage; import seedu.duke.Ui; -public class CommandListClients extends Command{ +public class CommandListClients extends Command { public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, PairingList pairingList) { - for(int i = 0; i < clientList.getCurrentListSize(); i++) { + for (int i = 0; i < clientList.getCurrentListSize(); i++) { ui.displayOneClient(clientList.getClientList().get(i)); } } diff --git a/src/main/java/seedu/duke/command/CommandListProperties.java b/src/main/java/seedu/duke/command/CommandListProperties.java index 27bdfd7ae..f586d9393 100644 --- a/src/main/java/seedu/duke/command/CommandListProperties.java +++ b/src/main/java/seedu/duke/command/CommandListProperties.java @@ -1,14 +1,15 @@ package seedu.duke.command; + import seedu.duke.ClientList; import seedu.duke.PairingList; import seedu.duke.PropertyList; import seedu.duke.Storage; import seedu.duke.Ui; -public class CommandListProperties extends Command{ +public class CommandListProperties extends Command { public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, PairingList pairingList) { - for(int i = 0; i < propertyList.getCurrentListSize(); i++) { + for (int i = 0; i < propertyList.getCurrentListSize(); i++) { ui.displayOneProperty(propertyList.getPropertyList().get(i)); } } diff --git a/src/main/java/seedu/duke/exception/IncorrectListDetailsException.java b/src/main/java/seedu/duke/exception/IncorrectListDetailsException.java index 8b08caf4e..d53abcbf5 100644 --- a/src/main/java/seedu/duke/exception/IncorrectListDetailsException.java +++ b/src/main/java/seedu/duke/exception/IncorrectListDetailsException.java @@ -1,7 +1,7 @@ package seedu.duke.exception; /** - * Represents exception when List details are incorrectly entered by the user + * Represents exception when List details are incorrectly entered by the user. */ public class IncorrectListDetailsException extends DukeException { } From f6acbceea008a91e0e2e56f65692c229fccd07ee Mon Sep 17 00:00:00 2001 From: "MSI\\User" Date: Wed, 12 Oct 2022 15:54:50 +0800 Subject: [PATCH 055/325] Implement function to update pairing file when client or property is deleted --- src/main/java/seedu/duke/PairingList.java | 45 ++++++++++++++++++- src/main/java/seedu/duke/PropertyList.java | 1 + src/main/java/seedu/duke/Storage.java | 18 ++++---- .../seedu/duke/command/CommandAddClient.java | 2 +- .../duke/command/CommandDeleteClient.java | 7 +++ .../duke/command/CommandDeleteProperty.java | 12 +++++ 6 files changed, 73 insertions(+), 12 deletions(-) diff --git a/src/main/java/seedu/duke/PairingList.java b/src/main/java/seedu/duke/PairingList.java index b3ab497d1..699a87fbf 100644 --- a/src/main/java/seedu/duke/PairingList.java +++ b/src/main/java/seedu/duke/PairingList.java @@ -8,7 +8,6 @@ */ public class PairingList { private static final String SEPARATOR = " | "; - private static final String CURRENCY = "SGD"; private static final String OPEN_BRACKET = "["; private static final String CLOSE_BRACKET = "]"; @@ -23,6 +22,7 @@ public PairingList() { /** * Records which property a client is renting, with Client and Property objects as parameters. + * * @param client Client renting the property. * @param property Property being rented. */ @@ -35,6 +35,7 @@ public void addPairing(Client client, Property property) { /** * Records which property a client is renting, with the client and property in the appropriate pairing formats as * parameters. This is used to load the pairings from the pairing data file into the class variable. + * * @param clientPairingData Pairing data of client that is renting the property. * @param propertyPairingData Pairing data of property that is being rented. */ @@ -45,6 +46,7 @@ public void addPairing(String clientPairingData, String propertyPairingData) { /** * Deletes client-property pair to indicate that the client is no longer renting that property. + * * @param client Client who is no longer renting the property. * @param property Property that is no longer being rented. */ @@ -56,8 +58,39 @@ public void deletePairing(Client client, Property property) { clientPropertyPairs.remove(clientPairingData, propertyPairingData); } + /** + * Deletes client-property pair to indicate that the client is no longer renting that property, given the property. + * + * @param property Property that has been deleted. + */ + public void deletePairing(Property property) { + String propertyPairingData = convertToPairingData(property); + assert clientPropertyPairs.containsValue(propertyPairingData) : "Property does not exist."; + + // Iterate through the hash map to delete all the entires containing the properties + for (String clientPairingData : clientPropertyPairs.keySet()) { + if (clientPropertyPairs.get(clientPairingData).equals(propertyPairingData)) { + clientPropertyPairs.remove(clientPairingData, propertyPairingData); + } + } + } + + /** + * Deletes client-property pair to indicate that the client is no longer renting that property, given the client. + * + * @param client Client that has been deleted. + */ + public void deletePairing(Client client) { + String clientPairingData = convertToPairingData(client); + + assert clientPropertyPairs.containsKey(clientPairingData) : "Client does not exist."; + + clientPropertyPairs.remove(clientPairingData); + } + /** * Returns true if the client is paired with a property. + * * @param client Client whose pairing status is being checked. * @return True if the client is currently paired with a property. False if not paired with a property. */ @@ -68,6 +101,7 @@ public boolean isClientPairedWithProperty(Client client) { /** * Returns true if the property is already paired with client. + * * @param property Property whose pairing status is being checked. * @return True if the property is currently paired with a client. False if not paired with a client. */ @@ -79,6 +113,7 @@ public boolean isPropertyPairedWithClient(Property property) { /** * Fetches a list of tenants that is renting the property. + * * @param property Property being queried. * @return List of tenants occupying the property, along with their data. */ @@ -97,6 +132,7 @@ public ArrayList getPropertyTenants(Property property) { /** * Converts client pairing data to a suitable string format. + * * @param client Client whose data is to be converted. * @return Client pairing data in a suitable string format. */ @@ -108,13 +144,14 @@ public String convertToPairingData(Client client) { /** * Converts property pairing data to a suitable string format. + * * @param property Property whose data is to be converted. * @return Property pairing data in a suitable string format. */ public String convertToPairingData(Property property) { return OPEN_BRACKET + property.getLandlordName() + SEPARATOR + property.getPropertyAddress() - + SEPARATOR + CURRENCY + property.getRentingPrice() + + SEPARATOR + property.getRentingPrice() + SEPARATOR + property.getUnitType() + CLOSE_BRACKET; } @@ -128,4 +165,8 @@ public HashMap getClientPropertyPairs() { return clientPropertyPairs; } + + + + } diff --git a/src/main/java/seedu/duke/PropertyList.java b/src/main/java/seedu/duke/PropertyList.java index ac0796c0f..a738f9b3b 100644 --- a/src/main/java/seedu/duke/PropertyList.java +++ b/src/main/java/seedu/duke/PropertyList.java @@ -41,6 +41,7 @@ public Property deleteProperty(int propertyIndex) { currentListSize--; return deletedProperty; } + } diff --git a/src/main/java/seedu/duke/Storage.java b/src/main/java/seedu/duke/Storage.java index 920b2dac7..89e1d3091 100644 --- a/src/main/java/seedu/duke/Storage.java +++ b/src/main/java/seedu/duke/Storage.java @@ -16,7 +16,6 @@ public class Storage { private static final String CLIENT_PATH = "./data/client.txt"; private static final String PAIR_PATH = "./data/pair.txt"; private static final String SEPARATOR = " | "; - private static final String CURRENCY = "SGD"; private static final String COLON = " : "; private static final String EMPTY_STRING = ""; private static final String LOG_ADD_CLIENT_LABEL = "Client has been added to text file as: "; @@ -159,7 +158,7 @@ public void loadClient(ClientList clientList, File clientFile) { String clientName = clientParameters[0]; String clientContact = clientParameters[1]; String clientEmail = clientParameters[2]; - String clientBudget = clientParameters[3].replace(CURRENCY, EMPTY_STRING).trim(); + String clientBudget = clientParameters[3].trim(); clientList.addClient(clientName, clientContact, clientEmail, clientBudget); } LOGGER.log(Level.INFO, LOG_CLIENT_LOAD_LABEL); @@ -184,7 +183,7 @@ public void loadProperty(PropertyList propertyList, File propertyFile) { String landlordName = propertyParameters[0]; String address = propertyParameters[1]; String price = propertyParameters[2]; - String unitType = propertyParameters[3].replace(CURRENCY, EMPTY_STRING).trim(); + String unitType = propertyParameters[3].trim(); propertyList.addProperty(landlordName, address, price, unitType); } LOGGER.log(Level.INFO, LOG_PROPERTY_LOAD_LABEL); @@ -228,7 +227,7 @@ public void loadPair(PairingList pairingList, File pairFile) { public void addToPropertyFile(String landlord, String address, String price, String unitType) { try { FileWriter fw = new FileWriter(PROPERTY_PATH, true); - String rentalPrice = CURRENCY + price; + String rentalPrice = price; String newText = landlord + SEPARATOR + address + SEPARATOR + rentalPrice + SEPARATOR + unitType + System.lineSeparator(); @@ -252,10 +251,10 @@ public void addToPropertyFile(String landlord, String address, String price, Str * @param email The email of the client. * @param budget The budget the client is looking at. */ - public void addToClientFile(String name, String contact, String email, int budget) { + public void addToClientFile(String name, String contact, String email, String budget) { try { FileWriter fw = new FileWriter(CLIENT_PATH, true); - String budgetPrice = CURRENCY + budget; + String budgetPrice = budget; String newText = name + SEPARATOR + contact + SEPARATOR + email + SEPARATOR + budgetPrice + System.lineSeparator(); @@ -272,6 +271,7 @@ public void addToClientFile(String name, String contact, String email, int budge + public void addToPairFile(String clientFormat, String propertyFormat) { try { FileWriter fw = new FileWriter(PAIR_PATH, true); @@ -302,7 +302,7 @@ public void updateClient(ClientList clientList) { String clientText = EMPTY_STRING; for (int i = 0; i < clientLists.size(); i += 1) { // Concatenate the string variables into clientText - String budgetPrice = CURRENCY + clientLists.get(i).getClientBudgetPerMonth(); + String budgetPrice = clientLists.get(i).getClientBudgetPerMonth(); String name = clientLists.get(i).getClientName(); String contact = clientLists.get(i).getClientContactNumber(); String email = clientLists.get(i).getClientEmail(); @@ -338,7 +338,7 @@ public void updateProperty(PropertyList propertyList) { String rentingPrice = propertyLists.get(i).getRentingPrice(); String unitType = propertyLists.get(i).getUnitType(); String finalText = landlordName + SEPARATOR + propertyAddress + SEPARATOR - + CURRENCY + rentingPrice + SEPARATOR + unitType + System.lineSeparator(); + + rentingPrice + SEPARATOR + unitType + System.lineSeparator(); propertyText = propertyText.concat(finalText); } @@ -362,7 +362,7 @@ public void updatePair(PairingList pairingList) { HashMap clientPropertyPair = pairingList.getClientPropertyPairs(); FileWriter pairFile = new FileWriter(PAIR_PATH); - String pairText = ""; + String pairText = EMPTY_STRING; for (String clientText : clientPropertyPair.keySet()) { String propertyText = clientPropertyPair.get(clientText); String finalText = clientText + COLON + propertyText + System.lineSeparator(); diff --git a/src/main/java/seedu/duke/command/CommandAddClient.java b/src/main/java/seedu/duke/command/CommandAddClient.java index a5e19a657..288a00017 100644 --- a/src/main/java/seedu/duke/command/CommandAddClient.java +++ b/src/main/java/seedu/duke/command/CommandAddClient.java @@ -38,6 +38,6 @@ public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientLis //Update Storage storage.addToClientFile(this.clientName, this.clientContactNumber, - this.clientEmail, Integer.parseInt(this.clientBudgetPerMonth)); + this.clientEmail, this.clientBudgetPerMonth); } } diff --git a/src/main/java/seedu/duke/command/CommandDeleteClient.java b/src/main/java/seedu/duke/command/CommandDeleteClient.java index ccf8aab30..b03ab7ebb 100644 --- a/src/main/java/seedu/duke/command/CommandDeleteClient.java +++ b/src/main/java/seedu/duke/command/CommandDeleteClient.java @@ -23,7 +23,14 @@ public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, PairingList pairingList) { Client deletedClient = clientList.deleteClient(clientIndex); ui.showClientDeletedConfirmationMessage(deletedClient); + pairingList.deletePairing(deletedClient); + //Update Storage storage.updateClient(clientList); + + for (String i : pairingList.getClientPropertyPairs().keySet()) { + System.out.println("Key: " + i + "Value: " + pairingList.getClientPropertyPairs().get(i)); + } + storage.updatePair(pairingList); } } diff --git a/src/main/java/seedu/duke/command/CommandDeleteProperty.java b/src/main/java/seedu/duke/command/CommandDeleteProperty.java index 23bf63920..54ca951b5 100644 --- a/src/main/java/seedu/duke/command/CommandDeleteProperty.java +++ b/src/main/java/seedu/duke/command/CommandDeleteProperty.java @@ -21,9 +21,21 @@ public CommandDeleteProperty(int propertyIndex) { @Override public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, PairingList pairingList) { + Property deletedProperty = propertyList.deleteProperty(propertyIndex); + ui.showPropertyDeletedConfirmationMessage(deletedProperty); + + pairingList.deletePairing(deletedProperty); //Update Storage storage.updateProperty(propertyList); + + + for (String i : pairingList.getClientPropertyPairs().keySet()) { + System.out.println("Key: " + i + "Value: " + pairingList.getClientPropertyPairs().get(i)); + } + + storage.updatePair(pairingList); + } } From c31bb5b6d931ce0ac3b35c8ee8fbb454468627bc Mon Sep 17 00:00:00 2001 From: "MSI\\User" Date: Wed, 12 Oct 2022 16:02:32 +0800 Subject: [PATCH 056/325] Fix CI Failure issue --- src/main/java/seedu/duke/Duke.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index ea7f51242..a8c111d71 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -66,7 +66,7 @@ public void run() throws IOException { do { try { - //System.exit(0); //to pass CI + System.exit(0); //to pass CI String userInputText = ui.readCommand(); command = parser.parseCommand(userInputText); command.execute(ui, storage, propertyList, clientList, pairingList); From ab56c636752fb34bfc300849115a731ccec825a2 Mon Sep 17 00:00:00 2001 From: Wilson Ng Jing An <31720838+wilsonngja@users.noreply.github.com> Date: Wed, 12 Oct 2022 16:07:11 +0800 Subject: [PATCH 057/325] Revert "List 2" --- src/main/java/seedu/duke/Duke.java | 3 --- src/main/java/seedu/duke/Messages.java | 2 -- src/main/java/seedu/duke/Parser.java | 27 +++---------------- src/main/java/seedu/duke/Ui.java | 21 +++------------ .../duke/command/CommandListClients.java | 16 ----------- .../duke/command/CommandListProperties.java | 16 ----------- .../IncorrectListDetailsException.java | 7 ----- 7 files changed, 7 insertions(+), 85 deletions(-) delete mode 100644 src/main/java/seedu/duke/command/CommandListClients.java delete mode 100644 src/main/java/seedu/duke/command/CommandListProperties.java delete mode 100644 src/main/java/seedu/duke/exception/IncorrectListDetailsException.java diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index bc2fa049b..ea7f51242 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -39,7 +39,6 @@ import seedu.duke.exception.UndefinedSubCommandAddTypeException; import seedu.duke.exception.UndefinedSubCommandCheckTypeException; import seedu.duke.exception.UndefinedSubCommandDeleteTypeException; -import seedu.duke.exception.IncorrectListDetailsException; import java.io.IOException; @@ -130,8 +129,6 @@ public void run() throws IOException { ui.showPropertyAlreadyPairedMessage(); } catch (NoExistingPairException e) { ui.showNoExistingPairMessage(); - } catch (IncorrectListDetailsException e) { - ui.showIncorrectListDetailsMessage(); } catch (MissingCheckPropertyFlagException e) { ui.showCheckPropertyWrongFormatMessage(); } catch (UndefinedSubCommandCheckTypeException e) { diff --git a/src/main/java/seedu/duke/Messages.java b/src/main/java/seedu/duke/Messages.java index 5af1ece6c..6d9f5d7ef 100644 --- a/src/main/java/seedu/duke/Messages.java +++ b/src/main/java/seedu/duke/Messages.java @@ -127,8 +127,6 @@ public class Messages { + "Examples:\n" + " pair ip/1 ic/5\n" + " unpair ip/2 ic/1"; - public static final String MESSAGE_INCORRECT_LIST_DETAILS = "OOPS!!! Please enter either -client or -property" - + "to list clients and properties respectively"; public static final String MESSAGE_PROPERTY_ALREADY_PAIRED = "OOPS!! This property is currently rented by a tenant," + " try pairing with another property"; diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index c769c3b5d..8329b086c 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -9,8 +9,6 @@ import seedu.duke.command.CommandPair; import seedu.duke.command.CommandUnpair; import seedu.duke.command.CommandUndefined; -import seedu.duke.command.CommandListClients; -import seedu.duke.command.CommandListProperties; import seedu.duke.exception.ClientAlreadyPairedException; import seedu.duke.exception.EmptyClientDetailException; @@ -51,7 +49,6 @@ import seedu.duke.exception.UndefinedSubCommandAddTypeException; import seedu.duke.exception.UndefinedSubCommandCheckTypeException; import seedu.duke.exception.UndefinedSubCommandDeleteTypeException; -import seedu.duke.exception.IncorrectListDetailsException; import java.util.ArrayList; import java.util.regex.Matcher; @@ -80,18 +77,13 @@ public Command parseCommand(String input) throws EmptyCommandAddDetailException, InvalidPriceFormatException, EmptyClientDetailException, MissingClientFlagException, IncorrectAddClientFlagOrderException, MissingClientDetailException, InvalidContactNumberException, InvalidEmailException, InvalidBudgetFormatException, UndefinedSubCommandDeleteTypeException, - EmptyCommandDeleteDetailException, InvalidClientIndexDeleteException, EmptyClientIndexDeleteException, - EmptyCommandPairUnpairDetailsException, MissingPairUnpairFlagException, - IncorrectPairUnpairFlagOrderException, NotValidIndexException, NotIntegerException, ExistingPairException, - NoExistingPairException, { EmptyCommandDeleteDetailException, InvalidPropertyIndexFlagFormatException, MissingPropertyIndexFlagException, EmptyPropertyIndexDeleteException, InvalidPropertyIndexDeleteException, InvalidClientIndexDeleteException, EmptyClientIndexDeleteException, MissingClientIndexFlagException, InvalidClientIndexFlagFormatException, EmptyCommandPairUnpairDetailsException, MissingPairUnpairFlagException, IncorrectPairUnpairFlagOrderException, NotValidIndexException, NotIntegerException, NoExistingPairException, ClientAlreadyPairedException, PropertyAlreadyPairedException, - UndefinedSubCommandCheckTypeException, EmptyCommandCheckDetailException, MissingCheckPropertyFlagException, - IncorrectListDetailsException { + UndefinedSubCommandCheckTypeException, EmptyCommandCheckDetailException, MissingCheckPropertyFlagException { ArrayList processedCommandDetails = partitionCommandTypeAndDetails(input); String commandType = processedCommandDetails.get(0); String commandDetails = processedCommandDetails.get(1); @@ -133,9 +125,7 @@ public Command parseCommand(String input) throws EmptyCommandAddDetailException, case "unpair": checkForEmptyCommandPairUnpairDetails(commandDetails); return prepareForCommandUnpair(commandDetails); - case "list": - checkForEmptyCommandAddDetails(commandDetails); - return prepareForCommandList(commandDetails); + case "check": checkForEmptyCommandCheckDetails(commandDetails); ArrayList processedCheckCommandDetails = partitionCommandTypeAndDetails(commandDetails); @@ -152,7 +142,6 @@ public Command parseCommand(String input) throws EmptyCommandAddDetailException, } } - private ArrayList partitionCommandTypeAndDetails(String fullCommandDetails) { String[] inputDetails = fullCommandDetails.trim().split(" ", 2); // This is the type of command/sub-command that will be executed @@ -189,16 +178,6 @@ private Command prepareForCommandAddProperty(String rawPropertyDescriptions) thr } } - private Command prepareForCommandList(String commandDetails) throws IncorrectListDetailsException { - if (commandDetails.trim().equals("-client")) { - return new CommandListClients(); - } else if (commandDetails.trim().equals("-property")) { - return new CommandListProperties(); - } else { - throw new IncorrectListDetailsException(); - } - } - private Command prepareForCommandAddClient(String rawClientDescriptions) throws EmptyClientDetailException, MissingClientFlagException, IncorrectAddClientFlagOrderException, MissingClientDetailException, InvalidContactNumberException, InvalidEmailException, InvalidBudgetFormatException { @@ -634,7 +613,7 @@ private void checkForPairUnpairFlagsOrder(int[] pairUnpairFlagIndexPosition) } private ArrayList extractPairUnpairDetails(String rawPairUnpairDetails, int[] pairFlagIndexPositions, - String[] pairUnpairFlags) throws NotIntegerException { + String[] pairUnpairFlags) throws NotIntegerException { String propertyIndexString = extractDetail(rawPairUnpairDetails, pairFlagIndexPositions[0] + pairUnpairFlags[0].length(), pairFlagIndexPositions[1]); diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index edc8f8bca..05049db0f 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -53,8 +53,6 @@ import static seedu.duke.Messages.MESSAGE_PAIR_UNPAIR_INPUT_EXAMPLE; import static seedu.duke.Messages.MESSAGE_TRY_AGAIN; -import static seedu.duke.Messages.MESSAGE_INCORRECT_LIST_DETAILS; - /** * Handler for all interactions between the user and the command line. */ @@ -198,11 +196,7 @@ public void showInvalidClientIndexDeleteMessage() { public void showEmptyClientIndexDeleteMessage() { showToUser(MESSAGE_EMPTY_CLIENT_INDEX); } - - public void showIncorrectListDetailsMessage() { - showToUser(MESSAGE_INCORRECT_LIST_DETAILS); - } - + public void showMissingClientIndexFlagMessage() { showToUser(MESSAGE_MISSING_CLIENT_INDEX_FLAG); } @@ -210,7 +204,8 @@ public void showMissingClientIndexFlagMessage() { public void showInvalidClientIndexFlagFormatMessage() { showToUser(MESSAGE_INVALID_CLIENT_INDEX_FLAG_FORMAT); } - + + /* Pair/Unpair-Command-related showMessage methods. */ public void showPairedConfirmationMessage(Client client, Property property) { @@ -241,14 +236,6 @@ public void showPairUnpairWrongFormatMessage() { showToUser(MESSAGE_TRY_AGAIN); } - public void displayOneClient(Client client) { - //client display interface - } - - public void displayOneProperty(Property property) { - //property display interface - } - public void showClientAlreadyPairedMessage() { showToUser(MESSAGE_CLIENT_ALREADY_PAIRED); } @@ -261,6 +248,7 @@ public void showNoExistingPairMessage() { showToUser(MESSAGE_NO_EXISTING_PAIR); } + /* Check-Command-related showMessage methods. */ public void showCheckPropertyWrongFormatMessage() { @@ -286,4 +274,3 @@ public void showCheckProperty(ArrayList tenants) { showToUser(MESSAGE_NUMBER_OF_LIST_RESULTS + count); } } - diff --git a/src/main/java/seedu/duke/command/CommandListClients.java b/src/main/java/seedu/duke/command/CommandListClients.java deleted file mode 100644 index eec0f1f78..000000000 --- a/src/main/java/seedu/duke/command/CommandListClients.java +++ /dev/null @@ -1,16 +0,0 @@ -package seedu.duke.command; - -import seedu.duke.ClientList; -import seedu.duke.PairingList; -import seedu.duke.PropertyList; -import seedu.duke.Storage; -import seedu.duke.Ui; - -public class CommandListClients extends Command { - public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, - PairingList pairingList) { - for (int i = 0; i < clientList.getCurrentListSize(); i++) { - ui.displayOneClient(clientList.getClientList().get(i)); - } - } -} diff --git a/src/main/java/seedu/duke/command/CommandListProperties.java b/src/main/java/seedu/duke/command/CommandListProperties.java deleted file mode 100644 index f586d9393..000000000 --- a/src/main/java/seedu/duke/command/CommandListProperties.java +++ /dev/null @@ -1,16 +0,0 @@ -package seedu.duke.command; - -import seedu.duke.ClientList; -import seedu.duke.PairingList; -import seedu.duke.PropertyList; -import seedu.duke.Storage; -import seedu.duke.Ui; - -public class CommandListProperties extends Command { - public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, - PairingList pairingList) { - for (int i = 0; i < propertyList.getCurrentListSize(); i++) { - ui.displayOneProperty(propertyList.getPropertyList().get(i)); - } - } -} diff --git a/src/main/java/seedu/duke/exception/IncorrectListDetailsException.java b/src/main/java/seedu/duke/exception/IncorrectListDetailsException.java deleted file mode 100644 index d53abcbf5..000000000 --- a/src/main/java/seedu/duke/exception/IncorrectListDetailsException.java +++ /dev/null @@ -1,7 +0,0 @@ -package seedu.duke.exception; - -/** - * Represents exception when List details are incorrectly entered by the user. - */ -public class IncorrectListDetailsException extends DukeException { -} From 649746bac694fc092edcf0b62d614472a588975d Mon Sep 17 00:00:00 2001 From: "ZORAN\\syedo" Date: Wed, 12 Oct 2022 18:24:30 +0800 Subject: [PATCH 058/325] Add list and bye --- src/main/java/seedu/duke/Duke.java | 11 ++++- src/main/java/seedu/duke/Messages.java | 11 +++++ src/main/java/seedu/duke/Parser.java | 44 +++++++++++++++++-- src/main/java/seedu/duke/Ui.java | 31 +++++++++++-- .../duke/command/CommandListClients.java | 17 +++++++ .../duke/command/CommandListProperties.java | 16 +++++++ .../ByeParametersPresentException.java | 4 ++ .../IncorrectListDetailsException.java | 7 +++ .../exception/MissingListDetailException.java | 7 +++ 9 files changed, 141 insertions(+), 7 deletions(-) create mode 100644 src/main/java/seedu/duke/command/CommandListClients.java create mode 100644 src/main/java/seedu/duke/command/CommandListProperties.java create mode 100644 src/main/java/seedu/duke/exception/ByeParametersPresentException.java create mode 100644 src/main/java/seedu/duke/exception/IncorrectListDetailsException.java create mode 100644 src/main/java/seedu/duke/exception/MissingListDetailException.java diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index a8c111d71..c212d7541 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -39,6 +39,9 @@ import seedu.duke.exception.UndefinedSubCommandAddTypeException; import seedu.duke.exception.UndefinedSubCommandCheckTypeException; import seedu.duke.exception.UndefinedSubCommandDeleteTypeException; +import seedu.duke.exception.ByeParametersPresentException; +import seedu.duke.exception.IncorrectListDetailsException; +import seedu.duke.exception.MissingListDetailException; import java.io.IOException; @@ -66,7 +69,7 @@ public void run() throws IOException { do { try { - System.exit(0); //to pass CI + // System.exit(0); //to pass CI String userInputText = ui.readCommand(); command = parser.parseCommand(userInputText); command.execute(ui, storage, propertyList, clientList, pairingList); @@ -135,6 +138,12 @@ public void run() throws IOException { ui.showUndefinedSubCommandCheckTypeMessage(); } catch (EmptyCommandCheckDetailException e) { ui.showEmptyCommandCheckDetailException(); + } catch (IncorrectListDetailsException e) { + ui.showIncorrectListDetailsMessage(); + } catch (MissingListDetailException e) { + ui.showMissingListDetailsMessage(); + } catch (ByeParametersPresentException e) { + ui.showByeParametersPresentMessage(); } } while (!isCommandBye); } diff --git a/src/main/java/seedu/duke/Messages.java b/src/main/java/seedu/duke/Messages.java index 6d9f5d7ef..8c2e06464 100644 --- a/src/main/java/seedu/duke/Messages.java +++ b/src/main/java/seedu/duke/Messages.java @@ -151,4 +151,15 @@ public class Messages { public static final String MESSAGE_EMPTY_CHECK_DESCRIPTION = "OOPS!!! The description for check cannot be empty."; public static final String MESSAGE_TRY_AGAIN = "Please try again."; + + public static final String MESSAGE_INCORRECT_LIST_DETAILS = "OOPS!!! Please enter either -client or -property to" + + " list clients and properties respectively"; + + public static final String MESSAGE_MISSING_LIST_DETAILS = "OOPS!!!" + + " The description for list cannot be empty"; + public static final String LINE_BREAK = "----------------------------------------------------------------------" + + "----------"; + + public static final String MESSAGE_BYE_PARAMETERS_PRESENT = "Please type bye without any parameters" + + " if you would like to quit"; } diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 8329b086c..19cee6815 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -9,6 +9,9 @@ import seedu.duke.command.CommandPair; import seedu.duke.command.CommandUnpair; import seedu.duke.command.CommandUndefined; +import seedu.duke.command.CommandListClients; +import seedu.duke.command.CommandListProperties; +import seedu.duke.command.CommandBye; import seedu.duke.exception.ClientAlreadyPairedException; import seedu.duke.exception.EmptyClientDetailException; @@ -49,6 +52,9 @@ import seedu.duke.exception.UndefinedSubCommandAddTypeException; import seedu.duke.exception.UndefinedSubCommandCheckTypeException; import seedu.duke.exception.UndefinedSubCommandDeleteTypeException; +import seedu.duke.exception.IncorrectListDetailsException; +import seedu.duke.exception.MissingListDetailException; +import seedu.duke.exception.ByeParametersPresentException; import java.util.ArrayList; import java.util.regex.Matcher; @@ -83,7 +89,8 @@ public Command parseCommand(String input) throws EmptyCommandAddDetailException, InvalidClientIndexFlagFormatException, EmptyCommandPairUnpairDetailsException, MissingPairUnpairFlagException, IncorrectPairUnpairFlagOrderException, NotValidIndexException, NotIntegerException, NoExistingPairException, ClientAlreadyPairedException, PropertyAlreadyPairedException, - UndefinedSubCommandCheckTypeException, EmptyCommandCheckDetailException, MissingCheckPropertyFlagException { + UndefinedSubCommandCheckTypeException, EmptyCommandCheckDetailException, MissingCheckPropertyFlagException, + IncorrectListDetailsException, MissingListDetailException, ByeParametersPresentException { ArrayList processedCommandDetails = partitionCommandTypeAndDetails(input); String commandType = processedCommandDetails.get(0); String commandDetails = processedCommandDetails.get(1); @@ -137,6 +144,14 @@ public Command parseCommand(String input) throws EmptyCommandAddDetailException, } else { throw new UndefinedSubCommandCheckTypeException(); } + + case "list": + checkForEmptyListParameters(commandDetails); + return prepareForCommandList(commandDetails); + + case "bye": + checkForByeParameters(commandDetails); + return new CommandBye(); default: return new CommandUndefined(); } @@ -153,6 +168,13 @@ private ArrayList partitionCommandTypeAndDetails(String fullCommandDetai return processedCommandDetails; } + void checkForEmptyListParameters(String commandListDetails) throws MissingListDetailException { + boolean isEmptyListDetail = checkForEmptyDetail(commandListDetails); + if (isEmptyListDetail) { + throw new MissingListDetailException(); + } + } + /* Add Property/Client Parse Section */ @@ -493,6 +515,16 @@ private int getClientIndexToDelete(String commandDetails) throws EmptyClientInde return Integer.parseInt(commandDetails.trim()) - 1; } + private Command prepareForCommandList(String commandDetails) throws IncorrectListDetailsException { + if (commandDetails.trim().equals("-client")) { + return new CommandListClients(); + } else if (commandDetails.trim().equals("-property")) { + return new CommandListProperties(); + } else { + throw new IncorrectListDetailsException(); + } + } + private void checkForClientIndexFlag(String commandDetails) throws MissingClientIndexFlagException, InvalidClientIndexFlagFormatException { if (!commandDetails.contains("ic/")) { @@ -613,7 +645,7 @@ private void checkForPairUnpairFlagsOrder(int[] pairUnpairFlagIndexPosition) } private ArrayList extractPairUnpairDetails(String rawPairUnpairDetails, int[] pairFlagIndexPositions, - String[] pairUnpairFlags) throws NotIntegerException { + String[] pairUnpairFlags) throws NotIntegerException { String propertyIndexString = extractDetail(rawPairUnpairDetails, pairFlagIndexPositions[0] + pairUnpairFlags[0].length(), pairFlagIndexPositions[1]); @@ -726,7 +758,7 @@ private void checkForEssentialCheckPropertyFlag(int checkPropertyFlagIndexPositi } private ArrayList extractCheckPropertyDetails(String rawPropertyDetails, - int[] checkPropertyFlagIndexPositions, String[] checkFlags) throws NotIntegerException { + int[] checkPropertyFlagIndexPositions, String[] checkFlags) throws NotIntegerException { String propertyIndexString = extractDetail(rawPropertyDetails, checkPropertyFlagIndexPositions[0] + checkFlags[0].length()); @@ -746,4 +778,10 @@ private void validateCheckPropertyDetails(ArrayList checkPropertyDetail checkForPropertyListIndexOutOfBounds(propertyIndex); } + private void checkForByeParameters(String commandDetails) throws ByeParametersPresentException { + if (!commandDetails.trim().isEmpty()) { + throw new ByeParametersPresentException(); + } + } + } diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index 05049db0f..0053b2e0f 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -21,8 +21,6 @@ import static seedu.duke.Messages.MESSAGE_EMPTY_ADD_DESCRIPTION; import static seedu.duke.Messages.MESSAGE_EMPTY_CHECK_DESCRIPTION; import static seedu.duke.Messages.MESSAGE_PROPERTY_ALREADY_PAIRED; -import static seedu.duke.Messages.MESSAGE_WELCOME; -import static seedu.duke.Messages.MESSAGE_PROPERTY_ADDED; import static seedu.duke.Messages.MESSAGE_PAIRED; import static seedu.duke.Messages.MESSAGE_UNPAIRED; import static seedu.duke.Messages.MESSAGE_NO_EXISTING_PAIR; @@ -51,7 +49,10 @@ import static seedu.duke.Messages.MESSAGE_NOT_VALID_INDEX; import static seedu.duke.Messages.MESSAGE_PAIR_UNPAIR_WRONG_FORMAT; import static seedu.duke.Messages.MESSAGE_PAIR_UNPAIR_INPUT_EXAMPLE; -import static seedu.duke.Messages.MESSAGE_TRY_AGAIN; +import static seedu.duke.Messages.MESSAGE_INCORRECT_LIST_DETAILS; +import static seedu.duke.Messages.MESSAGE_MISSING_LIST_DETAILS; +import static seedu.duke.Messages.LINE_BREAK; +import static seedu.duke.Messages.MESSAGE_BYE_PARAMETERS_PRESENT; /** * Handler for all interactions between the user and the command line. @@ -263,6 +264,30 @@ public void showEmptyCommandCheckDetailException() { showToUser(MESSAGE_EMPTY_CHECK_DESCRIPTION); } + public void displayOneClient(Client client, int i) { + System.out.println(i + "."); + System.out.println(client.toString()); + System.out.println(LINE_BREAK); + } + + public void displayOneProperty(Property property, int i) { + System.out.println(i + "."); + System.out.println(property.toString()); + System.out.println(LINE_BREAK); + } + + public void showByeParametersPresentMessage() { + showToUser(MESSAGE_BYE_PARAMETERS_PRESENT); + } + + public void showIncorrectListDetailsMessage() { + showToUser(MESSAGE_INCORRECT_LIST_DETAILS); + } + + public void showMissingListDetailsMessage() { + showToUser(MESSAGE_MISSING_LIST_DETAILS); + } + public void showCheckProperty(ArrayList tenants) { showToUser(MESSAGE_CHECK_PROPERTY_RESULT); int count = 0; diff --git a/src/main/java/seedu/duke/command/CommandListClients.java b/src/main/java/seedu/duke/command/CommandListClients.java new file mode 100644 index 000000000..086afaf4b --- /dev/null +++ b/src/main/java/seedu/duke/command/CommandListClients.java @@ -0,0 +1,17 @@ +package seedu.duke.command; + +import seedu.duke.ClientList; +import seedu.duke.PairingList; +import seedu.duke.PropertyList; +import seedu.duke.Storage; +import seedu.duke.Ui; + +public class CommandListClients extends Command { + public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, + PairingList pairingList) { + for (int i = 0; i < clientList.getCurrentListSize(); i++) { + ui.displayOneClient(clientList.getClientList().get(i), i + 1); + } + } +} + diff --git a/src/main/java/seedu/duke/command/CommandListProperties.java b/src/main/java/seedu/duke/command/CommandListProperties.java new file mode 100644 index 000000000..557adaf9a --- /dev/null +++ b/src/main/java/seedu/duke/command/CommandListProperties.java @@ -0,0 +1,16 @@ +package seedu.duke.command; + +import seedu.duke.ClientList; +import seedu.duke.PairingList; +import seedu.duke.PropertyList; +import seedu.duke.Storage; +import seedu.duke.Ui; + +public class CommandListProperties extends Command { + public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, + PairingList pairingList) { + for (int i = 0; i < propertyList.getCurrentListSize(); i++) { + ui.displayOneProperty(propertyList.getPropertyList().get(i), i + 1); + } + } +} \ No newline at end of file diff --git a/src/main/java/seedu/duke/exception/ByeParametersPresentException.java b/src/main/java/seedu/duke/exception/ByeParametersPresentException.java new file mode 100644 index 000000000..0ab4c2ac4 --- /dev/null +++ b/src/main/java/seedu/duke/exception/ByeParametersPresentException.java @@ -0,0 +1,4 @@ +package seedu.duke.exception; + +public class ByeParametersPresentException extends DukeException{ +} diff --git a/src/main/java/seedu/duke/exception/IncorrectListDetailsException.java b/src/main/java/seedu/duke/exception/IncorrectListDetailsException.java new file mode 100644 index 000000000..31905ae92 --- /dev/null +++ b/src/main/java/seedu/duke/exception/IncorrectListDetailsException.java @@ -0,0 +1,7 @@ +package seedu.duke.exception; + +/** + * Represents exception when List details are incorrectly entered by the user + */ +public class IncorrectListDetailsException extends DukeException { +} \ No newline at end of file diff --git a/src/main/java/seedu/duke/exception/MissingListDetailException.java b/src/main/java/seedu/duke/exception/MissingListDetailException.java new file mode 100644 index 000000000..646889be1 --- /dev/null +++ b/src/main/java/seedu/duke/exception/MissingListDetailException.java @@ -0,0 +1,7 @@ +package seedu.duke.exception; + +/** + * Represents an exception when list details entered by the user are missing + */ +public class MissingListDetailException extends DukeException{ +} From 3d70bd019563a217d906ac4489e7e5c3449b7691 Mon Sep 17 00:00:00 2001 From: "LAPTOP-S1RS66RO\\marcu" Date: Wed, 12 Oct 2022 19:47:48 +0800 Subject: [PATCH 059/325] Added simple logging for CommandAddProperty and CommandAddClient --- src/main/java/seedu/duke/command/CommandAddClient.java | 5 +++++ src/main/java/seedu/duke/command/CommandAddProperty.java | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/main/java/seedu/duke/command/CommandAddClient.java b/src/main/java/seedu/duke/command/CommandAddClient.java index 288a00017..e190b39d5 100644 --- a/src/main/java/seedu/duke/command/CommandAddClient.java +++ b/src/main/java/seedu/duke/command/CommandAddClient.java @@ -8,6 +8,8 @@ import seedu.duke.Ui; import java.util.ArrayList; +import java.util.logging.Level; +import java.util.logging.Logger; /** * Adds a client to the client list. @@ -18,6 +20,8 @@ public class CommandAddClient extends CommandAdd { private final String clientEmail; private final String clientBudgetPerMonth; + private static final Logger logger = Logger.getLogger("CommandAddClient"); + /** * Constructs constructor for Command Add Client which stores client's name, contact number, email and budget/month. * @@ -33,6 +37,7 @@ public CommandAddClient(ArrayList clientDetails) { @Override public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, PairingList pairingList) { + logger.log(Level.INFO, "Adding new client now"); clientList.addClient(clientName, clientContactNumber, clientEmail, clientBudgetPerMonth); ui.showClientAddedConfirmationMessage(clientList); diff --git a/src/main/java/seedu/duke/command/CommandAddProperty.java b/src/main/java/seedu/duke/command/CommandAddProperty.java index 587cb7dbc..482a5ce3d 100644 --- a/src/main/java/seedu/duke/command/CommandAddProperty.java +++ b/src/main/java/seedu/duke/command/CommandAddProperty.java @@ -5,6 +5,8 @@ import seedu.duke.PropertyList; import seedu.duke.Storage; import seedu.duke.Ui; +import java.util.logging.Level; +import java.util.logging.Logger; import java.util.ArrayList; @@ -17,6 +19,8 @@ public class CommandAddProperty extends CommandAdd { private final String rentingPrice; private final String unitType; + private static final Logger logger = Logger.getLogger("CommandAddProperty"); + /** * Constructs constructor for Command Add Property which stores property's Landlord's Name, Address, RentPrice/month * and Unit Type. @@ -33,6 +37,7 @@ public CommandAddProperty(ArrayList propertyDetails) { @Override public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, PairingList pairingList) { + logger.log(Level.INFO, "Adding new property now"); propertyList.addProperty(landlordName, propertyAddress, rentingPrice, unitType); ui.showPropertyAddedConfirmationMessage(propertyList); From 85e92d86c77932446b7b8d9432cacd75ba99df0c Mon Sep 17 00:00:00 2001 From: "LAPTOP-S1RS66RO\\marcu" Date: Wed, 12 Oct 2022 20:20:20 +0800 Subject: [PATCH 060/325] Add simple assertions for CommandAddProperty and CommandAddClient --- src/main/java/seedu/duke/command/CommandAddClient.java | 4 ++++ src/main/java/seedu/duke/command/CommandAddProperty.java | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/main/java/seedu/duke/command/CommandAddClient.java b/src/main/java/seedu/duke/command/CommandAddClient.java index 288a00017..42dcd0a1b 100644 --- a/src/main/java/seedu/duke/command/CommandAddClient.java +++ b/src/main/java/seedu/duke/command/CommandAddClient.java @@ -24,6 +24,10 @@ public class CommandAddClient extends CommandAdd { * @param clientDetails Contains client's name, contact number, email and budget/month. */ public CommandAddClient(ArrayList clientDetails) { + for (String clientDetail : clientDetails) { + assert clientDetail != null; + } + this.clientName = clientDetails.get(0); this.clientContactNumber = clientDetails.get(1); this.clientEmail = clientDetails.get(2); diff --git a/src/main/java/seedu/duke/command/CommandAddProperty.java b/src/main/java/seedu/duke/command/CommandAddProperty.java index 587cb7dbc..7b7e04ab8 100644 --- a/src/main/java/seedu/duke/command/CommandAddProperty.java +++ b/src/main/java/seedu/duke/command/CommandAddProperty.java @@ -24,6 +24,10 @@ public class CommandAddProperty extends CommandAdd { * @param propertyDetails Contains information relevant to property */ public CommandAddProperty(ArrayList propertyDetails) { + for (String propertyDetail : propertyDetails) { + assert propertyDetail != null; + } + this.landlordName = propertyDetails.get(0); this.propertyAddress = propertyDetails.get(1); this.rentingPrice = propertyDetails.get(2); From 918842fa4972dd755b517b57f2c18538d0839724 Mon Sep 17 00:00:00 2001 From: "ZORAN\\syedo" Date: Wed, 12 Oct 2022 21:23:47 +0800 Subject: [PATCH 061/325] Add list and bye features --- src/main/java/seedu/duke/Parser.java | 4 ++-- .../seedu/duke/exception/IncorrectListDetailsException.java | 2 +- .../java/seedu/duke/exception/MissingListDetailException.java | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 19cee6815..0ba93bdc8 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -645,7 +645,7 @@ private void checkForPairUnpairFlagsOrder(int[] pairUnpairFlagIndexPosition) } private ArrayList extractPairUnpairDetails(String rawPairUnpairDetails, int[] pairFlagIndexPositions, - String[] pairUnpairFlags) throws NotIntegerException { + String[] pairUnpairFlags) throws NotIntegerException { String propertyIndexString = extractDetail(rawPairUnpairDetails, pairFlagIndexPositions[0] + pairUnpairFlags[0].length(), pairFlagIndexPositions[1]); @@ -758,7 +758,7 @@ private void checkForEssentialCheckPropertyFlag(int checkPropertyFlagIndexPositi } private ArrayList extractCheckPropertyDetails(String rawPropertyDetails, - int[] checkPropertyFlagIndexPositions, String[] checkFlags) throws NotIntegerException { + int[] checkPropertyFlagIndexPositions, String[] checkFlags) throws NotIntegerException { String propertyIndexString = extractDetail(rawPropertyDetails, checkPropertyFlagIndexPositions[0] + checkFlags[0].length()); diff --git a/src/main/java/seedu/duke/exception/IncorrectListDetailsException.java b/src/main/java/seedu/duke/exception/IncorrectListDetailsException.java index 31905ae92..7289c022b 100644 --- a/src/main/java/seedu/duke/exception/IncorrectListDetailsException.java +++ b/src/main/java/seedu/duke/exception/IncorrectListDetailsException.java @@ -1,7 +1,7 @@ package seedu.duke.exception; /** - * Represents exception when List details are incorrectly entered by the user + * Represents exception when List details are incorrectly entered by the user. */ public class IncorrectListDetailsException extends DukeException { } \ No newline at end of file diff --git a/src/main/java/seedu/duke/exception/MissingListDetailException.java b/src/main/java/seedu/duke/exception/MissingListDetailException.java index 646889be1..771fdd772 100644 --- a/src/main/java/seedu/duke/exception/MissingListDetailException.java +++ b/src/main/java/seedu/duke/exception/MissingListDetailException.java @@ -1,7 +1,7 @@ package seedu.duke.exception; /** - * Represents an exception when list details entered by the user are missing + * Represents an exception when list details entered by the user are missing. */ -public class MissingListDetailException extends DukeException{ +public class MissingListDetailException extends DukeException { } From bb19a693a9ecb3bc061ac82ea8c6924dba8a2a0b Mon Sep 17 00:00:00 2001 From: ngdeqi Date: Thu, 13 Oct 2022 09:59:33 +0800 Subject: [PATCH 062/325] Handle case where user pairs a property and client that are already paired --- src/main/java/seedu/duke/Duke.java | 10 ++--- src/main/java/seedu/duke/Messages.java | 8 ++-- src/main/java/seedu/duke/PairingList.java | 24 ++++++----- src/main/java/seedu/duke/Parser.java | 43 +++++++++---------- src/main/java/seedu/duke/Ui.java | 6 +-- .../exception/AlreadyPairedException.java | 4 ++ .../duke/exception/InvalidIndexException.java | 4 ++ .../exception/NotValidIndexException.java | 4 -- .../PropertyAlreadyPairedException.java | 5 --- 9 files changed, 54 insertions(+), 54 deletions(-) create mode 100644 src/main/java/seedu/duke/exception/AlreadyPairedException.java create mode 100644 src/main/java/seedu/duke/exception/InvalidIndexException.java delete mode 100644 src/main/java/seedu/duke/exception/NotValidIndexException.java delete mode 100644 src/main/java/seedu/duke/exception/PropertyAlreadyPairedException.java diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index c212d7541..6ccfbd5e9 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -3,6 +3,7 @@ import seedu.duke.command.Command; import seedu.duke.command.CommandBye; +import seedu.duke.exception.AlreadyPairedException; import seedu.duke.exception.ClientAlreadyPairedException; import seedu.duke.exception.EmptyClientDetailException; import seedu.duke.exception.EmptyClientIndexDeleteException; @@ -34,8 +35,7 @@ import seedu.duke.exception.MissingPropertyIndexFlagException; import seedu.duke.exception.NoExistingPairException; import seedu.duke.exception.NotIntegerException; -import seedu.duke.exception.NotValidIndexException; -import seedu.duke.exception.PropertyAlreadyPairedException; +import seedu.duke.exception.InvalidIndexException; import seedu.duke.exception.UndefinedSubCommandAddTypeException; import seedu.duke.exception.UndefinedSubCommandCheckTypeException; import seedu.duke.exception.UndefinedSubCommandDeleteTypeException; @@ -122,16 +122,16 @@ public void run() throws IOException { ui.showEmptyCommandPairUnpairDetailsMessage(); } catch (MissingPairUnpairFlagException | IncorrectPairUnpairFlagOrderException e) { ui.showPairUnpairWrongFormatMessage(); - } catch (NotValidIndexException e) { + } catch (InvalidIndexException e) { ui.showNotValidIndexMessage(); } catch (NotIntegerException e) { ui.showNotIntegerMessage(); } catch (ClientAlreadyPairedException e) { ui.showClientAlreadyPairedMessage(); - } catch (PropertyAlreadyPairedException e) { - ui.showPropertyAlreadyPairedMessage(); } catch (NoExistingPairException e) { ui.showNoExistingPairMessage(); + } catch (AlreadyPairedException e) { + ui.showAlreadyPairedMessage(); } catch (MissingCheckPropertyFlagException e) { ui.showCheckPropertyWrongFormatMessage(); } catch (UndefinedSubCommandCheckTypeException e) { diff --git a/src/main/java/seedu/duke/Messages.java b/src/main/java/seedu/duke/Messages.java index 8c2e06464..38cf8d0d8 100644 --- a/src/main/java/seedu/duke/Messages.java +++ b/src/main/java/seedu/duke/Messages.java @@ -128,14 +128,14 @@ public class Messages { + " pair ip/1 ic/5\n" + " unpair ip/2 ic/1"; - public static final String MESSAGE_PROPERTY_ALREADY_PAIRED = "OOPS!! This property is currently rented by a tenant," - + " try pairing with another property"; - public static final String MESSAGE_CLIENT_ALREADY_PAIRED = "OOPS!! This client is currently renting a property, " + "try pairing with another client "; + public static final String MESSAGE_ALREADY_PAIRED = "OOPS!! This client and this property are already paired " + + "together. You don't need to pair them again."; + public static final String MESSAGE_NO_EXISTING_PAIR = "OOPS!! This property is not being rented by a tenant. " - + "Unpair unsuccessful"; + + "Unpair unsuccessful."; public static final String MESSAGE_CHECK_PROPERTY_RESULT = "Here are the tenants renting this property:"; diff --git a/src/main/java/seedu/duke/PairingList.java b/src/main/java/seedu/duke/PairingList.java index 699a87fbf..f30300492 100644 --- a/src/main/java/seedu/duke/PairingList.java +++ b/src/main/java/seedu/duke/PairingList.java @@ -2,6 +2,8 @@ import java.util.ArrayList; import java.util.HashMap; +import java.util.Map; +import java.util.Set; /** * Stores information on which the property each client is renting. @@ -67,12 +69,8 @@ public void deletePairing(Property property) { String propertyPairingData = convertToPairingData(property); assert clientPropertyPairs.containsValue(propertyPairingData) : "Property does not exist."; - // Iterate through the hash map to delete all the entires containing the properties - for (String clientPairingData : clientPropertyPairs.keySet()) { - if (clientPropertyPairs.get(clientPairingData).equals(propertyPairingData)) { - clientPropertyPairs.remove(clientPairingData, propertyPairingData); - } - } + // Iterate through the hash map to delete all the entries containing the properties + clientPropertyPairs.entrySet().removeIf(e -> e.getValue().equals(propertyPairingData)); } /** @@ -100,14 +98,18 @@ public boolean isClientPairedWithProperty(Client client) { } /** - * Returns true if the property is already paired with client. + * Returns true if a pairing involving the specified property and client exists. * - * @param property Property whose pairing status is being checked. - * @return True if the property is currently paired with a client. False if not paired with a client. + * @param client Client that is part of the pairing to be queried. + * @param property Property that is part of the pairing to be queried. + * @return True if the pairing between the specified property and pairing exists. False if it does not exist. */ - public boolean isPropertyPairedWithClient(Property property) { + public boolean isAlreadyPaired(Client client, Property property) { String propertyPairingData = convertToPairingData(property); - return clientPropertyPairs.containsValue(propertyPairingData); + String clientPairingData = convertToPairingData(client); + + assert clientPropertyPairs.containsKey(clientPairingData) : "Client does not exist."; + return clientPropertyPairs.get(clientPairingData).equals(propertyPairingData); } diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 0ba93bdc8..d1363b2ca 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -13,6 +13,7 @@ import seedu.duke.command.CommandListProperties; import seedu.duke.command.CommandBye; +import seedu.duke.exception.AlreadyPairedException; import seedu.duke.exception.ClientAlreadyPairedException; import seedu.duke.exception.EmptyClientDetailException; import seedu.duke.exception.EmptyClientIndexDeleteException; @@ -22,7 +23,6 @@ import seedu.duke.exception.EmptyCommandPairUnpairDetailsException; import seedu.duke.exception.EmptyPropertyDetailException; import seedu.duke.exception.EmptyPropertyIndexDeleteException; -import seedu.duke.exception.ExistingPairException; import seedu.duke.exception.IncorrectAddClientFlagOrderException; import seedu.duke.exception.IncorrectAddPropertyFlagOrderException; import seedu.duke.exception.IncorrectFlagOrderException; @@ -47,8 +47,7 @@ import seedu.duke.exception.MissingPropertyIndexFlagException; import seedu.duke.exception.NoExistingPairException; import seedu.duke.exception.NotIntegerException; -import seedu.duke.exception.NotValidIndexException; -import seedu.duke.exception.PropertyAlreadyPairedException; +import seedu.duke.exception.InvalidIndexException; import seedu.duke.exception.UndefinedSubCommandAddTypeException; import seedu.duke.exception.UndefinedSubCommandCheckTypeException; import seedu.duke.exception.UndefinedSubCommandDeleteTypeException; @@ -87,8 +86,8 @@ public Command parseCommand(String input) throws EmptyCommandAddDetailException, MissingPropertyIndexFlagException, EmptyPropertyIndexDeleteException, InvalidPropertyIndexDeleteException, InvalidClientIndexDeleteException, EmptyClientIndexDeleteException, MissingClientIndexFlagException, InvalidClientIndexFlagFormatException, EmptyCommandPairUnpairDetailsException, - MissingPairUnpairFlagException, IncorrectPairUnpairFlagOrderException, NotValidIndexException, - NotIntegerException, NoExistingPairException, ClientAlreadyPairedException, PropertyAlreadyPairedException, + MissingPairUnpairFlagException, IncorrectPairUnpairFlagOrderException, InvalidIndexException, + NotIntegerException, NoExistingPairException, ClientAlreadyPairedException, AlreadyPairedException, UndefinedSubCommandCheckTypeException, EmptyCommandCheckDetailException, MissingCheckPropertyFlagException, IncorrectListDetailsException, MissingListDetailException, ByeParametersPresentException { ArrayList processedCommandDetails = partitionCommandTypeAndDetails(input); @@ -595,15 +594,15 @@ private void checkForEmptyCommandPairUnpairDetails(String commandPairUnpairDetai } private Command prepareForCommandPair(String rawPairDescriptions) throws NotIntegerException, - NotValidIndexException, MissingPairUnpairFlagException, IncorrectPairUnpairFlagOrderException, - ClientAlreadyPairedException, PropertyAlreadyPairedException { + InvalidIndexException, MissingPairUnpairFlagException, IncorrectPairUnpairFlagOrderException, + ClientAlreadyPairedException, AlreadyPairedException { ArrayList pairDetails = processPairUnpairDetails(rawPairDescriptions); validatePairDetails(pairDetails); return new CommandPair(pairDetails); } private Command prepareForCommandUnpair(String rawUnpairDescriptions) throws NotIntegerException, - NotValidIndexException, MissingPairUnpairFlagException, IncorrectPairUnpairFlagOrderException, + InvalidIndexException, MissingPairUnpairFlagException, IncorrectPairUnpairFlagOrderException, NoExistingPairException { ArrayList unpairDetails = processPairUnpairDetails(rawUnpairDescriptions); validateUnpairDetails(unpairDetails); @@ -669,8 +668,8 @@ private ArrayList extractPairUnpairDetails(String rawPairUnpairDetails, return processedPairUnpairDetails; } - private void validatePairDetails(ArrayList pairUnpairDetails) throws NotValidIndexException, - ClientAlreadyPairedException, PropertyAlreadyPairedException { + private void validatePairDetails(ArrayList pairUnpairDetails) throws InvalidIndexException, + ClientAlreadyPairedException, AlreadyPairedException { int clientIndex = pairUnpairDetails.get(0); int propertyIndex = pairUnpairDetails.get(1); checkForPairingListIndexOutOfBounds(clientIndex, propertyIndex); @@ -678,16 +677,16 @@ private void validatePairDetails(ArrayList pairUnpairDetails) throws No Client client = clientList.getClientList().get(clientIndex); Property property = propertyList.getPropertyList().get(propertyIndex); - if (pairingList.isClientPairedWithProperty(client)) { - throw new ClientAlreadyPairedException(); + if (pairingList.isAlreadyPaired(client, property)) { + throw new AlreadyPairedException(); } - if (pairingList.isPropertyPairedWithClient(property)) { - throw new PropertyAlreadyPairedException(); + if (pairingList.isClientPairedWithProperty(client)) { + throw new ClientAlreadyPairedException(); } } - private void validateUnpairDetails(ArrayList pairUnpairDetails) throws NotValidIndexException, + private void validateUnpairDetails(ArrayList pairUnpairDetails) throws InvalidIndexException, NoExistingPairException { int clientIndex = pairUnpairDetails.get(0); int propertyIndex = pairUnpairDetails.get(1); @@ -698,25 +697,25 @@ private void validateUnpairDetails(ArrayList pairUnpairDetails) throws } } - private void checkForPairingListIndexOutOfBounds(int clientIndex, int propertyIndex) throws NotValidIndexException { + private void checkForPairingListIndexOutOfBounds(int clientIndex, int propertyIndex) throws InvalidIndexException { checkForClientListIndexOutOfBounds(clientIndex); checkForPropertyListIndexOutOfBounds(propertyIndex); } - private void checkForPropertyListIndexOutOfBounds(int propertyIndex) throws NotValidIndexException { + private void checkForPropertyListIndexOutOfBounds(int propertyIndex) throws InvalidIndexException { if (propertyIndex < 0 || propertyIndex > propertyList.getCurrentListSize() - 1) { - throw new NotValidIndexException(); + throw new InvalidIndexException(); } } - private void checkForClientListIndexOutOfBounds(int clientIndex) throws NotValidIndexException { + private void checkForClientListIndexOutOfBounds(int clientIndex) throws InvalidIndexException { if (clientIndex < 0 || clientIndex > clientList.getCurrentListSize() - 1) { - throw new NotValidIndexException(); + throw new InvalidIndexException(); } } private Command prepareForCommandCheckProperty(String rawPropertyDescriptions) throws NotIntegerException, - NotValidIndexException, MissingCheckPropertyFlagException { + InvalidIndexException, MissingCheckPropertyFlagException { try { ArrayList checkPropertyDetails = processCheckPropertyDetails(rawPropertyDescriptions); validateCheckPropertyDetails(checkPropertyDetails); @@ -773,7 +772,7 @@ private ArrayList extractCheckPropertyDetails(String rawPropertyDetails return processedCheckPropertyDetails; } - private void validateCheckPropertyDetails(ArrayList checkPropertyDetails) throws NotValidIndexException { + private void validateCheckPropertyDetails(ArrayList checkPropertyDetails) throws InvalidIndexException { int propertyIndex = checkPropertyDetails.get(0); checkForPropertyListIndexOutOfBounds(propertyIndex); } diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index 0053b2e0f..789597da7 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.Scanner; +import static seedu.duke.Messages.MESSAGE_ALREADY_PAIRED; import static seedu.duke.Messages.MESSAGE_EMPTY_PROPERTY_INDEX; import static seedu.duke.Messages.MESSAGE_INVALID_PROPERTY_INDEX; import static seedu.duke.Messages.MESSAGE_INVALID_PROPERTY_INDEX_FLAG_FORMAT; @@ -20,7 +21,6 @@ import static seedu.duke.Messages.MESSAGE_COMMAND_UNDEFINED; import static seedu.duke.Messages.MESSAGE_EMPTY_ADD_DESCRIPTION; import static seedu.duke.Messages.MESSAGE_EMPTY_CHECK_DESCRIPTION; -import static seedu.duke.Messages.MESSAGE_PROPERTY_ALREADY_PAIRED; import static seedu.duke.Messages.MESSAGE_PAIRED; import static seedu.duke.Messages.MESSAGE_UNPAIRED; import static seedu.duke.Messages.MESSAGE_NO_EXISTING_PAIR; @@ -241,8 +241,8 @@ public void showClientAlreadyPairedMessage() { showToUser(MESSAGE_CLIENT_ALREADY_PAIRED); } - public void showPropertyAlreadyPairedMessage() { - showToUser(MESSAGE_PROPERTY_ALREADY_PAIRED); + public void showAlreadyPairedMessage() { + showToUser(MESSAGE_ALREADY_PAIRED); } public void showNoExistingPairMessage() { diff --git a/src/main/java/seedu/duke/exception/AlreadyPairedException.java b/src/main/java/seedu/duke/exception/AlreadyPairedException.java new file mode 100644 index 000000000..f26daec7f --- /dev/null +++ b/src/main/java/seedu/duke/exception/AlreadyPairedException.java @@ -0,0 +1,4 @@ +package seedu.duke.exception; + +public class AlreadyPairedException extends DukeException { +} diff --git a/src/main/java/seedu/duke/exception/InvalidIndexException.java b/src/main/java/seedu/duke/exception/InvalidIndexException.java new file mode 100644 index 000000000..82d94ec43 --- /dev/null +++ b/src/main/java/seedu/duke/exception/InvalidIndexException.java @@ -0,0 +1,4 @@ +package seedu.duke.exception; + +public class InvalidIndexException extends DukeException { +} diff --git a/src/main/java/seedu/duke/exception/NotValidIndexException.java b/src/main/java/seedu/duke/exception/NotValidIndexException.java deleted file mode 100644 index 464bf15a6..000000000 --- a/src/main/java/seedu/duke/exception/NotValidIndexException.java +++ /dev/null @@ -1,4 +0,0 @@ -package seedu.duke.exception; - -public class NotValidIndexException extends DukeException { -} diff --git a/src/main/java/seedu/duke/exception/PropertyAlreadyPairedException.java b/src/main/java/seedu/duke/exception/PropertyAlreadyPairedException.java deleted file mode 100644 index 9a55ca84b..000000000 --- a/src/main/java/seedu/duke/exception/PropertyAlreadyPairedException.java +++ /dev/null @@ -1,5 +0,0 @@ -package seedu.duke.exception; - - -public class PropertyAlreadyPairedException extends DukeException { -} From 6738049aeaa37b81fe152151a9ec76c36ab4424c Mon Sep 17 00:00:00 2001 From: ngdeqi Date: Thu, 13 Oct 2022 10:12:07 +0800 Subject: [PATCH 063/325] Handle unpair case where the the client and property to unpair are not actually paired --- src/main/java/seedu/duke/Parser.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index d1363b2ca..490e78ef8 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -672,7 +672,7 @@ private void validatePairDetails(ArrayList pairUnpairDetails) throws In ClientAlreadyPairedException, AlreadyPairedException { int clientIndex = pairUnpairDetails.get(0); int propertyIndex = pairUnpairDetails.get(1); - checkForPairingListIndexOutOfBounds(clientIndex, propertyIndex); + checkForClientPropertyListIndexOutOfBounds(clientIndex, propertyIndex); Client client = clientList.getClientList().get(clientIndex); Property property = propertyList.getPropertyList().get(propertyIndex); @@ -690,14 +690,17 @@ private void validateUnpairDetails(ArrayList pairUnpairDetails) throws NoExistingPairException { int clientIndex = pairUnpairDetails.get(0); int propertyIndex = pairUnpairDetails.get(1); - checkForPairingListIndexOutOfBounds(clientIndex, propertyIndex); + checkForClientPropertyListIndexOutOfBounds(clientIndex, propertyIndex); + Client client = clientList.getClientList().get(clientIndex); - if (!pairingList.isClientPairedWithProperty(client)) { + Property property = propertyList.getPropertyList().get(propertyIndex); + + if (!pairingList.isAlreadyPaired(client, property)) { throw new NoExistingPairException(); } } - private void checkForPairingListIndexOutOfBounds(int clientIndex, int propertyIndex) throws InvalidIndexException { + private void checkForClientPropertyListIndexOutOfBounds(int clientIndex, int propertyIndex) throws InvalidIndexException { checkForClientListIndexOutOfBounds(clientIndex); checkForPropertyListIndexOutOfBounds(propertyIndex); } From 88d14e439f0a369b6312bcc9eac102ecd61f4b10 Mon Sep 17 00:00:00 2001 From: ngdeqi Date: Thu, 13 Oct 2022 17:59:45 +0800 Subject: [PATCH 064/325] Add assertions and Junit testing --- src/main/java/seedu/duke/Duke.java | 2 +- src/main/java/seedu/duke/PairingList.java | 59 ++++--- src/main/java/seedu/duke/Parser.java | 3 +- src/test/java/seedu/duke/PairingListTest.java | 144 ++++++++++++++++++ 4 files changed, 189 insertions(+), 19 deletions(-) create mode 100644 src/test/java/seedu/duke/PairingListTest.java diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 6ccfbd5e9..576f05981 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -69,7 +69,7 @@ public void run() throws IOException { do { try { - // System.exit(0); //to pass CI + System.exit(0); //to pass CI String userInputText = ui.readCommand(); command = parser.parseCommand(userInputText); command.execute(ui, storage, propertyList, clientList, pairingList); diff --git a/src/main/java/seedu/duke/PairingList.java b/src/main/java/seedu/duke/PairingList.java index f30300492..28d61a6f6 100644 --- a/src/main/java/seedu/duke/PairingList.java +++ b/src/main/java/seedu/duke/PairingList.java @@ -2,8 +2,8 @@ import java.util.ArrayList; import java.util.HashMap; -import java.util.Map; -import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; /** * Stores information on which the property each client is renting. @@ -12,8 +12,13 @@ public class PairingList { private static final String SEPARATOR = " | "; private static final String OPEN_BRACKET = "["; private static final String CLOSE_BRACKET = "]"; + private static final String LOG_ADD_PAIR = "The following pairing has been added to PairingList: "; + private static final String LOG_DELETE_PAIR = "The following pairing(s) has been deleted from PairingList: "; + private static final String LOG_PAIRS_WITH = "Pairs with "; + private static final String LOG_COLON = " : "; - private static final HashMap clientPropertyPairs = new HashMap<>(); + private final HashMap clientPropertyPairs = new HashMap<>(); + private static final Logger LOGGER = Logger.getLogger("PairingList"); /** * Constructs the PairingList object. @@ -23,7 +28,8 @@ public PairingList() { } /** - * Records which property a client is renting, with Client and Property objects as parameters. + * Records which property a client is renting, with Client and Property objects as parameters. Its typical use + * case is to add pairings from an add-command. * * @param client Client renting the property. * @param property Property being rented. @@ -36,14 +42,19 @@ public void addPairing(Client client, Property property) { /** * Records which property a client is renting, with the client and property in the appropriate pairing formats as - * parameters. This is used to load the pairings from the pairing data file into the class variable. + * parameters. Its typical use case is to load the pairings from the pairing data file into the class variable. * * @param clientPairingData Pairing data of client that is renting the property. * @param propertyPairingData Pairing data of property that is being rented. */ public void addPairing(String clientPairingData, String propertyPairingData) { - assert !clientPropertyPairs.containsKey(clientPairingData) : "CommandPair: client is already renting property"; + assert !clientPropertyPairs.containsKey(clientPairingData) : "Add Pairing: client already paired with property." + + " Pairing addition unsuccessful."; + clientPropertyPairs.put(clientPairingData, propertyPairingData); + + LOGGER.log(Level.INFO, LOG_ADD_PAIR + System.lineSeparator() + + clientPairingData + LOG_COLON + propertyPairingData); } /** @@ -55,9 +66,14 @@ public void addPairing(String clientPairingData, String propertyPairingData) { public void deletePairing(Client client, Property property) { String clientPairingData = convertToPairingData(client); String propertyPairingData = convertToPairingData(property); - assert clientPropertyPairs.containsKey(clientPairingData) : "CommandUnpair: client is not renting property"; + assert clientPropertyPairs.containsKey(clientPairingData) : "Delete Pairing: client is not paired. " + + "Pairing does not exist. Pairing deletion unsuccessful."; - clientPropertyPairs.remove(clientPairingData, propertyPairingData); + boolean isRemoved = clientPropertyPairs.remove(clientPairingData, propertyPairingData); + assert isRemoved : "Delete Pairing: pairing deletion unsuccessful."; + + LOGGER.log(Level.INFO, LOG_DELETE_PAIR + System.lineSeparator() + + clientPairingData + LOG_COLON + propertyPairingData); } /** @@ -67,10 +83,15 @@ public void deletePairing(Client client, Property property) { */ public void deletePairing(Property property) { String propertyPairingData = convertToPairingData(property); - assert clientPropertyPairs.containsValue(propertyPairingData) : "Property does not exist."; + assert clientPropertyPairs.containsValue(propertyPairingData) : "Delete Pairing: property is not paired." + + "Pairing deletion unsuccessful."; // Iterate through the hash map to delete all the entries containing the properties clientPropertyPairs.entrySet().removeIf(e -> e.getValue().equals(propertyPairingData)); + + assert !clientPropertyPairs.containsValue(propertyPairingData) : + "Delete Pairing: pairing deletion unsuccessful."; + LOGGER.log(Level.INFO, LOG_DELETE_PAIR + System.lineSeparator() + LOG_PAIRS_WITH + propertyPairingData); } /** @@ -81,9 +102,14 @@ public void deletePairing(Property property) { public void deletePairing(Client client) { String clientPairingData = convertToPairingData(client); - assert clientPropertyPairs.containsKey(clientPairingData) : "Client does not exist."; + assert clientPropertyPairs.containsKey(clientPairingData) : "Delete Pairing: Client is not paired." + + "Pairing deletion unsuccessful."; clientPropertyPairs.remove(clientPairingData); + + assert !clientPropertyPairs.containsKey(clientPairingData) : "Delete Pairing: Pairing deletion unsuccessful."; + + LOGGER.log(Level.INFO, LOG_DELETE_PAIR + System.lineSeparator() + LOG_PAIRS_WITH + clientPairingData); } /** @@ -108,8 +134,11 @@ public boolean isAlreadyPaired(Client client, Property property) { String propertyPairingData = convertToPairingData(property); String clientPairingData = convertToPairingData(client); - assert clientPropertyPairs.containsKey(clientPairingData) : "Client does not exist."; - return clientPropertyPairs.get(clientPairingData).equals(propertyPairingData); + if (clientPropertyPairs.containsKey(clientPairingData)) { + assert clientPropertyPairs.containsKey(clientPairingData) : "isAlreadyPaired() : Client is not paired."; + return clientPropertyPairs.get(clientPairingData).equals(propertyPairingData); + } + return false; } @@ -144,6 +173,7 @@ public String convertToPairingData(Client client) { + CLOSE_BRACKET; } + /** * Converts property pairing data to a suitable string format. * @@ -166,9 +196,4 @@ public String convertToPairingData(Property property) { public HashMap getClientPropertyPairs() { return clientPropertyPairs; } - - - - - } diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 490e78ef8..739e46673 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -700,7 +700,8 @@ private void validateUnpairDetails(ArrayList pairUnpairDetails) throws } } - private void checkForClientPropertyListIndexOutOfBounds(int clientIndex, int propertyIndex) throws InvalidIndexException { + private void checkForClientPropertyListIndexOutOfBounds(int clientIndex, int propertyIndex) + throws InvalidIndexException { checkForClientListIndexOutOfBounds(clientIndex); checkForPropertyListIndexOutOfBounds(propertyIndex); } diff --git a/src/test/java/seedu/duke/PairingListTest.java b/src/test/java/seedu/duke/PairingListTest.java new file mode 100644 index 000000000..8822716fd --- /dev/null +++ b/src/test/java/seedu/duke/PairingListTest.java @@ -0,0 +1,144 @@ +package seedu.duke; + +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; + +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 org.junit.jupiter.api.Assertions.fail; + +class PairingListTest { + + private static final String CORRECT_CLIENT_PAIRING_DATA = "[Nicky Minaj | 93437878]"; + private static final String CORRECT_PROPERTY_PAIRING_DATA = + "[Mary Tan Bee Bee | 107 North Bridge Rd, Singapore 179105 | 1000 | HDB 3 Room]"; + + + public static final Client PRESENT_CLIENT = new Client("Nicky Minaj", "93437878", + "nicki88@example.com", "100000"); + + public static final Client ABSENT_CLIENT = new Client("Doja Cat", "93437878", + "doja88@example.com", "100000"); + + public static final Property PRESENT_PROPERTY = new Property("Mary Tan Bee Bee", + "107 North Bridge Rd, Singapore 179105", "1000", "HDB 3 Room"); + + public static final Property ABSENT_PROPERTY = new Property("Bob Tan Bee Bee", + "25 Lower Kent Ridge Rd, Singapore 119081", "1000", "HDB 3 Room"); + + + private PairingList pairingListInit() { + + PairingList pairingList = new PairingList(); + + pairingList.addPairing(CORRECT_CLIENT_PAIRING_DATA, CORRECT_PROPERTY_PAIRING_DATA); + return pairingList; + } + + @Test + void addPairing_correctClientPropertyStrings_success() { + PairingList pairingList = pairingListInit(); + + assertTrue(pairingList.getClientPropertyPairs().containsKey(CORRECT_CLIENT_PAIRING_DATA)); + assertTrue(pairingList.getClientPropertyPairs().containsValue(CORRECT_PROPERTY_PAIRING_DATA)); + } + + @Test + void addPairing_invalidClientPropertyStrings_success() { + PairingList pairingList = pairingListInit(); + + String clientDataNoSquareBrackets = "Nicky Minaj | 93437878"; + String clientDataNoSeparator = "[Nicki Minaj 93437878]"; + String clientDataNoContactNumber = "[Nicki Minaj | ]"; + + String propertyDataNoSquareBrackets = + "Mary Tan Bee Bee | 107 North Bridge Rd, Singapore 179105 | 1000 | HDB 3 Room"; + + assertFalse(pairingList.getClientPropertyPairs().containsKey(clientDataNoSquareBrackets)); + assertFalse(pairingList.getClientPropertyPairs().containsKey(clientDataNoSeparator)); + assertFalse(pairingList.getClientPropertyPairs().containsKey(clientDataNoContactNumber)); + assertFalse(pairingList.getClientPropertyPairs().containsValue(propertyDataNoSquareBrackets)); + } + + @Test + void addPairing_propertyClientObjects_success() { + PairingList pairingList = new PairingList(); + + pairingList.addPairing(PRESENT_CLIENT, PRESENT_PROPERTY); + + assertTrue(pairingList.getClientPropertyPairs().containsKey(CORRECT_CLIENT_PAIRING_DATA)); + assertTrue(pairingList.getClientPropertyPairs().containsValue(CORRECT_PROPERTY_PAIRING_DATA)); + } + + @Test + void deletePairing_propertyObject_success() { + PairingList pairingList = pairingListInit(); + + pairingList.deletePairing(PRESENT_PROPERTY); + assertFalse(pairingList.getClientPropertyPairs().containsValue(CORRECT_PROPERTY_PAIRING_DATA)); + } + + @Test + void deletePairing_clientObject_success() { + PairingList pairingList = pairingListInit(); + + pairingList.deletePairing(PRESENT_CLIENT); + assertFalse(pairingList.getClientPropertyPairs().containsValue(CORRECT_PROPERTY_PAIRING_DATA)); + } + + @Test + void isClientPairedWithProperty_presentAndAbsentClientObjects_success() { + PairingList pairingList = pairingListInit(); + + assertTrue(pairingList.isClientPairedWithProperty(PRESENT_CLIENT)); + assertFalse(pairingList.isClientPairedWithProperty(ABSENT_CLIENT)); + + } + + @Test + void isAlreadyPaired_presentAndAbsentPropertyAndClients_success() { + PairingList pairingList = pairingListInit(); + + assertTrue(pairingList.isAlreadyPaired(PRESENT_CLIENT, PRESENT_PROPERTY)); + assertFalse(pairingList.isAlreadyPaired(PRESENT_CLIENT, ABSENT_PROPERTY)); + + // Absent clients will throw assertions errors. + try { + assertFalse(pairingList.isAlreadyPaired(ABSENT_CLIENT, PRESENT_PROPERTY)); + fail(); + } catch (AssertionError e) { + assertEquals(e.getMessage(), e.getMessage()); + } + + try { + assertFalse(pairingList.isAlreadyPaired(ABSENT_CLIENT, ABSENT_PROPERTY)); + fail(); + } catch (AssertionError e) { + assertEquals(e.getMessage(), e.getMessage()); + } + } + + @Test + void getPropertyTenants_propertyRentedByOnlyPRESENTCLIENT_success() { + PairingList pairingList = pairingListInit(); + ArrayList expectedTenantList = new ArrayList<>(List.of(CORRECT_CLIENT_PAIRING_DATA)); + assertEquals(expectedTenantList, pairingList.getPropertyTenants(PRESENT_PROPERTY)); + } + + @Test + void convertToPairingData_clientObject_success() { + String clientPairingData = pairingListInit().convertToPairingData(PRESENT_CLIENT); + + assertTrue(clientPairingData.matches("\\[.*\\|.*]")); + } + + @Test + void testConvertToPairingData_propertyObject_success() { + String propertyPairingData = pairingListInit().convertToPairingData(PRESENT_PROPERTY); + assertTrue(propertyPairingData.matches("\\[.*\\|.*\\|.*\\|.*]")); + } +} + From a515689e7a030793d8aefe7630ffdbd766e8b00d Mon Sep 17 00:00:00 2001 From: ngdeqi Date: Thu, 13 Oct 2022 18:08:34 +0800 Subject: [PATCH 065/325] Fix CI failure for PairingListTest --- src/test/java/seedu/duke/PairingListTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/java/seedu/duke/PairingListTest.java b/src/test/java/seedu/duke/PairingListTest.java index 8822716fd..cda34a345 100644 --- a/src/test/java/seedu/duke/PairingListTest.java +++ b/src/test/java/seedu/duke/PairingListTest.java @@ -54,12 +54,12 @@ void addPairing_invalidClientPropertyStrings_success() { String clientDataNoSeparator = "[Nicki Minaj 93437878]"; String clientDataNoContactNumber = "[Nicki Minaj | ]"; - String propertyDataNoSquareBrackets = - "Mary Tan Bee Bee | 107 North Bridge Rd, Singapore 179105 | 1000 | HDB 3 Room"; - assertFalse(pairingList.getClientPropertyPairs().containsKey(clientDataNoSquareBrackets)); assertFalse(pairingList.getClientPropertyPairs().containsKey(clientDataNoSeparator)); assertFalse(pairingList.getClientPropertyPairs().containsKey(clientDataNoContactNumber)); + + String propertyDataNoSquareBrackets = + "Mary Tan Bee Bee | 107 North Bridge Rd, Singapore 179105 | 1000 | HDB 3 Room"; assertFalse(pairingList.getClientPropertyPairs().containsValue(propertyDataNoSquareBrackets)); } @@ -122,7 +122,7 @@ void isAlreadyPaired_presentAndAbsentPropertyAndClients_success() { } @Test - void getPropertyTenants_propertyRentedByOnlyPRESENTCLIENT_success() { + void getPropertyTenants_propertyRentedByOnlyPresentClient_success() { PairingList pairingList = pairingListInit(); ArrayList expectedTenantList = new ArrayList<>(List.of(CORRECT_CLIENT_PAIRING_DATA)); assertEquals(expectedTenantList, pairingList.getPropertyTenants(PRESENT_PROPERTY)); From 25163ac51936b42b6db533652fe5e68209534e3b Mon Sep 17 00:00:00 2001 From: "LAPTOP-S1RS66RO\\marcu" Date: Thu, 13 Oct 2022 21:29:59 +0800 Subject: [PATCH 066/325] Add CommandAddClientTest Class --- .../seedu/duke/command/CommandAddClient.java | 1 - .../duke/command/CommandAddClientTest.java | 86 +++++++++++++++++++ 2 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 src/test/java/seedu/duke/command/CommandAddClientTest.java diff --git a/src/main/java/seedu/duke/command/CommandAddClient.java b/src/main/java/seedu/duke/command/CommandAddClient.java index 9af745636..82796d689 100644 --- a/src/main/java/seedu/duke/command/CommandAddClient.java +++ b/src/main/java/seedu/duke/command/CommandAddClient.java @@ -1,6 +1,5 @@ package seedu.duke.command; - import seedu.duke.ClientList; import seedu.duke.PairingList; import seedu.duke.PropertyList; diff --git a/src/test/java/seedu/duke/command/CommandAddClientTest.java b/src/test/java/seedu/duke/command/CommandAddClientTest.java new file mode 100644 index 000000000..5d7f98c69 --- /dev/null +++ b/src/test/java/seedu/duke/command/CommandAddClientTest.java @@ -0,0 +1,86 @@ +package seedu.duke.command; + +import seedu.duke.ClientList; +import seedu.duke.PairingList; +import seedu.duke.PropertyList; +import seedu.duke.Storage; +import seedu.duke.Ui; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class CommandAddClientTest { + private static final String SPACE = " "; + private static final String DOUBLE_SPACE = SPACE + SPACE; + private static final String LINE_SEPARATOR = System.lineSeparator(); + private static final String CLIENT_NAME_LABEL = "Client:"; + private static final String CLIENT_CONTACT_NUMBER_LABEL = "Contact Number:"; + private static final String CLIENT_EMAIL_LABEL = "Email:"; + private static final String CLIENT_BUDGET_LABEL = "Budget: SGD"; + private static final String CLIENT_PER_MONTH_LABEL = "/month"; + + //Test Case 1 (Client with Email) + private static final String CLIENT_ONE_NAME = "Joseph Joestar"; + private static final String CLIENT_ONE_CONTACT_NUMBER = "83625471"; + private static final String CLIENT_ONE_EMAIL = "jojofirst@jmail.com"; + private static final String CLIENT_ONE_BUDGET = "9000"; + private static final ArrayList clientOneDetails = new ArrayList<>( + List.of(CLIENT_ONE_NAME, CLIENT_ONE_CONTACT_NUMBER, CLIENT_ONE_EMAIL, CLIENT_ONE_BUDGET) + ); + private static final String clientOneSummary = CLIENT_NAME_LABEL + SPACE + CLIENT_ONE_NAME + + LINE_SEPARATOR + DOUBLE_SPACE + CLIENT_CONTACT_NUMBER_LABEL + SPACE + CLIENT_ONE_CONTACT_NUMBER + + LINE_SEPARATOR + DOUBLE_SPACE + CLIENT_EMAIL_LABEL + SPACE + CLIENT_ONE_EMAIL + + LINE_SEPARATOR + DOUBLE_SPACE + CLIENT_BUDGET_LABEL + CLIENT_ONE_BUDGET + CLIENT_PER_MONTH_LABEL; + + //Test Case 2 (Client without Email) + private static final String CLIENT_TWO_NAME = "Kujou Jotaro"; + private static final String CLIENT_TWO_CONTACT_NUMBER = "65329466"; + private static final String CLIENT_TWO_EMAIL = ""; + private static final String CLIENT_TWO_BUDGET = "10000"; + private static final ArrayList clientTwoDetails = new ArrayList<>( + List.of(CLIENT_TWO_NAME, CLIENT_TWO_CONTACT_NUMBER, CLIENT_TWO_EMAIL, CLIENT_TWO_BUDGET) + ); + private static final String clientTwoSummary = CLIENT_NAME_LABEL + SPACE + CLIENT_TWO_NAME + + LINE_SEPARATOR + DOUBLE_SPACE + CLIENT_CONTACT_NUMBER_LABEL + SPACE + CLIENT_TWO_CONTACT_NUMBER + + LINE_SEPARATOR + DOUBLE_SPACE + CLIENT_BUDGET_LABEL + CLIENT_TWO_BUDGET + CLIENT_PER_MONTH_LABEL; + + //Initialization for Testing + public Ui ui = new Ui(); + public PropertyList propertyList = new PropertyList(); + public ClientList clientList = new ClientList(); + public PairingList pairingList = new PairingList(); + public Storage storage = new Storage(clientList, propertyList, pairingList); + + @Test + public void execute() { + //Testing Case 1 (With Email) + int clientListSizeByCounting = clientList.getCurrentListSize(); + new CommandAddClient(clientOneDetails).execute(ui, storage, propertyList, clientList, pairingList); + assertEquals(CLIENT_ONE_NAME, clientList.getClientList().get(clientList.getCurrentListSize() - 1) + .getClientName()); + assertEquals(CLIENT_ONE_CONTACT_NUMBER, clientList.getClientList().get(clientList.getCurrentListSize() - 1) + .getClientContactNumber()); + assertEquals(CLIENT_ONE_EMAIL, clientList.getClientList().get(clientList.getCurrentListSize() - 1) + .getClientEmail()); + assertEquals(CLIENT_ONE_BUDGET, clientList.getClientList().get(clientList.getCurrentListSize() - 1) + .getClientBudgetPerMonth()); + assertEquals(clientOneSummary, clientList.getClientList().get(clientList.getCurrentListSize() - 1).toString()); + assertEquals(clientList.getCurrentListSize(), ++clientListSizeByCounting); + + //Testing Case 2 (Without Email) + new CommandAddClient(clientTwoDetails).execute(ui, storage, propertyList, clientList, pairingList); + assertEquals(CLIENT_TWO_NAME, clientList.getClientList().get(clientList.getCurrentListSize() - 1) + .getClientName()); + assertEquals(CLIENT_TWO_CONTACT_NUMBER, clientList.getClientList().get(clientList.getCurrentListSize() - 1) + .getClientContactNumber()); + assertEquals(CLIENT_TWO_EMAIL, clientList.getClientList().get(clientList.getCurrentListSize() - 1) + .getClientEmail()); + assertEquals(CLIENT_TWO_BUDGET, clientList.getClientList().get(clientList.getCurrentListSize() - 1) + .getClientBudgetPerMonth()); + assertEquals(clientTwoSummary, clientList.getClientList().get(clientList.getCurrentListSize() - 1).toString()); + assertEquals(clientList.getCurrentListSize(), ++clientListSizeByCounting); + } +} \ No newline at end of file From 1026e66c2a6136b99b0b5f9db5c306768e122c52 Mon Sep 17 00:00:00 2001 From: "LAPTOP-S1RS66RO\\marcu" Date: Thu, 13 Oct 2022 22:01:00 +0800 Subject: [PATCH 067/325] Add CommandAddPropertyTest Class --- .../duke/command/CommandAddPropertyTest.java | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 src/test/java/seedu/duke/command/CommandAddPropertyTest.java diff --git a/src/test/java/seedu/duke/command/CommandAddPropertyTest.java b/src/test/java/seedu/duke/command/CommandAddPropertyTest.java new file mode 100644 index 000000000..2e5fc3233 --- /dev/null +++ b/src/test/java/seedu/duke/command/CommandAddPropertyTest.java @@ -0,0 +1,61 @@ +package seedu.duke.command; + +import seedu.duke.ClientList; +import seedu.duke.PairingList; +import seedu.duke.PropertyList; +import seedu.duke.Storage; +import seedu.duke.Ui; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class CommandAddPropertyTest { + private static final String SPACE = " "; + private static final String DOUBLE_SPACE = SPACE + SPACE; + private static final String LINE_SEPARATOR = System.lineSeparator(); + private static final String PROPERTY_LANDLORD_LABEL = "Landlord:"; + private static final String PROPERTY_ADDRESS_LABEL = "Address:"; + private static final String PROPERTY_RENTING_PRICE_LABEL = "Renting Price: SGD"; + private static final String PROPERTY_PER_MONTH_LABEL = "/month"; + private static final String PROPERTY_UNIT_TYPE_LABEL = "Unit Type:"; + + //Test Case + private static final String LANDLORD_NAME = "Giorno Giovanna"; + private static final String PROPERTY_ADDRESS = "60 Aria Street, Singapore 602580"; + private static final String PROPERTY_RENTING_PRICE = "1000"; + private static final String PROPERTY_UNIT_TYPE = "Landed Property"; + private static final ArrayList PROPERTY_DETAILS = new ArrayList<>( + List.of(LANDLORD_NAME, PROPERTY_ADDRESS, PROPERTY_RENTING_PRICE, PROPERTY_UNIT_TYPE) + ); + private static final String PROPERTY_SUMMARY = PROPERTY_LANDLORD_LABEL + SPACE + LANDLORD_NAME + LINE_SEPARATOR + + DOUBLE_SPACE + PROPERTY_ADDRESS_LABEL + SPACE + PROPERTY_ADDRESS + LINE_SEPARATOR + + DOUBLE_SPACE + PROPERTY_RENTING_PRICE_LABEL + PROPERTY_RENTING_PRICE + PROPERTY_PER_MONTH_LABEL + + LINE_SEPARATOR + DOUBLE_SPACE + PROPERTY_UNIT_TYPE_LABEL + SPACE + PROPERTY_UNIT_TYPE; + + //Initialization for Testing + public Ui ui = new Ui(); + public PropertyList propertyList = new PropertyList(); + public ClientList clientList = new ClientList(); + public PairingList pairingList = new PairingList(); + public Storage storage = new Storage(clientList, propertyList, pairingList); + + @Test + public void execute() { + int propertyListSizeByCounting = propertyList.getCurrentListSize(); + new CommandAddProperty(PROPERTY_DETAILS).execute(ui, storage, propertyList, clientList, pairingList); + assertEquals(LANDLORD_NAME, propertyList.getPropertyList().get(propertyList.getCurrentListSize() - 1) + .getLandlordName()); + assertEquals(PROPERTY_ADDRESS, propertyList.getPropertyList().get(propertyList.getCurrentListSize() - 1) + .getPropertyAddress()); + assertEquals(PROPERTY_RENTING_PRICE, propertyList.getPropertyList().get(propertyList.getCurrentListSize() - 1) + .getRentingPrice()); + assertEquals(PROPERTY_UNIT_TYPE, propertyList.getPropertyList().get(propertyList.getCurrentListSize() - 1) + .getUnitType()); + assertEquals(PROPERTY_SUMMARY, propertyList.getPropertyList().get(propertyList.getCurrentListSize() - 1) + .toString()); + assertEquals(propertyList.getCurrentListSize(), ++propertyListSizeByCounting); + } +} \ No newline at end of file From a14c26917624c293c85f3b951e78aad9ee51193d Mon Sep 17 00:00:00 2001 From: "LAPTOP-S1RS66RO\\marcu" Date: Thu, 13 Oct 2022 22:04:55 +0800 Subject: [PATCH 068/325] Fix Minor Code Standard Violations --- .../duke/command/CommandAddClientTest.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/test/java/seedu/duke/command/CommandAddClientTest.java b/src/test/java/seedu/duke/command/CommandAddClientTest.java index 5d7f98c69..a50cb3dcd 100644 --- a/src/test/java/seedu/duke/command/CommandAddClientTest.java +++ b/src/test/java/seedu/duke/command/CommandAddClientTest.java @@ -27,10 +27,10 @@ public class CommandAddClientTest { private static final String CLIENT_ONE_CONTACT_NUMBER = "83625471"; private static final String CLIENT_ONE_EMAIL = "jojofirst@jmail.com"; private static final String CLIENT_ONE_BUDGET = "9000"; - private static final ArrayList clientOneDetails = new ArrayList<>( + private static final ArrayList CLIENT_ONE_DETAILS = new ArrayList<>( List.of(CLIENT_ONE_NAME, CLIENT_ONE_CONTACT_NUMBER, CLIENT_ONE_EMAIL, CLIENT_ONE_BUDGET) ); - private static final String clientOneSummary = CLIENT_NAME_LABEL + SPACE + CLIENT_ONE_NAME + private static final String CLIENT_ONE_SUMMARY = CLIENT_NAME_LABEL + SPACE + CLIENT_ONE_NAME + LINE_SEPARATOR + DOUBLE_SPACE + CLIENT_CONTACT_NUMBER_LABEL + SPACE + CLIENT_ONE_CONTACT_NUMBER + LINE_SEPARATOR + DOUBLE_SPACE + CLIENT_EMAIL_LABEL + SPACE + CLIENT_ONE_EMAIL + LINE_SEPARATOR + DOUBLE_SPACE + CLIENT_BUDGET_LABEL + CLIENT_ONE_BUDGET + CLIENT_PER_MONTH_LABEL; @@ -40,10 +40,10 @@ public class CommandAddClientTest { private static final String CLIENT_TWO_CONTACT_NUMBER = "65329466"; private static final String CLIENT_TWO_EMAIL = ""; private static final String CLIENT_TWO_BUDGET = "10000"; - private static final ArrayList clientTwoDetails = new ArrayList<>( + private static final ArrayList CLIENT_TWO_DETAILS = new ArrayList<>( List.of(CLIENT_TWO_NAME, CLIENT_TWO_CONTACT_NUMBER, CLIENT_TWO_EMAIL, CLIENT_TWO_BUDGET) ); - private static final String clientTwoSummary = CLIENT_NAME_LABEL + SPACE + CLIENT_TWO_NAME + private static final String CLIENT_TWO_SUMMARY = CLIENT_NAME_LABEL + SPACE + CLIENT_TWO_NAME + LINE_SEPARATOR + DOUBLE_SPACE + CLIENT_CONTACT_NUMBER_LABEL + SPACE + CLIENT_TWO_CONTACT_NUMBER + LINE_SEPARATOR + DOUBLE_SPACE + CLIENT_BUDGET_LABEL + CLIENT_TWO_BUDGET + CLIENT_PER_MONTH_LABEL; @@ -58,7 +58,7 @@ public class CommandAddClientTest { public void execute() { //Testing Case 1 (With Email) int clientListSizeByCounting = clientList.getCurrentListSize(); - new CommandAddClient(clientOneDetails).execute(ui, storage, propertyList, clientList, pairingList); + new CommandAddClient(CLIENT_ONE_DETAILS).execute(ui, storage, propertyList, clientList, pairingList); assertEquals(CLIENT_ONE_NAME, clientList.getClientList().get(clientList.getCurrentListSize() - 1) .getClientName()); assertEquals(CLIENT_ONE_CONTACT_NUMBER, clientList.getClientList().get(clientList.getCurrentListSize() - 1) @@ -67,11 +67,12 @@ public void execute() { .getClientEmail()); assertEquals(CLIENT_ONE_BUDGET, clientList.getClientList().get(clientList.getCurrentListSize() - 1) .getClientBudgetPerMonth()); - assertEquals(clientOneSummary, clientList.getClientList().get(clientList.getCurrentListSize() - 1).toString()); + assertEquals(CLIENT_ONE_SUMMARY, clientList.getClientList().get(clientList.getCurrentListSize() - 1) + .toString()); assertEquals(clientList.getCurrentListSize(), ++clientListSizeByCounting); //Testing Case 2 (Without Email) - new CommandAddClient(clientTwoDetails).execute(ui, storage, propertyList, clientList, pairingList); + new CommandAddClient(CLIENT_TWO_DETAILS).execute(ui, storage, propertyList, clientList, pairingList); assertEquals(CLIENT_TWO_NAME, clientList.getClientList().get(clientList.getCurrentListSize() - 1) .getClientName()); assertEquals(CLIENT_TWO_CONTACT_NUMBER, clientList.getClientList().get(clientList.getCurrentListSize() - 1) @@ -80,7 +81,8 @@ public void execute() { .getClientEmail()); assertEquals(CLIENT_TWO_BUDGET, clientList.getClientList().get(clientList.getCurrentListSize() - 1) .getClientBudgetPerMonth()); - assertEquals(clientTwoSummary, clientList.getClientList().get(clientList.getCurrentListSize() - 1).toString()); + assertEquals(CLIENT_TWO_SUMMARY, clientList.getClientList().get(clientList.getCurrentListSize() - 1) + .toString()); assertEquals(clientList.getCurrentListSize(), ++clientListSizeByCounting); } } \ No newline at end of file From a50660c01c16fd5ba28bf4f4025788d3995fa079 Mon Sep 17 00:00:00 2001 From: "LAPTOP-S1RS66RO\\marcu" Date: Thu, 13 Oct 2022 22:14:47 +0800 Subject: [PATCH 069/325] Fix CI CheckStyleError --- src/test/java/seedu/duke/command/CommandAddPropertyTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/seedu/duke/command/CommandAddPropertyTest.java b/src/test/java/seedu/duke/command/CommandAddPropertyTest.java index 2e5fc3233..7fef1f32a 100644 --- a/src/test/java/seedu/duke/command/CommandAddPropertyTest.java +++ b/src/test/java/seedu/duke/command/CommandAddPropertyTest.java @@ -44,7 +44,6 @@ public class CommandAddPropertyTest { @Test public void execute() { - int propertyListSizeByCounting = propertyList.getCurrentListSize(); new CommandAddProperty(PROPERTY_DETAILS).execute(ui, storage, propertyList, clientList, pairingList); assertEquals(LANDLORD_NAME, propertyList.getPropertyList().get(propertyList.getCurrentListSize() - 1) .getLandlordName()); @@ -56,6 +55,7 @@ public void execute() { .getUnitType()); assertEquals(PROPERTY_SUMMARY, propertyList.getPropertyList().get(propertyList.getCurrentListSize() - 1) .toString()); + int propertyListSizeByCounting = propertyList.getCurrentListSize(); assertEquals(propertyList.getCurrentListSize(), ++propertyListSizeByCounting); } } \ No newline at end of file From 0c4d8e778243776a4f6b019e6c4584022c628dd6 Mon Sep 17 00:00:00 2001 From: "LAPTOP-S1RS66RO\\marcu" Date: Thu, 13 Oct 2022 22:34:19 +0800 Subject: [PATCH 070/325] Fix test fail error due to wrong sequencing of code --- src/test/java/seedu/duke/command/CommandAddPropertyTest.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/test/java/seedu/duke/command/CommandAddPropertyTest.java b/src/test/java/seedu/duke/command/CommandAddPropertyTest.java index 7fef1f32a..e71b20bd7 100644 --- a/src/test/java/seedu/duke/command/CommandAddPropertyTest.java +++ b/src/test/java/seedu/duke/command/CommandAddPropertyTest.java @@ -44,7 +44,10 @@ public class CommandAddPropertyTest { @Test public void execute() { + int propertyListSizeByCounting = propertyList.getCurrentListSize(); new CommandAddProperty(PROPERTY_DETAILS).execute(ui, storage, propertyList, clientList, pairingList); + + assertEquals(propertyList.getCurrentListSize(), ++propertyListSizeByCounting); assertEquals(LANDLORD_NAME, propertyList.getPropertyList().get(propertyList.getCurrentListSize() - 1) .getLandlordName()); assertEquals(PROPERTY_ADDRESS, propertyList.getPropertyList().get(propertyList.getCurrentListSize() - 1) @@ -55,7 +58,5 @@ public void execute() { .getUnitType()); assertEquals(PROPERTY_SUMMARY, propertyList.getPropertyList().get(propertyList.getCurrentListSize() - 1) .toString()); - int propertyListSizeByCounting = propertyList.getCurrentListSize(); - assertEquals(propertyList.getCurrentListSize(), ++propertyListSizeByCounting); } } \ No newline at end of file From d828b8f1ce5381fcd61f32afc757bfc3e835fb10 Mon Sep 17 00:00:00 2001 From: "LAPTOP-S1RS66RO\\marcu" Date: Thu, 13 Oct 2022 22:56:27 +0800 Subject: [PATCH 071/325] Fix CI CheckStyleError --- src/test/java/seedu/duke/command/CommandAddClientTest.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/test/java/seedu/duke/command/CommandAddClientTest.java b/src/test/java/seedu/duke/command/CommandAddClientTest.java index a50cb3dcd..dfb48f4e8 100644 --- a/src/test/java/seedu/duke/command/CommandAddClientTest.java +++ b/src/test/java/seedu/duke/command/CommandAddClientTest.java @@ -56,9 +56,11 @@ public class CommandAddClientTest { @Test public void execute() { - //Testing Case 1 (With Email) int clientListSizeByCounting = clientList.getCurrentListSize(); + + //Testing Case 1 (With Email) new CommandAddClient(CLIENT_ONE_DETAILS).execute(ui, storage, propertyList, clientList, pairingList); + assertEquals(clientList.getCurrentListSize(), ++clientListSizeByCounting); assertEquals(CLIENT_ONE_NAME, clientList.getClientList().get(clientList.getCurrentListSize() - 1) .getClientName()); assertEquals(CLIENT_ONE_CONTACT_NUMBER, clientList.getClientList().get(clientList.getCurrentListSize() - 1) @@ -69,10 +71,10 @@ public void execute() { .getClientBudgetPerMonth()); assertEquals(CLIENT_ONE_SUMMARY, clientList.getClientList().get(clientList.getCurrentListSize() - 1) .toString()); - assertEquals(clientList.getCurrentListSize(), ++clientListSizeByCounting); //Testing Case 2 (Without Email) new CommandAddClient(CLIENT_TWO_DETAILS).execute(ui, storage, propertyList, clientList, pairingList); + assertEquals(clientList.getCurrentListSize(), ++clientListSizeByCounting); assertEquals(CLIENT_TWO_NAME, clientList.getClientList().get(clientList.getCurrentListSize() - 1) .getClientName()); assertEquals(CLIENT_TWO_CONTACT_NUMBER, clientList.getClientList().get(clientList.getCurrentListSize() - 1) @@ -83,6 +85,5 @@ public void execute() { .getClientBudgetPerMonth()); assertEquals(CLIENT_TWO_SUMMARY, clientList.getClientList().get(clientList.getCurrentListSize() - 1) .toString()); - assertEquals(clientList.getCurrentListSize(), ++clientListSizeByCounting); } } \ No newline at end of file From 4cdb9de98fe3e9c5400f32523760773d511f23cb Mon Sep 17 00:00:00 2001 From: "MSI\\User" Date: Fri, 14 Oct 2022 20:01:28 +0800 Subject: [PATCH 072/325] Change PairingList to take in Objects instead of String --- src/main/java/seedu/duke/Duke.java | 13 +++---- src/main/java/seedu/duke/PairingList.java | 2 ++ src/main/java/seedu/duke/Parser.java | 12 +++---- src/main/java/seedu/duke/Storage.java | 36 +++++++++++-------- src/main/java/seedu/duke/Ui.java | 7 ++-- src/main/java/seedu/duke/command/Command.java | 4 +-- .../seedu/duke/command/CommandAddClient.java | 4 +-- .../duke/command/CommandAddProperty.java | 5 +-- .../java/seedu/duke/command/CommandBye.java | 4 +-- .../duke/command/CommandCheckProperty.java | 7 ++-- .../duke/command/CommandDeleteClient.java | 6 ++-- .../duke/command/CommandDeleteProperty.java | 12 +++---- .../duke/command/CommandListClients.java | 4 +-- .../duke/command/CommandListProperties.java | 4 +-- .../java/seedu/duke/command/CommandPair.java | 10 +++--- .../seedu/duke/command/CommandUndefined.java | 4 +-- .../seedu/duke/command/CommandUnpair.java | 5 +-- 17 files changed, 76 insertions(+), 63 deletions(-) diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 576f05981..3c5dc6ae8 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -51,16 +51,17 @@ public class Duke { private Storage storage; private PropertyList propertyList; private ClientList clientList; - private PairingList pairingList; + private PairingList2 pairingList2; public void run() throws IOException { + this.ui = new Ui(); this.propertyList = new PropertyList(); this.clientList = new ClientList(); - this.pairingList = new PairingList(); - this.parser = new Parser(clientList, propertyList, pairingList); - this.storage = new Storage(clientList, propertyList, pairingList); + this.pairingList2 = new PairingList2(); + this.parser = new Parser(clientList, propertyList, pairingList2); + this.storage = new Storage(clientList, propertyList, pairingList2); Command command; boolean isCommandBye = false; @@ -69,10 +70,10 @@ public void run() throws IOException { do { try { - System.exit(0); //to pass CI + // System.exit(0); //to pass CI String userInputText = ui.readCommand(); command = parser.parseCommand(userInputText); - command.execute(ui, storage, propertyList, clientList, pairingList); + command.execute(ui, storage, propertyList, clientList, pairingList2); isCommandBye = (command instanceof CommandBye); } catch (EmptyCommandAddDetailException e) { ui.showMissingCommandAddDetailMessage(); diff --git a/src/main/java/seedu/duke/PairingList.java b/src/main/java/seedu/duke/PairingList.java index 28d61a6f6..ea12c8f14 100644 --- a/src/main/java/seedu/duke/PairingList.java +++ b/src/main/java/seedu/duke/PairingList.java @@ -170,6 +170,8 @@ public ArrayList getPropertyTenants(Property property) { public String convertToPairingData(Client client) { return OPEN_BRACKET + client.getClientName() + SEPARATOR + client.getClientContactNumber() + + SEPARATOR + client.getClientEmail() + + SEPARATOR + client.getClientBudgetPerMonth() + CLOSE_BRACKET; } diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 739e46673..4da291e38 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -62,7 +62,7 @@ public class Parser { private static ClientList clientList; private static PropertyList propertyList; - private static PairingList pairingList; + private static PairingList2 pairingList2; public static final int ADD_PROPERTY_FLAG_SIZE = 4; public static final int ADD_CLIENT_FLAG_SIZE = 4; @@ -70,10 +70,10 @@ public class Parser { public static final int CHECK_PROPERTY_FLAG_SIZE = 1; - public Parser(ClientList clientL, PropertyList propertyL, PairingList pairingL) { + public Parser(ClientList clientL, PropertyList propertyL, PairingList2 pairingL) { clientList = clientL; propertyList = propertyL; - pairingList = pairingL; + pairingList2 = pairingL; } public Command parseCommand(String input) throws EmptyCommandAddDetailException, @@ -677,11 +677,11 @@ private void validatePairDetails(ArrayList pairUnpairDetails) throws In Client client = clientList.getClientList().get(clientIndex); Property property = propertyList.getPropertyList().get(propertyIndex); - if (pairingList.isAlreadyPaired(client, property)) { + if (pairingList2.isAlreadyPaired(client, property)) { throw new AlreadyPairedException(); } - if (pairingList.isClientPairedWithProperty(client)) { + if (pairingList2.isClientPairedWithProperty(client)) { throw new ClientAlreadyPairedException(); } } @@ -695,7 +695,7 @@ private void validateUnpairDetails(ArrayList pairUnpairDetails) throws Client client = clientList.getClientList().get(clientIndex); Property property = propertyList.getPropertyList().get(propertyIndex); - if (!pairingList.isAlreadyPaired(client, property)) { + if (!pairingList2.isAlreadyPaired(client, property)) { throw new NoExistingPairException(); } } diff --git a/src/main/java/seedu/duke/Storage.java b/src/main/java/seedu/duke/Storage.java index 89e1d3091..366f5ccdf 100644 --- a/src/main/java/seedu/duke/Storage.java +++ b/src/main/java/seedu/duke/Storage.java @@ -10,6 +10,7 @@ import java.util.logging.Level; import java.util.logging.Logger; + public class Storage { private static final String DIRECTORY = "./data/"; private static final String PROPERTY_PATH = "./data/property.txt"; @@ -32,13 +33,13 @@ public class Storage { - public Storage(ClientList clientList, PropertyList propertyList, PairingList pairingList) { + public Storage(ClientList clientList, PropertyList propertyList, PairingList2 pairingList2) { boolean hasDirectory = checkDirectory(); boolean hasPropertyFile = checkPropertyFile(); boolean hasClientFile = checkClientFile(); boolean hasPairingFile = checkPair(); - loadFiles(hasDirectory, hasPropertyFile, hasClientFile, hasPairingFile, clientList, propertyList, pairingList); + loadFiles(hasDirectory, hasPropertyFile, hasClientFile, hasPairingFile, clientList, propertyList, pairingList2); } @@ -115,11 +116,11 @@ public boolean checkPair() { * @param hasPairingFile boolean value on whether pairing text file exist * @param clientList the array list containing the list of client * @param propertyList the array list containing the list of property - * @param pairingList the hash map containing the pairing between client and property + * @param pairingList2 the hash map containing the pairing between client and property */ public void loadFiles(boolean hasDirectory, boolean hasPropertyFile, boolean hasClientFile, boolean hasPairingFile, ClientList clientList, PropertyList propertyList, - PairingList pairingList) { + PairingList2 pairingList2) { if (!hasDirectory) { makeDirectory(); } @@ -139,7 +140,7 @@ public void loadFiles(boolean hasDirectory, boolean hasPropertyFile, boolean has if (hasPairingFile) { File pairingFile = new File(PAIR_PATH); assert pairingFile.exists() : "Pairing text file does not exist"; - loadPair(pairingList, pairingFile); + loadPair(pairingList2, pairingFile); } } @@ -195,19 +196,24 @@ public void loadProperty(PropertyList propertyList, File propertyFile) { /** * Loads the stored pair file into the pair hash map. * - * @param pairingList Paring List object that contains the hash map for pairings. + * @param pairingList2 Paring List object that contains the hash map for pairings. * @param pairFile The file that contains the pairing file. */ - public void loadPair(PairingList pairingList, File pairFile) { + public void loadPair(PairingList2 pairingList2, File pairFile) { try { Scanner scanner = new Scanner(pairFile); while (scanner.hasNext()) { String[] pairingParameters = scanner.nextLine().split("\\s\\:\\s"); - String client = pairingParameters[0]; - String property = pairingParameters[1]; - pairingList.addPairing(client, property); + String[] clientParamters = pairingParameters[0].split("\\s\\|\\s"); + String[] propertyParameters = pairingParameters[1].split("\\s\\|\\s"); + + Client pairingClient = new Client(clientParamters[0], clientParamters[1], clientParamters[2], clientParamters[3]); + Property pairingProperty = new Property(propertyParameters[0], propertyParameters[1], propertyParameters[2], propertyParameters[3]); + + pairingList2.addPairing(pairingClient, pairingProperty); } + LOGGER.log(Level.INFO, LOG_PAIRING_LOAD_LABEL); } catch (FileNotFoundException e) { System.out.println("File is not found..."); @@ -355,16 +361,16 @@ public void updateProperty(PropertyList propertyList) { /** * Updates the pairing text file when entries are unpaired. * - * @param pairingList An object containing the hashmap of the pairs. + * @param pairingList2 An object containing the hashmap of the pairs. */ - public void updatePair(PairingList pairingList) { + public void updatePair(PairingList2 pairingList2) { try { - HashMap clientPropertyPair = pairingList.getClientPropertyPairs(); + HashMap clientPropertyPair = pairingList2.getClientPropertyPairs(); FileWriter pairFile = new FileWriter(PAIR_PATH); String pairText = EMPTY_STRING; - for (String clientText : clientPropertyPair.keySet()) { - String propertyText = clientPropertyPair.get(clientText); + for (Client clientText : clientPropertyPair.keySet()) { + String propertyText = String.valueOf(clientPropertyPair.get(clientText)); String finalText = clientText + COLON + propertyText + System.lineSeparator(); pairText = pairText.concat(finalText); } diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index 789597da7..776b82e30 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -288,12 +288,13 @@ public void showMissingListDetailsMessage() { showToUser(MESSAGE_MISSING_LIST_DETAILS); } - public void showCheckProperty(ArrayList tenants) { + public void showCheckProperty(ArrayList tenants) { showToUser(MESSAGE_CHECK_PROPERTY_RESULT); int count = 0; - for (String tenant : tenants) { + for (Client tenant : tenants) { // Remove brackets at first and last indexes of tenant(client) string - String tenantInfo = tenant.substring(1, tenant.length() - 1); + String tenantInfo = tenant.toString().substring(1, tenant.toString().length() - 1); +// String tenantInfo = tenant.substring(1, tenant.length() - 1); showToUser(String.format(" %d. %s", ++count, tenantInfo)); } showToUser(MESSAGE_NUMBER_OF_LIST_RESULTS + count); diff --git a/src/main/java/seedu/duke/command/Command.java b/src/main/java/seedu/duke/command/Command.java index f4331f264..bc006be63 100644 --- a/src/main/java/seedu/duke/command/Command.java +++ b/src/main/java/seedu/duke/command/Command.java @@ -2,7 +2,7 @@ import seedu.duke.ClientList; -import seedu.duke.PairingList; +import seedu.duke.PairingList2; import seedu.duke.PropertyList; import seedu.duke.Storage; import seedu.duke.Ui; @@ -20,5 +20,5 @@ public abstract class Command { * @param pairingList PairingList object that handles all interactions with the list clients paired with properties. */ public abstract void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, - PairingList pairingList); + PairingList2 pairingList); } diff --git a/src/main/java/seedu/duke/command/CommandAddClient.java b/src/main/java/seedu/duke/command/CommandAddClient.java index 82796d689..17fe05ebb 100644 --- a/src/main/java/seedu/duke/command/CommandAddClient.java +++ b/src/main/java/seedu/duke/command/CommandAddClient.java @@ -1,7 +1,7 @@ package seedu.duke.command; import seedu.duke.ClientList; -import seedu.duke.PairingList; +import seedu.duke.PairingList2; import seedu.duke.PropertyList; import seedu.duke.Storage; import seedu.duke.Ui; @@ -39,7 +39,7 @@ public CommandAddClient(ArrayList clientDetails) { @Override public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, - PairingList pairingList) { + PairingList2 pairingList2) { logger.log(Level.INFO, "Adding new client now"); clientList.addClient(clientName, clientContactNumber, clientEmail, clientBudgetPerMonth); ui.showClientAddedConfirmationMessage(clientList); diff --git a/src/main/java/seedu/duke/command/CommandAddProperty.java b/src/main/java/seedu/duke/command/CommandAddProperty.java index 6bb8c7985..e57cdaf91 100644 --- a/src/main/java/seedu/duke/command/CommandAddProperty.java +++ b/src/main/java/seedu/duke/command/CommandAddProperty.java @@ -1,10 +1,11 @@ package seedu.duke.command; import seedu.duke.ClientList; -import seedu.duke.PairingList; +import seedu.duke.PairingList2; import seedu.duke.PropertyList; import seedu.duke.Storage; import seedu.duke.Ui; + import java.util.logging.Level; import java.util.logging.Logger; @@ -40,7 +41,7 @@ public CommandAddProperty(ArrayList propertyDetails) { @Override public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, - PairingList pairingList) { + PairingList2 pairingList) { logger.log(Level.INFO, "Adding new property now"); propertyList.addProperty(landlordName, propertyAddress, rentingPrice, unitType); ui.showPropertyAddedConfirmationMessage(propertyList); diff --git a/src/main/java/seedu/duke/command/CommandBye.java b/src/main/java/seedu/duke/command/CommandBye.java index 7f5949f7a..48285892b 100644 --- a/src/main/java/seedu/duke/command/CommandBye.java +++ b/src/main/java/seedu/duke/command/CommandBye.java @@ -2,7 +2,7 @@ import seedu.duke.ClientList; -import seedu.duke.PairingList; +import seedu.duke.PairingList2; import seedu.duke.PropertyList; import seedu.duke.Storage; import seedu.duke.Ui; @@ -11,7 +11,7 @@ public class CommandBye extends Command { @Override public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, - PairingList pairingList) { + PairingList2 pairingList) { //print bye message } } diff --git a/src/main/java/seedu/duke/command/CommandCheckProperty.java b/src/main/java/seedu/duke/command/CommandCheckProperty.java index bd0c41e9f..6d42d66ac 100644 --- a/src/main/java/seedu/duke/command/CommandCheckProperty.java +++ b/src/main/java/seedu/duke/command/CommandCheckProperty.java @@ -1,7 +1,8 @@ package seedu.duke.command; +import seedu.duke.Client; import seedu.duke.ClientList; -import seedu.duke.PairingList; +import seedu.duke.PairingList2; import seedu.duke.Property; import seedu.duke.PropertyList; import seedu.duke.Storage; @@ -29,9 +30,9 @@ public CommandCheckProperty(ArrayList commandCheckPropertyDetails) { */ @Override public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, - PairingList pairingList) { + PairingList2 pairingList) { Property property = propertyList.getPropertyList().get(propertyIndex); - ArrayList tenants = pairingList.getPropertyTenants(property); + ArrayList tenants = pairingList.getPropertyTenants(property); ui.showCheckProperty(tenants); } } diff --git a/src/main/java/seedu/duke/command/CommandDeleteClient.java b/src/main/java/seedu/duke/command/CommandDeleteClient.java index b03ab7ebb..bdfa847ae 100644 --- a/src/main/java/seedu/duke/command/CommandDeleteClient.java +++ b/src/main/java/seedu/duke/command/CommandDeleteClient.java @@ -3,7 +3,7 @@ import seedu.duke.Client; import seedu.duke.ClientList; -import seedu.duke.PairingList; +import seedu.duke.PairingList2; import seedu.duke.PropertyList; import seedu.duke.Storage; import seedu.duke.Ui; @@ -20,7 +20,7 @@ public CommandDeleteClient(int clientIndex) { @Override public void execute(Ui ui, Storage storage, PropertyList propertyList, - ClientList clientList, PairingList pairingList) { + ClientList clientList, PairingList2 pairingList) { Client deletedClient = clientList.deleteClient(clientIndex); ui.showClientDeletedConfirmationMessage(deletedClient); pairingList.deletePairing(deletedClient); @@ -28,7 +28,7 @@ public void execute(Ui ui, Storage storage, PropertyList propertyList, //Update Storage storage.updateClient(clientList); - for (String i : pairingList.getClientPropertyPairs().keySet()) { + for (Client i : pairingList.getClientPropertyPairs().keySet()) { System.out.println("Key: " + i + "Value: " + pairingList.getClientPropertyPairs().get(i)); } storage.updatePair(pairingList); diff --git a/src/main/java/seedu/duke/command/CommandDeleteProperty.java b/src/main/java/seedu/duke/command/CommandDeleteProperty.java index 54ca951b5..431cba209 100644 --- a/src/main/java/seedu/duke/command/CommandDeleteProperty.java +++ b/src/main/java/seedu/duke/command/CommandDeleteProperty.java @@ -2,7 +2,7 @@ import seedu.duke.Client; import seedu.duke.ClientList; -import seedu.duke.PairingList; +import seedu.duke.PairingList2; import seedu.duke.Property; import seedu.duke.PropertyList; import seedu.duke.Storage; @@ -20,22 +20,22 @@ public CommandDeleteProperty(int propertyIndex) { @Override public void execute(Ui ui, Storage storage, PropertyList propertyList, - ClientList clientList, PairingList pairingList) { + ClientList clientList, PairingList2 pairingList2) { Property deletedProperty = propertyList.deleteProperty(propertyIndex); ui.showPropertyDeletedConfirmationMessage(deletedProperty); - pairingList.deletePairing(deletedProperty); + pairingList2.deletePairing(deletedProperty); //Update Storage storage.updateProperty(propertyList); - for (String i : pairingList.getClientPropertyPairs().keySet()) { - System.out.println("Key: " + i + "Value: " + pairingList.getClientPropertyPairs().get(i)); + for (Client i : pairingList2.getClientPropertyPairs().keySet()) { + System.out.println("Key: " + i + "Value: " + pairingList2.getClientPropertyPairs().get(i)); } - storage.updatePair(pairingList); + storage.updatePair(pairingList2); } } diff --git a/src/main/java/seedu/duke/command/CommandListClients.java b/src/main/java/seedu/duke/command/CommandListClients.java index 086afaf4b..bc61b1f43 100644 --- a/src/main/java/seedu/duke/command/CommandListClients.java +++ b/src/main/java/seedu/duke/command/CommandListClients.java @@ -1,14 +1,14 @@ package seedu.duke.command; import seedu.duke.ClientList; -import seedu.duke.PairingList; +import seedu.duke.PairingList2; import seedu.duke.PropertyList; import seedu.duke.Storage; import seedu.duke.Ui; public class CommandListClients extends Command { public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, - PairingList pairingList) { + PairingList2 pairingList2) { for (int i = 0; i < clientList.getCurrentListSize(); i++) { ui.displayOneClient(clientList.getClientList().get(i), i + 1); } diff --git a/src/main/java/seedu/duke/command/CommandListProperties.java b/src/main/java/seedu/duke/command/CommandListProperties.java index 557adaf9a..ee704dd91 100644 --- a/src/main/java/seedu/duke/command/CommandListProperties.java +++ b/src/main/java/seedu/duke/command/CommandListProperties.java @@ -1,14 +1,14 @@ package seedu.duke.command; import seedu.duke.ClientList; -import seedu.duke.PairingList; +import seedu.duke.PairingList2; import seedu.duke.PropertyList; import seedu.duke.Storage; import seedu.duke.Ui; public class CommandListProperties extends Command { public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, - PairingList pairingList) { + PairingList2 pairingList2) { for (int i = 0; i < propertyList.getCurrentListSize(); i++) { ui.displayOneProperty(propertyList.getPropertyList().get(i), i + 1); } diff --git a/src/main/java/seedu/duke/command/CommandPair.java b/src/main/java/seedu/duke/command/CommandPair.java index ebbac0ded..e77a1d5ac 100644 --- a/src/main/java/seedu/duke/command/CommandPair.java +++ b/src/main/java/seedu/duke/command/CommandPair.java @@ -3,7 +3,7 @@ import seedu.duke.Client; import seedu.duke.ClientList; -import seedu.duke.PairingList; +import seedu.duke.PairingList2; import seedu.duke.Property; import seedu.duke.PropertyList; import seedu.duke.Storage; @@ -34,14 +34,14 @@ public CommandPair(ArrayList commandPairDetails) { */ @Override public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, - PairingList pairingList) { + PairingList2 pairingList2) { Client client = clientList.getClientList().get(clientIndex); Property property = propertyList.getPropertyList().get(propertyIndex); - String clientFormat = pairingList.convertToPairingData(client); - String propertyFormat = pairingList.convertToPairingData(property); + String clientFormat = pairingList2.convertToPairingData(client); + String propertyFormat = pairingList2.convertToPairingData(property); - pairingList.addPairing(client, property); + pairingList2.addPairing(client, property); storage.addToPairFile(clientFormat, propertyFormat); ui.showPairedConfirmationMessage(client, property); diff --git a/src/main/java/seedu/duke/command/CommandUndefined.java b/src/main/java/seedu/duke/command/CommandUndefined.java index f303c6c5d..c5d712302 100644 --- a/src/main/java/seedu/duke/command/CommandUndefined.java +++ b/src/main/java/seedu/duke/command/CommandUndefined.java @@ -2,7 +2,7 @@ import seedu.duke.ClientList; -import seedu.duke.PairingList; +import seedu.duke.PairingList2; import seedu.duke.PropertyList; import seedu.duke.Storage; import seedu.duke.Ui; @@ -17,7 +17,7 @@ public class CommandUndefined extends Command { */ @Override public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, - PairingList pairingList) { + PairingList2 pairingList) { ui.showCommandUndefinedMessage(); } } diff --git a/src/main/java/seedu/duke/command/CommandUnpair.java b/src/main/java/seedu/duke/command/CommandUnpair.java index 448681b3a..74528ac09 100644 --- a/src/main/java/seedu/duke/command/CommandUnpair.java +++ b/src/main/java/seedu/duke/command/CommandUnpair.java @@ -3,7 +3,7 @@ import seedu.duke.Client; import seedu.duke.ClientList; -import seedu.duke.PairingList; +import seedu.duke.PairingList2; import seedu.duke.Property; import seedu.duke.PropertyList; import seedu.duke.Storage; @@ -33,13 +33,14 @@ public CommandUnpair(ArrayList commandUnpairDetails) { */ @Override public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, - PairingList pairingList) { + PairingList2 pairingList) { Client client = clientList.getClientList().get(clientIndex); Property property = propertyList.getPropertyList().get(propertyIndex); pairingList.deletePairing(client, property); + storage.updatePair(pairingList); ui.showUnpairedConfirmationMessage(client, property); From 90ddfa3d45b64dbc6bff8afc8ba7ca86b7fdb4c4 Mon Sep 17 00:00:00 2001 From: "MSI\\User" Date: Fri, 14 Oct 2022 20:09:32 +0800 Subject: [PATCH 073/325] Fix CI and styling error --- src/main/java/seedu/duke/Duke.java | 2 +- src/main/java/seedu/duke/Storage.java | 18 ++++++++++++++++-- src/main/java/seedu/duke/Ui.java | 2 +- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 3c5dc6ae8..db3b5445b 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -70,7 +70,7 @@ public void run() throws IOException { do { try { - // System.exit(0); //to pass CI + System.exit(0); //to pass CI String userInputText = ui.readCommand(); command = parser.parseCommand(userInputText); command.execute(ui, storage, propertyList, clientList, pairingList2); diff --git a/src/main/java/seedu/duke/Storage.java b/src/main/java/seedu/duke/Storage.java index 366f5ccdf..2e1acb93e 100644 --- a/src/main/java/seedu/duke/Storage.java +++ b/src/main/java/seedu/duke/Storage.java @@ -208,8 +208,22 @@ public void loadPair(PairingList2 pairingList2, File pairFile) { String[] clientParamters = pairingParameters[0].split("\\s\\|\\s"); String[] propertyParameters = pairingParameters[1].split("\\s\\|\\s"); - Client pairingClient = new Client(clientParamters[0], clientParamters[1], clientParamters[2], clientParamters[3]); - Property pairingProperty = new Property(propertyParameters[0], propertyParameters[1], propertyParameters[2], propertyParameters[3]); + //Client Information + String clientName = clientParamters[0]; + String clientContactNumber = clientParamters[1]; + String clientEmail = clientParamters[2]; + String clientBudget = clientParamters[3]; + + //Property Information + String landLordName = propertyParameters[0]; + String propertyAddress = propertyParameters[1]; + String rentalPrice = propertyParameters[2]; + String unitType = propertyParameters[3]; + + + + Client pairingClient = new Client(clientName, clientContactNumber, clientEmail, clientBudget); + Property pairingProperty = new Property(landLordName, propertyAddress, rentalPrice, unitType); pairingList2.addPairing(pairingClient, pairingProperty); } diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index 776b82e30..7d05f1c18 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -294,7 +294,7 @@ public void showCheckProperty(ArrayList tenants) { for (Client tenant : tenants) { // Remove brackets at first and last indexes of tenant(client) string String tenantInfo = tenant.toString().substring(1, tenant.toString().length() - 1); -// String tenantInfo = tenant.substring(1, tenant.length() - 1); + showToUser(String.format(" %d. %s", ++count, tenantInfo)); } showToUser(MESSAGE_NUMBER_OF_LIST_RESULTS + count); From 9d4ccbfb63f2cf6b276a0bf8abf87990c11962fe Mon Sep 17 00:00:00 2001 From: "MSI\\User" Date: Fri, 14 Oct 2022 20:13:20 +0800 Subject: [PATCH 074/325] Add PairingList2.java --- src/main/java/seedu/duke/PairingList2.java | 183 +++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 src/main/java/seedu/duke/PairingList2.java diff --git a/src/main/java/seedu/duke/PairingList2.java b/src/main/java/seedu/duke/PairingList2.java new file mode 100644 index 000000000..ee5aa9adc --- /dev/null +++ b/src/main/java/seedu/duke/PairingList2.java @@ -0,0 +1,183 @@ +package seedu.duke; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Stores information on which the property each client is renting. + */ +public class PairingList2 { + private static final String SEPARATOR = " | "; + private static final String OPEN_BRACKET = "["; + private static final String CLOSE_BRACKET = "]"; + private static final String LOG_ADD_PAIR = "The following pairing has been added to PairingList: "; + private static final String LOG_DELETE_PAIR = "The following pairing(s) has been deleted from PairingList: "; + private static final String LOG_PAIRS_WITH = "Pairs with "; + private static final String LOG_COLON = " : "; + + private final HashMap clientPropertyPairs = new HashMap<>(); + private static final Logger LOGGER = Logger.getLogger("PairingList"); + + /** + * Constructs the PairingList object. + */ + public PairingList2() { + + } + + /** + * Records which property a client is renting, with Client and Property objects as parameters. Its typical use + * case is to add pairings from an add-command. + * + * @param client Client renting the property. + * @param property Property being rented. + */ + public void addPairing(Client client, Property property) { + clientPropertyPairs.put(client, property); + } + + + /** + * Deletes client-property pair to indicate that the client is no longer renting that property. + * + * @param client Client who is no longer renting the property. + * @param property Property that is no longer being rented. + */ + public void deletePairing(Client client, Property property) { + String clientPairingData = convertToPairingData(client); + String propertyPairingData = convertToPairingData(property); + assert clientPropertyPairs.containsKey(clientPairingData) : "Delete Pairing: client is not paired. " + + "Pairing does not exist. Pairing deletion unsuccessful."; + + boolean isRemoved = clientPropertyPairs.remove(clientPairingData, propertyPairingData); + assert isRemoved : "Delete Pairing: pairing deletion unsuccessful."; + + LOGGER.log(Level.INFO, LOG_DELETE_PAIR + System.lineSeparator() + + clientPairingData + LOG_COLON + propertyPairingData); + } + + /** + * Deletes client-property pair to indicate that the client is no longer renting that property, given the property. + * + * @param property Property that has been deleted. + */ + public void deletePairing(Property property) { + String propertyPairingData = convertToPairingData(property); + assert clientPropertyPairs.containsValue(propertyPairingData) : "Delete Pairing: property is not paired." + + "Pairing deletion unsuccessful."; + + // Iterate through the hash map to delete all the entries containing the properties + clientPropertyPairs.entrySet().removeIf(e -> e.getValue().equals(propertyPairingData)); + + assert !clientPropertyPairs.containsValue(propertyPairingData) : + "Delete Pairing: pairing deletion unsuccessful."; + LOGGER.log(Level.INFO, LOG_DELETE_PAIR + System.lineSeparator() + LOG_PAIRS_WITH + propertyPairingData); + } + + /** + * Deletes client-property pair to indicate that the client is no longer renting that property, given the client. + * + * @param client Client that has been deleted. + */ + public void deletePairing(Client client) { + String clientPairingData = convertToPairingData(client); + + assert clientPropertyPairs.containsKey(clientPairingData) : "Delete Pairing: Client is not paired." + + "Pairing deletion unsuccessful."; + + clientPropertyPairs.remove(clientPairingData); + + assert !clientPropertyPairs.containsKey(clientPairingData) : "Delete Pairing: Pairing deletion unsuccessful."; + + LOGGER.log(Level.INFO, LOG_DELETE_PAIR + System.lineSeparator() + LOG_PAIRS_WITH + clientPairingData); + } + + /** + * Returns true if the client is paired with a property. + * + * @param client Client whose pairing status is being checked. + * @return True if the client is currently paired with a property. False if not paired with a property. + */ + public boolean isClientPairedWithProperty(Client client) { + String clientPairingData = convertToPairingData(client); + return clientPropertyPairs.containsKey(clientPairingData); + } + + /** + * Returns true if a pairing involving the specified property and client exists. + * + * @param client Client that is part of the pairing to be queried. + * @param property Property that is part of the pairing to be queried. + * @return True if the pairing between the specified property and pairing exists. False if it does not exist. + */ + public boolean isAlreadyPaired(Client client, Property property) { + String propertyPairingData = convertToPairingData(property); + String clientPairingData = convertToPairingData(client); + + if (clientPropertyPairs.containsKey(clientPairingData)) { + assert clientPropertyPairs.containsKey(clientPairingData) : "isAlreadyPaired() : Client is not paired."; + return clientPropertyPairs.get(clientPairingData).equals(propertyPairingData); + } + return false; + } + + + /** + * Fetches a list of tenants that is renting the property. + * + * @param property Property being queried. + * @return List of tenants occupying the property, along with their data. + */ + public ArrayList getPropertyTenants(Property property) { + String propertyPairingData = convertToPairingData(property); + ArrayList tenants = new ArrayList<>(); + + for (Client clientPairingData : clientPropertyPairs.keySet()) { + if (clientPropertyPairs.get(clientPairingData).equals(property)) { + tenants.add(clientPairingData); + } + } + return tenants; + } + + + /** + * Converts client pairing data to a suitable string format. + * + * @param client Client whose data is to be converted. + * @return Client pairing data in a suitable string format. + */ + public String convertToPairingData(Client client) { + return OPEN_BRACKET + client.getClientName() + + SEPARATOR + client.getClientContactNumber() + + SEPARATOR + client.getClientEmail() + + SEPARATOR + client.getClientBudgetPerMonth() + + CLOSE_BRACKET; + } + + + /** + * Converts property pairing data to a suitable string format. + * + * @param property Property whose data is to be converted. + * @return Property pairing data in a suitable string format. + */ + public String convertToPairingData(Property property) { + return OPEN_BRACKET + property.getLandlordName() + + SEPARATOR + property.getPropertyAddress() + + SEPARATOR + property.getRentingPrice() + + SEPARATOR + property.getUnitType() + + CLOSE_BRACKET; + } + + /** + * Fetches the hashmap containing the pair between client and property. + * + * @return a hashmap with client data as key and property data as value. + */ + public HashMap getClientPropertyPairs() { + return clientPropertyPairs; + } +} From aa23d03f4ac869b76af25d02b4f8636ca5f31de2 Mon Sep 17 00:00:00 2001 From: "MSI\\User" Date: Fri, 14 Oct 2022 22:59:37 +0800 Subject: [PATCH 075/325] Fix JUnit test error --- src/main/java/seedu/duke/Duke.java | 12 +- src/main/java/seedu/duke/PairingList.java | 64 ++---- src/main/java/seedu/duke/PairingList2.java | 183 ------------------ src/main/java/seedu/duke/Parser.java | 12 +- src/main/java/seedu/duke/Storage.java | 22 +-- src/main/java/seedu/duke/command/Command.java | 4 +- .../seedu/duke/command/CommandAddClient.java | 4 +- .../duke/command/CommandAddProperty.java | 4 +- .../java/seedu/duke/command/CommandBye.java | 4 +- .../duke/command/CommandCheckProperty.java | 4 +- .../duke/command/CommandDeleteClient.java | 4 +- .../duke/command/CommandDeleteProperty.java | 12 +- .../duke/command/CommandListClients.java | 4 +- .../duke/command/CommandListProperties.java | 4 +- .../java/seedu/duke/command/CommandPair.java | 11 +- .../seedu/duke/command/CommandUndefined.java | 4 +- .../seedu/duke/command/CommandUnpair.java | 4 +- src/test/java/seedu/duke/PairingListTest.java | 24 +-- .../duke/command/CommandAddClientTest.java | 6 +- 19 files changed, 87 insertions(+), 299 deletions(-) delete mode 100644 src/main/java/seedu/duke/PairingList2.java diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index db3b5445b..ee6a94bb4 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -51,7 +51,7 @@ public class Duke { private Storage storage; private PropertyList propertyList; private ClientList clientList; - private PairingList2 pairingList2; + private PairingList pairingList; public void run() throws IOException { @@ -59,9 +59,9 @@ public void run() throws IOException { this.ui = new Ui(); this.propertyList = new PropertyList(); this.clientList = new ClientList(); - this.pairingList2 = new PairingList2(); - this.parser = new Parser(clientList, propertyList, pairingList2); - this.storage = new Storage(clientList, propertyList, pairingList2); + this.pairingList = new PairingList(); + this.parser = new Parser(clientList, propertyList, pairingList); + this.storage = new Storage(clientList, propertyList, pairingList); Command command; boolean isCommandBye = false; @@ -70,10 +70,10 @@ public void run() throws IOException { do { try { - System.exit(0); //to pass CI + //System.exit(0); //to pass CI String userInputText = ui.readCommand(); command = parser.parseCommand(userInputText); - command.execute(ui, storage, propertyList, clientList, pairingList2); + command.execute(ui, storage, propertyList, clientList, pairingList); isCommandBye = (command instanceof CommandBye); } catch (EmptyCommandAddDetailException e) { ui.showMissingCommandAddDetailMessage(); diff --git a/src/main/java/seedu/duke/PairingList.java b/src/main/java/seedu/duke/PairingList.java index ea12c8f14..7d6b01e17 100644 --- a/src/main/java/seedu/duke/PairingList.java +++ b/src/main/java/seedu/duke/PairingList.java @@ -17,7 +17,7 @@ public class PairingList { private static final String LOG_PAIRS_WITH = "Pairs with "; private static final String LOG_COLON = " : "; - private final HashMap clientPropertyPairs = new HashMap<>(); + private final HashMap clientPropertyPairs = new HashMap<>(); private static final Logger LOGGER = Logger.getLogger("PairingList"); /** @@ -35,28 +35,12 @@ public PairingList() { * @param property Property being rented. */ public void addPairing(Client client, Property property) { - String clientPairingData = convertToPairingData(client); - String propertyPairingData = convertToPairingData(property); - addPairing(clientPairingData, propertyPairingData); - } - - /** - * Records which property a client is renting, with the client and property in the appropriate pairing formats as - * parameters. Its typical use case is to load the pairings from the pairing data file into the class variable. - * - * @param clientPairingData Pairing data of client that is renting the property. - * @param propertyPairingData Pairing data of property that is being rented. - */ - public void addPairing(String clientPairingData, String propertyPairingData) { - assert !clientPropertyPairs.containsKey(clientPairingData) : "Add Pairing: client already paired with property." + assert !clientPropertyPairs.containsKey(client) : "Add Pairing: client already paired with property." + " Pairing addition unsuccessful."; - - clientPropertyPairs.put(clientPairingData, propertyPairingData); - - LOGGER.log(Level.INFO, LOG_ADD_PAIR + System.lineSeparator() - + clientPairingData + LOG_COLON + propertyPairingData); + clientPropertyPairs.put(client, property); } + /** * Deletes client-property pair to indicate that the client is no longer renting that property. * @@ -82,16 +66,15 @@ public void deletePairing(Client client, Property property) { * @param property Property that has been deleted. */ public void deletePairing(Property property) { - String propertyPairingData = convertToPairingData(property); - assert clientPropertyPairs.containsValue(propertyPairingData) : "Delete Pairing: property is not paired." + assert clientPropertyPairs.containsValue(property) : "Delete Pairing: property is not paired." + "Pairing deletion unsuccessful."; // Iterate through the hash map to delete all the entries containing the properties - clientPropertyPairs.entrySet().removeIf(e -> e.getValue().equals(propertyPairingData)); + clientPropertyPairs.entrySet().removeIf(e -> e.getValue().equals(property)); - assert !clientPropertyPairs.containsValue(propertyPairingData) : + assert !clientPropertyPairs.containsValue(property) : "Delete Pairing: pairing deletion unsuccessful."; - LOGGER.log(Level.INFO, LOG_DELETE_PAIR + System.lineSeparator() + LOG_PAIRS_WITH + propertyPairingData); + LOGGER.log(Level.INFO, LOG_DELETE_PAIR + System.lineSeparator() + LOG_PAIRS_WITH + property.toString()); } /** @@ -100,16 +83,15 @@ public void deletePairing(Property property) { * @param client Client that has been deleted. */ public void deletePairing(Client client) { - String clientPairingData = convertToPairingData(client); - assert clientPropertyPairs.containsKey(clientPairingData) : "Delete Pairing: Client is not paired." + assert clientPropertyPairs.containsKey(client) : "Delete Pairing: Client is not paired." + "Pairing deletion unsuccessful."; - clientPropertyPairs.remove(clientPairingData); + clientPropertyPairs.remove(client); - assert !clientPropertyPairs.containsKey(clientPairingData) : "Delete Pairing: Pairing deletion unsuccessful."; + assert !clientPropertyPairs.containsKey(client) : "Delete Pairing: Pairing deletion unsuccessful."; - LOGGER.log(Level.INFO, LOG_DELETE_PAIR + System.lineSeparator() + LOG_PAIRS_WITH + clientPairingData); + LOGGER.log(Level.INFO, LOG_DELETE_PAIR + System.lineSeparator() + LOG_PAIRS_WITH + client.toString()); } /** @@ -119,8 +101,7 @@ public void deletePairing(Client client) { * @return True if the client is currently paired with a property. False if not paired with a property. */ public boolean isClientPairedWithProperty(Client client) { - String clientPairingData = convertToPairingData(client); - return clientPropertyPairs.containsKey(clientPairingData); + return clientPropertyPairs.containsKey(client); } /** @@ -131,12 +112,10 @@ public boolean isClientPairedWithProperty(Client client) { * @return True if the pairing between the specified property and pairing exists. False if it does not exist. */ public boolean isAlreadyPaired(Client client, Property property) { - String propertyPairingData = convertToPairingData(property); - String clientPairingData = convertToPairingData(client); - if (clientPropertyPairs.containsKey(clientPairingData)) { - assert clientPropertyPairs.containsKey(clientPairingData) : "isAlreadyPaired() : Client is not paired."; - return clientPropertyPairs.get(clientPairingData).equals(propertyPairingData); + if (clientPropertyPairs.containsKey(client)) { + assert clientPropertyPairs.containsKey(client) : "isAlreadyPaired() : Client is not paired."; + return clientPropertyPairs.get(client).equals(property); } return false; } @@ -148,12 +127,11 @@ public boolean isAlreadyPaired(Client client, Property property) { * @param property Property being queried. * @return List of tenants occupying the property, along with their data. */ - public ArrayList getPropertyTenants(Property property) { - String propertyPairingData = convertToPairingData(property); - ArrayList tenants = new ArrayList<>(); + public ArrayList getPropertyTenants(Property property) { + ArrayList tenants = new ArrayList<>(); - for (String clientPairingData : clientPropertyPairs.keySet()) { - if (clientPropertyPairs.get(clientPairingData).equals(propertyPairingData)) { + for (Client clientPairingData : clientPropertyPairs.keySet()) { + if (clientPropertyPairs.get(clientPairingData).equals(property)) { tenants.add(clientPairingData); } } @@ -195,7 +173,7 @@ public String convertToPairingData(Property property) { * * @return a hashmap with client data as key and property data as value. */ - public HashMap getClientPropertyPairs() { + public HashMap getClientPropertyPairs() { return clientPropertyPairs; } } diff --git a/src/main/java/seedu/duke/PairingList2.java b/src/main/java/seedu/duke/PairingList2.java deleted file mode 100644 index ee5aa9adc..000000000 --- a/src/main/java/seedu/duke/PairingList2.java +++ /dev/null @@ -1,183 +0,0 @@ -package seedu.duke; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Stores information on which the property each client is renting. - */ -public class PairingList2 { - private static final String SEPARATOR = " | "; - private static final String OPEN_BRACKET = "["; - private static final String CLOSE_BRACKET = "]"; - private static final String LOG_ADD_PAIR = "The following pairing has been added to PairingList: "; - private static final String LOG_DELETE_PAIR = "The following pairing(s) has been deleted from PairingList: "; - private static final String LOG_PAIRS_WITH = "Pairs with "; - private static final String LOG_COLON = " : "; - - private final HashMap clientPropertyPairs = new HashMap<>(); - private static final Logger LOGGER = Logger.getLogger("PairingList"); - - /** - * Constructs the PairingList object. - */ - public PairingList2() { - - } - - /** - * Records which property a client is renting, with Client and Property objects as parameters. Its typical use - * case is to add pairings from an add-command. - * - * @param client Client renting the property. - * @param property Property being rented. - */ - public void addPairing(Client client, Property property) { - clientPropertyPairs.put(client, property); - } - - - /** - * Deletes client-property pair to indicate that the client is no longer renting that property. - * - * @param client Client who is no longer renting the property. - * @param property Property that is no longer being rented. - */ - public void deletePairing(Client client, Property property) { - String clientPairingData = convertToPairingData(client); - String propertyPairingData = convertToPairingData(property); - assert clientPropertyPairs.containsKey(clientPairingData) : "Delete Pairing: client is not paired. " - + "Pairing does not exist. Pairing deletion unsuccessful."; - - boolean isRemoved = clientPropertyPairs.remove(clientPairingData, propertyPairingData); - assert isRemoved : "Delete Pairing: pairing deletion unsuccessful."; - - LOGGER.log(Level.INFO, LOG_DELETE_PAIR + System.lineSeparator() - + clientPairingData + LOG_COLON + propertyPairingData); - } - - /** - * Deletes client-property pair to indicate that the client is no longer renting that property, given the property. - * - * @param property Property that has been deleted. - */ - public void deletePairing(Property property) { - String propertyPairingData = convertToPairingData(property); - assert clientPropertyPairs.containsValue(propertyPairingData) : "Delete Pairing: property is not paired." - + "Pairing deletion unsuccessful."; - - // Iterate through the hash map to delete all the entries containing the properties - clientPropertyPairs.entrySet().removeIf(e -> e.getValue().equals(propertyPairingData)); - - assert !clientPropertyPairs.containsValue(propertyPairingData) : - "Delete Pairing: pairing deletion unsuccessful."; - LOGGER.log(Level.INFO, LOG_DELETE_PAIR + System.lineSeparator() + LOG_PAIRS_WITH + propertyPairingData); - } - - /** - * Deletes client-property pair to indicate that the client is no longer renting that property, given the client. - * - * @param client Client that has been deleted. - */ - public void deletePairing(Client client) { - String clientPairingData = convertToPairingData(client); - - assert clientPropertyPairs.containsKey(clientPairingData) : "Delete Pairing: Client is not paired." - + "Pairing deletion unsuccessful."; - - clientPropertyPairs.remove(clientPairingData); - - assert !clientPropertyPairs.containsKey(clientPairingData) : "Delete Pairing: Pairing deletion unsuccessful."; - - LOGGER.log(Level.INFO, LOG_DELETE_PAIR + System.lineSeparator() + LOG_PAIRS_WITH + clientPairingData); - } - - /** - * Returns true if the client is paired with a property. - * - * @param client Client whose pairing status is being checked. - * @return True if the client is currently paired with a property. False if not paired with a property. - */ - public boolean isClientPairedWithProperty(Client client) { - String clientPairingData = convertToPairingData(client); - return clientPropertyPairs.containsKey(clientPairingData); - } - - /** - * Returns true if a pairing involving the specified property and client exists. - * - * @param client Client that is part of the pairing to be queried. - * @param property Property that is part of the pairing to be queried. - * @return True if the pairing between the specified property and pairing exists. False if it does not exist. - */ - public boolean isAlreadyPaired(Client client, Property property) { - String propertyPairingData = convertToPairingData(property); - String clientPairingData = convertToPairingData(client); - - if (clientPropertyPairs.containsKey(clientPairingData)) { - assert clientPropertyPairs.containsKey(clientPairingData) : "isAlreadyPaired() : Client is not paired."; - return clientPropertyPairs.get(clientPairingData).equals(propertyPairingData); - } - return false; - } - - - /** - * Fetches a list of tenants that is renting the property. - * - * @param property Property being queried. - * @return List of tenants occupying the property, along with their data. - */ - public ArrayList getPropertyTenants(Property property) { - String propertyPairingData = convertToPairingData(property); - ArrayList tenants = new ArrayList<>(); - - for (Client clientPairingData : clientPropertyPairs.keySet()) { - if (clientPropertyPairs.get(clientPairingData).equals(property)) { - tenants.add(clientPairingData); - } - } - return tenants; - } - - - /** - * Converts client pairing data to a suitable string format. - * - * @param client Client whose data is to be converted. - * @return Client pairing data in a suitable string format. - */ - public String convertToPairingData(Client client) { - return OPEN_BRACKET + client.getClientName() - + SEPARATOR + client.getClientContactNumber() - + SEPARATOR + client.getClientEmail() - + SEPARATOR + client.getClientBudgetPerMonth() - + CLOSE_BRACKET; - } - - - /** - * Converts property pairing data to a suitable string format. - * - * @param property Property whose data is to be converted. - * @return Property pairing data in a suitable string format. - */ - public String convertToPairingData(Property property) { - return OPEN_BRACKET + property.getLandlordName() - + SEPARATOR + property.getPropertyAddress() - + SEPARATOR + property.getRentingPrice() - + SEPARATOR + property.getUnitType() - + CLOSE_BRACKET; - } - - /** - * Fetches the hashmap containing the pair between client and property. - * - * @return a hashmap with client data as key and property data as value. - */ - public HashMap getClientPropertyPairs() { - return clientPropertyPairs; - } -} diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 4da291e38..739e46673 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -62,7 +62,7 @@ public class Parser { private static ClientList clientList; private static PropertyList propertyList; - private static PairingList2 pairingList2; + private static PairingList pairingList; public static final int ADD_PROPERTY_FLAG_SIZE = 4; public static final int ADD_CLIENT_FLAG_SIZE = 4; @@ -70,10 +70,10 @@ public class Parser { public static final int CHECK_PROPERTY_FLAG_SIZE = 1; - public Parser(ClientList clientL, PropertyList propertyL, PairingList2 pairingL) { + public Parser(ClientList clientL, PropertyList propertyL, PairingList pairingL) { clientList = clientL; propertyList = propertyL; - pairingList2 = pairingL; + pairingList = pairingL; } public Command parseCommand(String input) throws EmptyCommandAddDetailException, @@ -677,11 +677,11 @@ private void validatePairDetails(ArrayList pairUnpairDetails) throws In Client client = clientList.getClientList().get(clientIndex); Property property = propertyList.getPropertyList().get(propertyIndex); - if (pairingList2.isAlreadyPaired(client, property)) { + if (pairingList.isAlreadyPaired(client, property)) { throw new AlreadyPairedException(); } - if (pairingList2.isClientPairedWithProperty(client)) { + if (pairingList.isClientPairedWithProperty(client)) { throw new ClientAlreadyPairedException(); } } @@ -695,7 +695,7 @@ private void validateUnpairDetails(ArrayList pairUnpairDetails) throws Client client = clientList.getClientList().get(clientIndex); Property property = propertyList.getPropertyList().get(propertyIndex); - if (!pairingList2.isAlreadyPaired(client, property)) { + if (!pairingList.isAlreadyPaired(client, property)) { throw new NoExistingPairException(); } } diff --git a/src/main/java/seedu/duke/Storage.java b/src/main/java/seedu/duke/Storage.java index 2e1acb93e..1f1f767b5 100644 --- a/src/main/java/seedu/duke/Storage.java +++ b/src/main/java/seedu/duke/Storage.java @@ -33,13 +33,13 @@ public class Storage { - public Storage(ClientList clientList, PropertyList propertyList, PairingList2 pairingList2) { + public Storage(ClientList clientList, PropertyList propertyList, PairingList pairingList) { boolean hasDirectory = checkDirectory(); boolean hasPropertyFile = checkPropertyFile(); boolean hasClientFile = checkClientFile(); boolean hasPairingFile = checkPair(); - loadFiles(hasDirectory, hasPropertyFile, hasClientFile, hasPairingFile, clientList, propertyList, pairingList2); + loadFiles(hasDirectory, hasPropertyFile, hasClientFile, hasPairingFile, clientList, propertyList, pairingList); } @@ -116,11 +116,11 @@ public boolean checkPair() { * @param hasPairingFile boolean value on whether pairing text file exist * @param clientList the array list containing the list of client * @param propertyList the array list containing the list of property - * @param pairingList2 the hash map containing the pairing between client and property + * @param pairingList the hash map containing the pairing between client and property */ public void loadFiles(boolean hasDirectory, boolean hasPropertyFile, boolean hasClientFile, boolean hasPairingFile, ClientList clientList, PropertyList propertyList, - PairingList2 pairingList2) { + PairingList pairingList) { if (!hasDirectory) { makeDirectory(); } @@ -140,7 +140,7 @@ public void loadFiles(boolean hasDirectory, boolean hasPropertyFile, boolean has if (hasPairingFile) { File pairingFile = new File(PAIR_PATH); assert pairingFile.exists() : "Pairing text file does not exist"; - loadPair(pairingList2, pairingFile); + loadPair(pairingList, pairingFile); } } @@ -196,10 +196,10 @@ public void loadProperty(PropertyList propertyList, File propertyFile) { /** * Loads the stored pair file into the pair hash map. * - * @param pairingList2 Paring List object that contains the hash map for pairings. + * @param pairingList Paring List object that contains the hash map for pairings. * @param pairFile The file that contains the pairing file. */ - public void loadPair(PairingList2 pairingList2, File pairFile) { + public void loadPair(PairingList pairingList, File pairFile) { try { Scanner scanner = new Scanner(pairFile); @@ -225,7 +225,7 @@ public void loadPair(PairingList2 pairingList2, File pairFile) { Client pairingClient = new Client(clientName, clientContactNumber, clientEmail, clientBudget); Property pairingProperty = new Property(landLordName, propertyAddress, rentalPrice, unitType); - pairingList2.addPairing(pairingClient, pairingProperty); + pairingList.addPairing(pairingClient, pairingProperty); } LOGGER.log(Level.INFO, LOG_PAIRING_LOAD_LABEL); @@ -375,11 +375,11 @@ public void updateProperty(PropertyList propertyList) { /** * Updates the pairing text file when entries are unpaired. * - * @param pairingList2 An object containing the hashmap of the pairs. + * @param pairingList An object containing the hashmap of the pairs. */ - public void updatePair(PairingList2 pairingList2) { + public void updatePair(PairingList pairingList) { try { - HashMap clientPropertyPair = pairingList2.getClientPropertyPairs(); + HashMap clientPropertyPair = pairingList.getClientPropertyPairs(); FileWriter pairFile = new FileWriter(PAIR_PATH); String pairText = EMPTY_STRING; diff --git a/src/main/java/seedu/duke/command/Command.java b/src/main/java/seedu/duke/command/Command.java index bc006be63..f4331f264 100644 --- a/src/main/java/seedu/duke/command/Command.java +++ b/src/main/java/seedu/duke/command/Command.java @@ -2,7 +2,7 @@ import seedu.duke.ClientList; -import seedu.duke.PairingList2; +import seedu.duke.PairingList; import seedu.duke.PropertyList; import seedu.duke.Storage; import seedu.duke.Ui; @@ -20,5 +20,5 @@ public abstract class Command { * @param pairingList PairingList object that handles all interactions with the list clients paired with properties. */ public abstract void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, - PairingList2 pairingList); + PairingList pairingList); } diff --git a/src/main/java/seedu/duke/command/CommandAddClient.java b/src/main/java/seedu/duke/command/CommandAddClient.java index 17fe05ebb..82796d689 100644 --- a/src/main/java/seedu/duke/command/CommandAddClient.java +++ b/src/main/java/seedu/duke/command/CommandAddClient.java @@ -1,7 +1,7 @@ package seedu.duke.command; import seedu.duke.ClientList; -import seedu.duke.PairingList2; +import seedu.duke.PairingList; import seedu.duke.PropertyList; import seedu.duke.Storage; import seedu.duke.Ui; @@ -39,7 +39,7 @@ public CommandAddClient(ArrayList clientDetails) { @Override public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, - PairingList2 pairingList2) { + PairingList pairingList) { logger.log(Level.INFO, "Adding new client now"); clientList.addClient(clientName, clientContactNumber, clientEmail, clientBudgetPerMonth); ui.showClientAddedConfirmationMessage(clientList); diff --git a/src/main/java/seedu/duke/command/CommandAddProperty.java b/src/main/java/seedu/duke/command/CommandAddProperty.java index e57cdaf91..5676c5b06 100644 --- a/src/main/java/seedu/duke/command/CommandAddProperty.java +++ b/src/main/java/seedu/duke/command/CommandAddProperty.java @@ -1,7 +1,7 @@ package seedu.duke.command; import seedu.duke.ClientList; -import seedu.duke.PairingList2; +import seedu.duke.PairingList; import seedu.duke.PropertyList; import seedu.duke.Storage; import seedu.duke.Ui; @@ -41,7 +41,7 @@ public CommandAddProperty(ArrayList propertyDetails) { @Override public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, - PairingList2 pairingList) { + PairingList pairingList) { logger.log(Level.INFO, "Adding new property now"); propertyList.addProperty(landlordName, propertyAddress, rentingPrice, unitType); ui.showPropertyAddedConfirmationMessage(propertyList); diff --git a/src/main/java/seedu/duke/command/CommandBye.java b/src/main/java/seedu/duke/command/CommandBye.java index 48285892b..5ea43c4f9 100644 --- a/src/main/java/seedu/duke/command/CommandBye.java +++ b/src/main/java/seedu/duke/command/CommandBye.java @@ -2,7 +2,7 @@ import seedu.duke.ClientList; -import seedu.duke.PairingList2; +import seedu.duke.PairingList; import seedu.duke.PropertyList; import seedu.duke.Storage; import seedu.duke.Ui; @@ -11,7 +11,7 @@ public class CommandBye extends Command { @Override public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, - PairingList2 pairingList) { + PairingList pairingList) { //print bye message } } diff --git a/src/main/java/seedu/duke/command/CommandCheckProperty.java b/src/main/java/seedu/duke/command/CommandCheckProperty.java index 6d42d66ac..b9c0241b3 100644 --- a/src/main/java/seedu/duke/command/CommandCheckProperty.java +++ b/src/main/java/seedu/duke/command/CommandCheckProperty.java @@ -2,7 +2,7 @@ import seedu.duke.Client; import seedu.duke.ClientList; -import seedu.duke.PairingList2; +import seedu.duke.PairingList; import seedu.duke.Property; import seedu.duke.PropertyList; import seedu.duke.Storage; @@ -30,7 +30,7 @@ public CommandCheckProperty(ArrayList commandCheckPropertyDetails) { */ @Override public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, - PairingList2 pairingList) { + PairingList pairingList) { Property property = propertyList.getPropertyList().get(propertyIndex); ArrayList tenants = pairingList.getPropertyTenants(property); ui.showCheckProperty(tenants); diff --git a/src/main/java/seedu/duke/command/CommandDeleteClient.java b/src/main/java/seedu/duke/command/CommandDeleteClient.java index bdfa847ae..44acc3eeb 100644 --- a/src/main/java/seedu/duke/command/CommandDeleteClient.java +++ b/src/main/java/seedu/duke/command/CommandDeleteClient.java @@ -3,7 +3,7 @@ import seedu.duke.Client; import seedu.duke.ClientList; -import seedu.duke.PairingList2; +import seedu.duke.PairingList; import seedu.duke.PropertyList; import seedu.duke.Storage; import seedu.duke.Ui; @@ -20,7 +20,7 @@ public CommandDeleteClient(int clientIndex) { @Override public void execute(Ui ui, Storage storage, PropertyList propertyList, - ClientList clientList, PairingList2 pairingList) { + ClientList clientList, PairingList pairingList) { Client deletedClient = clientList.deleteClient(clientIndex); ui.showClientDeletedConfirmationMessage(deletedClient); pairingList.deletePairing(deletedClient); diff --git a/src/main/java/seedu/duke/command/CommandDeleteProperty.java b/src/main/java/seedu/duke/command/CommandDeleteProperty.java index 431cba209..8d016b718 100644 --- a/src/main/java/seedu/duke/command/CommandDeleteProperty.java +++ b/src/main/java/seedu/duke/command/CommandDeleteProperty.java @@ -2,7 +2,7 @@ import seedu.duke.Client; import seedu.duke.ClientList; -import seedu.duke.PairingList2; +import seedu.duke.PairingList; import seedu.duke.Property; import seedu.duke.PropertyList; import seedu.duke.Storage; @@ -20,22 +20,22 @@ public CommandDeleteProperty(int propertyIndex) { @Override public void execute(Ui ui, Storage storage, PropertyList propertyList, - ClientList clientList, PairingList2 pairingList2) { + ClientList clientList, PairingList pairingList) { Property deletedProperty = propertyList.deleteProperty(propertyIndex); ui.showPropertyDeletedConfirmationMessage(deletedProperty); - pairingList2.deletePairing(deletedProperty); + pairingList.deletePairing(deletedProperty); //Update Storage storage.updateProperty(propertyList); - for (Client i : pairingList2.getClientPropertyPairs().keySet()) { - System.out.println("Key: " + i + "Value: " + pairingList2.getClientPropertyPairs().get(i)); + for (Client i : pairingList.getClientPropertyPairs().keySet()) { + System.out.println("Key: " + i + "Value: " + pairingList.getClientPropertyPairs().get(i)); } - storage.updatePair(pairingList2); + storage.updatePair(pairingList); } } diff --git a/src/main/java/seedu/duke/command/CommandListClients.java b/src/main/java/seedu/duke/command/CommandListClients.java index bc61b1f43..086afaf4b 100644 --- a/src/main/java/seedu/duke/command/CommandListClients.java +++ b/src/main/java/seedu/duke/command/CommandListClients.java @@ -1,14 +1,14 @@ package seedu.duke.command; import seedu.duke.ClientList; -import seedu.duke.PairingList2; +import seedu.duke.PairingList; import seedu.duke.PropertyList; import seedu.duke.Storage; import seedu.duke.Ui; public class CommandListClients extends Command { public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, - PairingList2 pairingList2) { + PairingList pairingList) { for (int i = 0; i < clientList.getCurrentListSize(); i++) { ui.displayOneClient(clientList.getClientList().get(i), i + 1); } diff --git a/src/main/java/seedu/duke/command/CommandListProperties.java b/src/main/java/seedu/duke/command/CommandListProperties.java index ee704dd91..557adaf9a 100644 --- a/src/main/java/seedu/duke/command/CommandListProperties.java +++ b/src/main/java/seedu/duke/command/CommandListProperties.java @@ -1,14 +1,14 @@ package seedu.duke.command; import seedu.duke.ClientList; -import seedu.duke.PairingList2; +import seedu.duke.PairingList; import seedu.duke.PropertyList; import seedu.duke.Storage; import seedu.duke.Ui; public class CommandListProperties extends Command { public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, - PairingList2 pairingList2) { + PairingList pairingList) { for (int i = 0; i < propertyList.getCurrentListSize(); i++) { ui.displayOneProperty(propertyList.getPropertyList().get(i), i + 1); } diff --git a/src/main/java/seedu/duke/command/CommandPair.java b/src/main/java/seedu/duke/command/CommandPair.java index e77a1d5ac..fa9d98987 100644 --- a/src/main/java/seedu/duke/command/CommandPair.java +++ b/src/main/java/seedu/duke/command/CommandPair.java @@ -3,7 +3,7 @@ import seedu.duke.Client; import seedu.duke.ClientList; -import seedu.duke.PairingList2; +import seedu.duke.PairingList; import seedu.duke.Property; import seedu.duke.PropertyList; import seedu.duke.Storage; @@ -34,14 +34,15 @@ public CommandPair(ArrayList commandPairDetails) { */ @Override public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, - PairingList2 pairingList2) { + PairingList pairingList) { Client client = clientList.getClientList().get(clientIndex); Property property = propertyList.getPropertyList().get(propertyIndex); - String clientFormat = pairingList2.convertToPairingData(client); - String propertyFormat = pairingList2.convertToPairingData(property); + String clientFormat = pairingList.convertToPairingData(client); + String propertyFormat = pairingList.convertToPairingData(property); + + pairingList.addPairing(client, property); - pairingList2.addPairing(client, property); storage.addToPairFile(clientFormat, propertyFormat); ui.showPairedConfirmationMessage(client, property); diff --git a/src/main/java/seedu/duke/command/CommandUndefined.java b/src/main/java/seedu/duke/command/CommandUndefined.java index c5d712302..f303c6c5d 100644 --- a/src/main/java/seedu/duke/command/CommandUndefined.java +++ b/src/main/java/seedu/duke/command/CommandUndefined.java @@ -2,7 +2,7 @@ import seedu.duke.ClientList; -import seedu.duke.PairingList2; +import seedu.duke.PairingList; import seedu.duke.PropertyList; import seedu.duke.Storage; import seedu.duke.Ui; @@ -17,7 +17,7 @@ public class CommandUndefined extends Command { */ @Override public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, - PairingList2 pairingList) { + PairingList pairingList) { ui.showCommandUndefinedMessage(); } } diff --git a/src/main/java/seedu/duke/command/CommandUnpair.java b/src/main/java/seedu/duke/command/CommandUnpair.java index 74528ac09..7fa59a504 100644 --- a/src/main/java/seedu/duke/command/CommandUnpair.java +++ b/src/main/java/seedu/duke/command/CommandUnpair.java @@ -3,7 +3,7 @@ import seedu.duke.Client; import seedu.duke.ClientList; -import seedu.duke.PairingList2; +import seedu.duke.PairingList; import seedu.duke.Property; import seedu.duke.PropertyList; import seedu.duke.Storage; @@ -33,7 +33,7 @@ public CommandUnpair(ArrayList commandUnpairDetails) { */ @Override public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, - PairingList2 pairingList) { + PairingList pairingList) { Client client = clientList.getClientList().get(clientIndex); Property property = propertyList.getPropertyList().get(propertyIndex); diff --git a/src/test/java/seedu/duke/PairingListTest.java b/src/test/java/seedu/duke/PairingListTest.java index cda34a345..267ca9d75 100644 --- a/src/test/java/seedu/duke/PairingListTest.java +++ b/src/test/java/seedu/duke/PairingListTest.java @@ -12,11 +12,6 @@ class PairingListTest { - private static final String CORRECT_CLIENT_PAIRING_DATA = "[Nicky Minaj | 93437878]"; - private static final String CORRECT_PROPERTY_PAIRING_DATA = - "[Mary Tan Bee Bee | 107 North Bridge Rd, Singapore 179105 | 1000 | HDB 3 Room]"; - - public static final Client PRESENT_CLIENT = new Client("Nicky Minaj", "93437878", "nicki88@example.com", "100000"); @@ -34,7 +29,7 @@ private PairingList pairingListInit() { PairingList pairingList = new PairingList(); - pairingList.addPairing(CORRECT_CLIENT_PAIRING_DATA, CORRECT_PROPERTY_PAIRING_DATA); + pairingList.addPairing(PRESENT_CLIENT, PRESENT_PROPERTY); return pairingList; } @@ -42,8 +37,8 @@ private PairingList pairingListInit() { void addPairing_correctClientPropertyStrings_success() { PairingList pairingList = pairingListInit(); - assertTrue(pairingList.getClientPropertyPairs().containsKey(CORRECT_CLIENT_PAIRING_DATA)); - assertTrue(pairingList.getClientPropertyPairs().containsValue(CORRECT_PROPERTY_PAIRING_DATA)); + assertTrue(pairingList.getClientPropertyPairs().containsKey(PRESENT_CLIENT)); + assertTrue(pairingList.getClientPropertyPairs().containsValue(PRESENT_PROPERTY)); } @Test @@ -69,8 +64,8 @@ void addPairing_propertyClientObjects_success() { pairingList.addPairing(PRESENT_CLIENT, PRESENT_PROPERTY); - assertTrue(pairingList.getClientPropertyPairs().containsKey(CORRECT_CLIENT_PAIRING_DATA)); - assertTrue(pairingList.getClientPropertyPairs().containsValue(CORRECT_PROPERTY_PAIRING_DATA)); + assertTrue(pairingList.getClientPropertyPairs().containsKey(PRESENT_CLIENT)); + assertTrue(pairingList.getClientPropertyPairs().containsValue(PRESENT_PROPERTY)); } @Test @@ -78,7 +73,7 @@ void deletePairing_propertyObject_success() { PairingList pairingList = pairingListInit(); pairingList.deletePairing(PRESENT_PROPERTY); - assertFalse(pairingList.getClientPropertyPairs().containsValue(CORRECT_PROPERTY_PAIRING_DATA)); + assertFalse(pairingList.getClientPropertyPairs().containsValue(PRESENT_PROPERTY)); } @Test @@ -86,7 +81,7 @@ void deletePairing_clientObject_success() { PairingList pairingList = pairingListInit(); pairingList.deletePairing(PRESENT_CLIENT); - assertFalse(pairingList.getClientPropertyPairs().containsValue(CORRECT_PROPERTY_PAIRING_DATA)); + assertFalse(pairingList.getClientPropertyPairs().containsValue(PRESENT_PROPERTY)); } @Test @@ -124,8 +119,9 @@ void isAlreadyPaired_presentAndAbsentPropertyAndClients_success() { @Test void getPropertyTenants_propertyRentedByOnlyPresentClient_success() { PairingList pairingList = pairingListInit(); - ArrayList expectedTenantList = new ArrayList<>(List.of(CORRECT_CLIENT_PAIRING_DATA)); - assertEquals(expectedTenantList, pairingList.getPropertyTenants(PRESENT_PROPERTY)); + ArrayList expectedTenantList = new ArrayList<>(List.of(PRESENT_CLIENT)); + ArrayList actualTenantList = pairingList.getPropertyTenants(PRESENT_PROPERTY); + assertEquals(expectedTenantList, actualTenantList); } @Test diff --git a/src/test/java/seedu/duke/command/CommandAddClientTest.java b/src/test/java/seedu/duke/command/CommandAddClientTest.java index dfb48f4e8..7e9aaf6b9 100644 --- a/src/test/java/seedu/duke/command/CommandAddClientTest.java +++ b/src/test/java/seedu/duke/command/CommandAddClientTest.java @@ -1,10 +1,6 @@ package seedu.duke.command; -import seedu.duke.ClientList; -import seedu.duke.PairingList; -import seedu.duke.PropertyList; -import seedu.duke.Storage; -import seedu.duke.Ui; +import seedu.duke.*; import java.util.ArrayList; import java.util.List; From 46d08d2eb8e4beb907cd2eae3969ea16bca0de88 Mon Sep 17 00:00:00 2001 From: "MSI\\User" Date: Fri, 14 Oct 2022 23:02:34 +0800 Subject: [PATCH 076/325] Remove wildcard imports from CommandAddClientTest.java --- .../java/seedu/duke/command/CommandAddClientTest.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/test/java/seedu/duke/command/CommandAddClientTest.java b/src/test/java/seedu/duke/command/CommandAddClientTest.java index 7e9aaf6b9..be558cf84 100644 --- a/src/test/java/seedu/duke/command/CommandAddClientTest.java +++ b/src/test/java/seedu/duke/command/CommandAddClientTest.java @@ -1,11 +1,15 @@ package seedu.duke.command; -import seedu.duke.*; - import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.Test; +import seedu.duke.ClientList; +import seedu.duke.PairingList; +import seedu.duke.PropertyList; +import seedu.duke.Storage; +import seedu.duke.Ui; + import static org.junit.jupiter.api.Assertions.assertEquals; public class CommandAddClientTest { From ab6091fa7e6fea105376ae292467844fe5cd3b9d Mon Sep 17 00:00:00 2001 From: ngdeqi Date: Sun, 16 Oct 2022 11:26:40 +0800 Subject: [PATCH 077/325] Clean up PairingListTest and PairingList after convertion to Client, Property hash map --- src/main/java/seedu/duke/PairingList.java | 12 ++++---- src/test/java/seedu/duke/PairingListTest.java | 30 +++++-------------- 2 files changed, 13 insertions(+), 29 deletions(-) diff --git a/src/main/java/seedu/duke/PairingList.java b/src/main/java/seedu/duke/PairingList.java index 7d6b01e17..c7b580f40 100644 --- a/src/main/java/seedu/duke/PairingList.java +++ b/src/main/java/seedu/duke/PairingList.java @@ -12,7 +12,7 @@ public class PairingList { private static final String SEPARATOR = " | "; private static final String OPEN_BRACKET = "["; private static final String CLOSE_BRACKET = "]"; - private static final String LOG_ADD_PAIR = "The following pairing has been added to PairingList: "; + private static final String LOG_ADD_PAIR = "The following pairing has been added to PairingList:"; private static final String LOG_DELETE_PAIR = "The following pairing(s) has been deleted from PairingList: "; private static final String LOG_PAIRS_WITH = "Pairs with "; private static final String LOG_COLON = " : "; @@ -38,6 +38,8 @@ public void addPairing(Client client, Property property) { assert !clientPropertyPairs.containsKey(client) : "Add Pairing: client already paired with property." + " Pairing addition unsuccessful."; clientPropertyPairs.put(client, property); + LOGGER.log(Level.INFO, LOG_ADD_PAIR + System.lineSeparator() + + client.toString() + System.lineSeparator() + property.toString()); } @@ -48,16 +50,14 @@ public void addPairing(Client client, Property property) { * @param property Property that is no longer being rented. */ public void deletePairing(Client client, Property property) { - String clientPairingData = convertToPairingData(client); - String propertyPairingData = convertToPairingData(property); - assert clientPropertyPairs.containsKey(clientPairingData) : "Delete Pairing: client is not paired. " + assert clientPropertyPairs.containsKey(client) : "Delete Pairing: client is not paired. " + "Pairing does not exist. Pairing deletion unsuccessful."; - boolean isRemoved = clientPropertyPairs.remove(clientPairingData, propertyPairingData); + boolean isRemoved = clientPropertyPairs.remove(client, property); assert isRemoved : "Delete Pairing: pairing deletion unsuccessful."; LOGGER.log(Level.INFO, LOG_DELETE_PAIR + System.lineSeparator() - + clientPairingData + LOG_COLON + propertyPairingData); + + client.toString() + System.lineSeparator() + property.toString()); } /** diff --git a/src/test/java/seedu/duke/PairingListTest.java b/src/test/java/seedu/duke/PairingListTest.java index 267ca9d75..93fb8cbaf 100644 --- a/src/test/java/seedu/duke/PairingListTest.java +++ b/src/test/java/seedu/duke/PairingListTest.java @@ -34,39 +34,23 @@ private PairingList pairingListInit() { } @Test - void addPairing_correctClientPropertyStrings_success() { - PairingList pairingList = pairingListInit(); + void addPairing_propertyClientObjects_success() { + PairingList pairingList = new PairingList(); + + pairingList.addPairing(PRESENT_CLIENT, PRESENT_PROPERTY); assertTrue(pairingList.getClientPropertyPairs().containsKey(PRESENT_CLIENT)); assertTrue(pairingList.getClientPropertyPairs().containsValue(PRESENT_PROPERTY)); } @Test - void addPairing_invalidClientPropertyStrings_success() { + void deletePairing_clientPropertyObject_success() { PairingList pairingList = pairingListInit(); - String clientDataNoSquareBrackets = "Nicky Minaj | 93437878"; - String clientDataNoSeparator = "[Nicki Minaj 93437878]"; - String clientDataNoContactNumber = "[Nicki Minaj | ]"; - - assertFalse(pairingList.getClientPropertyPairs().containsKey(clientDataNoSquareBrackets)); - assertFalse(pairingList.getClientPropertyPairs().containsKey(clientDataNoSeparator)); - assertFalse(pairingList.getClientPropertyPairs().containsKey(clientDataNoContactNumber)); - - String propertyDataNoSquareBrackets = - "Mary Tan Bee Bee | 107 North Bridge Rd, Singapore 179105 | 1000 | HDB 3 Room"; - assertFalse(pairingList.getClientPropertyPairs().containsValue(propertyDataNoSquareBrackets)); + pairingList.deletePairing(PRESENT_CLIENT, PRESENT_PROPERTY); + assertFalse(pairingList.getClientPropertyPairs().containsKey(PRESENT_CLIENT)); } - @Test - void addPairing_propertyClientObjects_success() { - PairingList pairingList = new PairingList(); - - pairingList.addPairing(PRESENT_CLIENT, PRESENT_PROPERTY); - - assertTrue(pairingList.getClientPropertyPairs().containsKey(PRESENT_CLIENT)); - assertTrue(pairingList.getClientPropertyPairs().containsValue(PRESENT_PROPERTY)); - } @Test void deletePairing_propertyObject_success() { From ec4bda14f13472a506c3287c8adac73acd14af32 Mon Sep 17 00:00:00 2001 From: "MSI\\User" Date: Sun, 16 Oct 2022 15:51:00 +0800 Subject: [PATCH 078/325] Update DeveloperGuide.md --- docs/DeveloperGuide.md | 77 +++++++++++++++++++++++++++++++----------- 1 file changed, 58 insertions(+), 19 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 64e1f0ed2..32a0c03ec 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -1,29 +1,70 @@ -# Developer Guide - +# Property Rental Manager - Developer Guide +* [Acknowledgements](#acknowledgements) +* [Setting Up and Getting Started](#setting-up-and-getting-started) +* [Product Scope](#product-scope) +* [Target User Profile](#target-user-profile) +* [Value Proposition](#value-proposition) +* [User Stories](#user-stories) +* [Design](#design) + * [Architecture](#architecture) + * [UI Component](#ui-component) + * [Client Component](#client-component) + * [Property Component](#property-component) + * [Model Component](#model-component) + * [Storage Component](#storage-component) + * [Common Classes](#storage-component) +* [Implementation](#implementation) +* [Documentation, logging, testing, configuration and dev-ops](#documentation-logging-testing-configuration-and-dev-ops) +* [Appendix: Requirements](#appendix-requirements) +* [Appendix: Instruction for manual testing](#appendix-instruction-for-manual-testing) +* [Non Functional Requirement (NFR)](#non-functional-requirements) +* [Glossary](#glossary) +___ ## Acknowledgements {list here sources of all reused/adapted ideas, code, documentation, and third-party libraries -- include links to the original source as well} - -## Design & implementation - -{Describe the design and implementation of the product. Use UML diagrams and short code snippets where applicable.} - - +___ +## Setting Up and Getting Started +___ ## Product scope -### Target user profile - -{Describe the target user profile} - -### Value proposition - -{Describe the value proposition: what problem does it solve?} - +___ +## Target user profile +This application is for property agent who is managing single owner rental units and is looking to reduce the overhead to filter appropriate tenants. The property agent would also want to monitor the expenses such as damages, utility bills and payment dates for rent. +___ +## Value proposition +Aids property agent in tracking information related to their property which includes: +- Filtering appropriate tenants (Based on tags e.g.: gender, occupations and age) +- Show expenses from the rented unit +- Monitor payment dates + +Some of the constraint includes: +- Single owner unit (Shared ownership will be registered under one owner's name) +- Unable to calculate tax payment +___ ## User Stories |Version| As a ... | I want to ... | So that I can ...| |--------|----------|---------------|------------------| |v1.0|new user|see usage instructions|refer to them when I forget how to use the application| |v2.0|user|find a to-do item by name|locate a to-do without having to go through the entire list| +___ +## Design +{Describe the design and implementation of the product. Use UML diagrams and short code snippets where applicable.} +### Architecture +### UI Component +### Client Component +### Property Component +### Model Component +### Storage Component +### Common Classes +___ +## Implementation +___ +## Documentation, logging, testing, configuration and dev-ops +___ +## Appendix: Requirements +___ +## Appendix: Instruction for Manual Testing ## Non-Functional Requirements @@ -33,6 +74,4 @@ * *glossary item* - Definition -## Instructions for manual testing - -{Give instructions on how to do a manual product testing e.g., how to load sample data to be used for testing} +## Instructions for manual testing \ No newline at end of file From c47ddcc156adabf060563bba1df5879edcf7c14d Mon Sep 17 00:00:00 2001 From: ngdeqi Date: Sun, 16 Oct 2022 21:54:11 +0800 Subject: [PATCH 079/325] Extract common exceptions and parsing helper methods, shorten Duke --- .../java/seedu/duke/CommandStructure.java | 24 + src/main/java/seedu/duke/Duke.java | 120 +-- src/main/java/seedu/duke/Messages.java | 116 ++- src/main/java/seedu/duke/Parser.java | 766 ++++++++---------- .../seedu/duke/ParserCommandAddClient.java | 4 + .../seedu/duke/ParserCommandAddProperty.java | 4 + .../java/seedu/duke/ParserCommandDelete.java | 4 + .../java/seedu/duke/ParserCommandExit.java | 4 + .../java/seedu/duke/ParserCommandList.java | 4 + .../java/seedu/duke/ParserCommandPair.java | 4 + .../java/seedu/duke/ParserCommandUnpair.java | 4 + src/main/java/seedu/duke/Ui.java | 203 +---- .../java/seedu/duke/command/CommandPair.java | 4 +- .../seedu/duke/command/CommandUnpair.java | 4 +- .../exception/AlreadyPairedException.java | 13 +- .../ByeParametersPresentException.java | 4 - .../ClientAlreadyPairedException.java | 13 +- .../duke/exception/DukeCommandException.java | 4 + .../seedu/duke/exception/DukeException.java | 1 + .../duke/exception/DukeParseException.java | 4 + .../exception/EmptyClientDetailException.java | 7 - .../EmptyClientIndexDeleteException.java | 7 - .../EmptyCommandAddDetailException.java | 7 - .../EmptyCommandCheckDetailException.java | 4 - .../EmptyCommandDeleteDetailException.java | 7 - ...mptyCommandPairUnpairDetailsException.java | 4 - .../exception/EmptyDescriptionException.java | 18 + .../duke/exception/EmptyDetailException.java | 18 + .../EmptyPropertyDetailException.java | 7 - .../EmptyPropertyIndexDeleteException.java | 7 - .../duke/exception/ExistingPairException.java | 13 +- .../exception/ExtraParametersException.java | 15 + .../IncorrectAddClientFlagOrderException.java | 7 - ...ncorrectAddPropertyFlagOrderException.java | 7 - .../IncorrectFlagOrderException.java | 13 +- .../IncorrectListDetailsException.java | 7 - ...IncorrectPairUnpairFlagOrderException.java | 4 - .../InvalidBudgetFormatException.java | 13 +- .../InvalidClientIndexDeleteException.java | 7 - ...InvalidClientIndexFlagFormatException.java | 7 - .../InvalidContactNumberException.java | 13 +- .../duke/exception/InvalidEmailException.java | 13 +- .../duke/exception/InvalidIndexException.java | 13 +- .../InvalidPriceFormatException.java | 13 +- .../InvalidPropertyIndexDeleteException.java | 7 - ...validPropertyIndexFlagFormatException.java | 7 - .../InvalidSingaporeAddressException.java | 13 +- .../MissingCheckPropertyFlagException.java | 4 - .../MissingClientDetailException.java | 9 - .../exception/MissingClientFlagException.java | 7 - .../MissingClientIndexFlagException.java | 7 - .../duke/exception/MissingFlagException.java | 15 +- .../exception/MissingListDetailException.java | 7 - .../MissingPairUnpairDetailException.java | 4 - .../MissingPairUnpairFlagException.java | 4 - .../MissingPropertyDetailException.java | 7 - .../MissingPropertyFlagException.java | 7 - .../MissingPropertyIndexFlagException.java | 7 - .../exception/NoExistingPairException.java | 13 +- .../duke/exception/NotIntegerException.java | 13 +- .../UndefinedSubCommandAddTypeException.java | 9 - ...UndefinedSubCommandCheckTypeException.java | 4 - ...ndefinedSubCommandDeleteTypeException.java | 7 - .../UndefinedSubCommandTypeException.java | 18 + 64 files changed, 698 insertions(+), 1006 deletions(-) create mode 100644 src/main/java/seedu/duke/CommandStructure.java create mode 100644 src/main/java/seedu/duke/ParserCommandAddClient.java create mode 100644 src/main/java/seedu/duke/ParserCommandAddProperty.java create mode 100644 src/main/java/seedu/duke/ParserCommandDelete.java create mode 100644 src/main/java/seedu/duke/ParserCommandExit.java create mode 100644 src/main/java/seedu/duke/ParserCommandList.java create mode 100644 src/main/java/seedu/duke/ParserCommandPair.java create mode 100644 src/main/java/seedu/duke/ParserCommandUnpair.java delete mode 100644 src/main/java/seedu/duke/exception/ByeParametersPresentException.java create mode 100644 src/main/java/seedu/duke/exception/DukeCommandException.java create mode 100644 src/main/java/seedu/duke/exception/DukeParseException.java delete mode 100644 src/main/java/seedu/duke/exception/EmptyClientDetailException.java delete mode 100644 src/main/java/seedu/duke/exception/EmptyClientIndexDeleteException.java delete mode 100644 src/main/java/seedu/duke/exception/EmptyCommandAddDetailException.java delete mode 100644 src/main/java/seedu/duke/exception/EmptyCommandCheckDetailException.java delete mode 100644 src/main/java/seedu/duke/exception/EmptyCommandDeleteDetailException.java delete mode 100644 src/main/java/seedu/duke/exception/EmptyCommandPairUnpairDetailsException.java create mode 100644 src/main/java/seedu/duke/exception/EmptyDescriptionException.java create mode 100644 src/main/java/seedu/duke/exception/EmptyDetailException.java delete mode 100644 src/main/java/seedu/duke/exception/EmptyPropertyDetailException.java delete mode 100644 src/main/java/seedu/duke/exception/EmptyPropertyIndexDeleteException.java create mode 100644 src/main/java/seedu/duke/exception/ExtraParametersException.java delete mode 100644 src/main/java/seedu/duke/exception/IncorrectAddClientFlagOrderException.java delete mode 100644 src/main/java/seedu/duke/exception/IncorrectAddPropertyFlagOrderException.java delete mode 100644 src/main/java/seedu/duke/exception/IncorrectListDetailsException.java delete mode 100644 src/main/java/seedu/duke/exception/IncorrectPairUnpairFlagOrderException.java delete mode 100644 src/main/java/seedu/duke/exception/InvalidClientIndexDeleteException.java delete mode 100644 src/main/java/seedu/duke/exception/InvalidClientIndexFlagFormatException.java delete mode 100644 src/main/java/seedu/duke/exception/InvalidPropertyIndexDeleteException.java delete mode 100644 src/main/java/seedu/duke/exception/InvalidPropertyIndexFlagFormatException.java delete mode 100644 src/main/java/seedu/duke/exception/MissingCheckPropertyFlagException.java delete mode 100644 src/main/java/seedu/duke/exception/MissingClientDetailException.java delete mode 100644 src/main/java/seedu/duke/exception/MissingClientFlagException.java delete mode 100644 src/main/java/seedu/duke/exception/MissingClientIndexFlagException.java delete mode 100644 src/main/java/seedu/duke/exception/MissingListDetailException.java delete mode 100644 src/main/java/seedu/duke/exception/MissingPairUnpairDetailException.java delete mode 100644 src/main/java/seedu/duke/exception/MissingPairUnpairFlagException.java delete mode 100644 src/main/java/seedu/duke/exception/MissingPropertyDetailException.java delete mode 100644 src/main/java/seedu/duke/exception/MissingPropertyFlagException.java delete mode 100644 src/main/java/seedu/duke/exception/MissingPropertyIndexFlagException.java delete mode 100644 src/main/java/seedu/duke/exception/UndefinedSubCommandAddTypeException.java delete mode 100644 src/main/java/seedu/duke/exception/UndefinedSubCommandCheckTypeException.java delete mode 100644 src/main/java/seedu/duke/exception/UndefinedSubCommandDeleteTypeException.java create mode 100644 src/main/java/seedu/duke/exception/UndefinedSubCommandTypeException.java diff --git a/src/main/java/seedu/duke/CommandStructure.java b/src/main/java/seedu/duke/CommandStructure.java new file mode 100644 index 000000000..fc5997dd3 --- /dev/null +++ b/src/main/java/seedu/duke/CommandStructure.java @@ -0,0 +1,24 @@ +package seedu.duke; + +public class CommandStructure { + + public static final String COMMAND_ADD = "add"; + public static final String COMMAND_DELETE = "delete"; + public static final String COMMAND_LIST = "list"; + public static final String COMMAND_PAIR = "pair"; + public static final String COMMAND_UNPAIR = "unpair"; + public static final String COMMAND_CHECK = "check"; + public static final String COMMAND_EXIT = "quit"; + + + public static final String[] ADD_PROPERTY_FLAGS = {"n/", "a/", "p/", "t/"}; + public static final String[] ADD_CLIENT_FLAGS = {"n/", "c/", "e/", "b/"}; + public static final String[] DELETE_PROPERTY_FLAGS = {"ip/"}; + public static final String[] DELETE_CLIENT_FLAGS = {"ic/"}; + public static final String[] PAIR_FLAGS = {"ip/", "ic/"}; + public static final String[] UNPAIR_FLAGS = {"ip/", "ic/"}; + public static final String[] CHECK_PROPERTY_FLAGS = {"ip/"}; + public static final String[] CHECK_CLIENT_FLAGS = {"ic/"}; + + +} diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index ee6a94bb4..93bd76104 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -3,45 +3,7 @@ import seedu.duke.command.Command; import seedu.duke.command.CommandBye; -import seedu.duke.exception.AlreadyPairedException; -import seedu.duke.exception.ClientAlreadyPairedException; -import seedu.duke.exception.EmptyClientDetailException; -import seedu.duke.exception.EmptyClientIndexDeleteException; -import seedu.duke.exception.EmptyCommandAddDetailException; -import seedu.duke.exception.EmptyCommandCheckDetailException; -import seedu.duke.exception.EmptyCommandDeleteDetailException; -import seedu.duke.exception.EmptyCommandPairUnpairDetailsException; -import seedu.duke.exception.EmptyPropertyDetailException; -import seedu.duke.exception.EmptyPropertyIndexDeleteException; -import seedu.duke.exception.IncorrectAddClientFlagOrderException; -import seedu.duke.exception.IncorrectAddPropertyFlagOrderException; -import seedu.duke.exception.IncorrectPairUnpairFlagOrderException; -import seedu.duke.exception.InvalidBudgetFormatException; -import seedu.duke.exception.InvalidClientIndexDeleteException; -import seedu.duke.exception.InvalidClientIndexFlagFormatException; -import seedu.duke.exception.InvalidContactNumberException; -import seedu.duke.exception.InvalidEmailException; -import seedu.duke.exception.MissingCheckPropertyFlagException; -import seedu.duke.exception.InvalidPriceFormatException; -import seedu.duke.exception.InvalidPropertyIndexDeleteException; -import seedu.duke.exception.InvalidPropertyIndexFlagFormatException; -import seedu.duke.exception.InvalidSingaporeAddressException; -import seedu.duke.exception.MissingClientDetailException; -import seedu.duke.exception.MissingClientFlagException; -import seedu.duke.exception.MissingClientIndexFlagException; -import seedu.duke.exception.MissingPairUnpairFlagException; -import seedu.duke.exception.MissingPropertyDetailException; -import seedu.duke.exception.MissingPropertyFlagException; -import seedu.duke.exception.MissingPropertyIndexFlagException; -import seedu.duke.exception.NoExistingPairException; -import seedu.duke.exception.NotIntegerException; -import seedu.duke.exception.InvalidIndexException; -import seedu.duke.exception.UndefinedSubCommandAddTypeException; -import seedu.duke.exception.UndefinedSubCommandCheckTypeException; -import seedu.duke.exception.UndefinedSubCommandDeleteTypeException; -import seedu.duke.exception.ByeParametersPresentException; -import seedu.duke.exception.IncorrectListDetailsException; -import seedu.duke.exception.MissingListDetailException; +import seedu.duke.exception.DukeException; import java.io.IOException; @@ -53,15 +15,17 @@ public class Duke { private ClientList clientList; private PairingList pairingList; - - public void run() throws IOException { - + public Duke() { this.ui = new Ui(); this.propertyList = new PropertyList(); this.clientList = new ClientList(); this.pairingList = new PairingList(); this.parser = new Parser(clientList, propertyList, pairingList); this.storage = new Storage(clientList, propertyList, pairingList); + } + + + public void run() throws IOException { Command command; boolean isCommandBye = false; @@ -75,76 +39,8 @@ public void run() throws IOException { command = parser.parseCommand(userInputText); command.execute(ui, storage, propertyList, clientList, pairingList); isCommandBye = (command instanceof CommandBye); - } catch (EmptyCommandAddDetailException e) { - ui.showMissingCommandAddDetailMessage(); - } catch (UndefinedSubCommandAddTypeException e) { - ui.showUndefinedSubCommandAddTypeMessage(); - } catch (EmptyPropertyDetailException e) { - ui.showEmptyPropertyDetailMessage(); - } catch (MissingPropertyFlagException | IncorrectAddPropertyFlagOrderException - | MissingPropertyDetailException e) { - ui.showAddPropertyWrongFormatMessage(); - } catch (InvalidSingaporeAddressException e) { - ui.showInvalidSingaporeAddressMessage(); - } catch (InvalidPriceFormatException e) { - ui.showInvalidPriceFormatMessage(); - } catch (EmptyClientDetailException e) { - ui.showEmptyClientDetailMessage(); - } catch (MissingClientFlagException | IncorrectAddClientFlagOrderException - | MissingClientDetailException e) { - ui.showAddClientWrongFormatMessage(); - } catch (InvalidContactNumberException e) { - ui.showInvalidContactNumberMessage(); - } catch (InvalidEmailException e) { - ui.showInvalidEmailMessage(); - } catch (InvalidBudgetFormatException e) { - ui.showInvalidBudgetFormatMessage(); - } catch (EmptyCommandDeleteDetailException e) { - ui.showMissingCommandDeleteDetailMessage(); - } catch (UndefinedSubCommandDeleteTypeException e) { - ui.showUndefinedSubCommandDeleteTypeMessage(); - } catch (InvalidPropertyIndexDeleteException e) { - ui.showInvalidPropertyIndexDeleteMessage(); - } catch (InvalidPropertyIndexFlagFormatException e) { - ui.showInvalidPropertyIndexFlagFormatMessage(); - } catch (EmptyPropertyIndexDeleteException e) { - ui.showEmptyPropertyIndexDeleteMessage(); - } catch (MissingPropertyIndexFlagException e) { - ui.showMissingPropertyIndexFlagMessage(); - } catch (InvalidClientIndexDeleteException e) { - ui.showInvalidClientIndexDeleteMessage(); - } catch (EmptyClientIndexDeleteException e) { - ui.showEmptyClientIndexDeleteMessage(); - } catch (MissingClientIndexFlagException e) { - ui.showMissingClientIndexFlagMessage(); - } catch (InvalidClientIndexFlagFormatException e) { - ui.showInvalidClientIndexFlagFormatMessage(); - } catch (EmptyCommandPairUnpairDetailsException e) { - ui.showEmptyCommandPairUnpairDetailsMessage(); - } catch (MissingPairUnpairFlagException | IncorrectPairUnpairFlagOrderException e) { - ui.showPairUnpairWrongFormatMessage(); - } catch (InvalidIndexException e) { - ui.showNotValidIndexMessage(); - } catch (NotIntegerException e) { - ui.showNotIntegerMessage(); - } catch (ClientAlreadyPairedException e) { - ui.showClientAlreadyPairedMessage(); - } catch (NoExistingPairException e) { - ui.showNoExistingPairMessage(); - } catch (AlreadyPairedException e) { - ui.showAlreadyPairedMessage(); - } catch (MissingCheckPropertyFlagException e) { - ui.showCheckPropertyWrongFormatMessage(); - } catch (UndefinedSubCommandCheckTypeException e) { - ui.showUndefinedSubCommandCheckTypeMessage(); - } catch (EmptyCommandCheckDetailException e) { - ui.showEmptyCommandCheckDetailException(); - } catch (IncorrectListDetailsException e) { - ui.showIncorrectListDetailsMessage(); - } catch (MissingListDetailException e) { - ui.showMissingListDetailsMessage(); - } catch (ByeParametersPresentException e) { - ui.showByeParametersPresentMessage(); + } catch (DukeException e) { + ui.showExceptionMessage(e); } } while (!isCommandBye); } diff --git a/src/main/java/seedu/duke/Messages.java b/src/main/java/seedu/duke/Messages.java index 38cf8d0d8..7782e46e1 100644 --- a/src/main/java/seedu/duke/Messages.java +++ b/src/main/java/seedu/duke/Messages.java @@ -4,6 +4,12 @@ * Container for user visible messages. */ public class Messages { + + public static final String EXCEPTION = "EXCEPTION"; + + + /* Confirmation Messages */ + public static final String MESSAGE_WELCOME = "Welcome to Property Manager! How may I help you?"; public static final String MESSAGE_COMMAND_UNDEFINED = "OOPS!!! Command not recognised. Try again."; @@ -12,51 +18,50 @@ public class Messages { public static final String MESSAGE_PROPERTY_ADDED = "Adding a property with the following information:"; - public static final String MESSAGE_PROPERTY_DELETED = "Deleting a property with the following information:"; + public static final String MESSAGE_PROPERTY_DELETED = "Deleting property with the following information:"; public static final String MESSAGE_CLIENT_ADDED = "Adding a client with the following information:"; - public static final String MESSAGE_CLIENT_DELETED = "Deleting a client with the following information:"; + public static final String MESSAGE_CLIENT_DELETED = "Deleting client with the following information:"; public static final String MESSAGE_PAIRED = "Pairing the following client and property: "; public static final String MESSAGE_UNPAIRED = "Unpairing the following client and property: "; - /* Add Property/Client Related Error Messages */ + /* General Error Messages */ + + public static final String MESSAGE_EMPTY_DESCRIPTION = "OOPS!!! The description for this command cannot be empty."; - public static final String MESSAGE_EMPTY_ADD_DESCRIPTION = "OOPS!!! The description for add cannot be empty."; + public static final String MESSAGE_MISSING_SUB_COMMAND_TYPE = "OOPS!!! Please specify sub-command type.\n" + + "For client: -client\n" + + "For property: -property"; - public static final String MESSAGE_MISSING_SUB_COMMAND_TYPE_FOR_ADD = "OOPS!!! To add, " - + "please specify sub-command type.\n" - + "For client: add -client\n" - + "For property: add -property"; + public static final String MESSAGE_INVALID_INDEX = "OOPS!!! Please enter an index that appears within the " + + "property list or client list"; - public static final String MESSAGE_EMPTY_PROPERTY_DESCRIPTION = "OOPS!!! The description of property " - + "cannot be empty."; + public static final String MESSAGE_NOT_INTEGER = "OOPS!! Please enter a positive integer as index"; - public static final String MESSAGE_EMPTY_CLIENT_DESCRIPTION = "OOPS!!! The description of client cannot be empty."; - public static final String MESSAGE_ADD_PROPERTY_WRONG_FORMAT = "OOPS!!! To add a property, it requires " - + "the following format and details as shown below."; + /* Add Property/Client Related Error Messages */ - public static final String MESSAGE_PROPERTY_INPUT_EXAMPLE = "Format: add -property n/NAME a/ADDRESS p/PRICE t/TYPE" - + "\nExample: add -property n/Bob Tan Bee Bee a/25 Lower Kent Ridge Rd, Singapore 119081 " + public static final String MESSAGE_ADD_PROPERTY_WRONG_FORMAT = "OOPS!!! To add a property, it requires " + + "the following format and details:\n" + + "Format: add -property n/NAME a/ADDRESS p/PRICE t/TYPE\n" + + "Example: add -property n/Bob Tan Bee Bee a/25 Lower Kent Ridge Rd, Singapore 119081 " + "p/1000 t/HDB 3 Room"; public static final String MESSAGE_ADD_CLIENT_WRONG_FORMAT = "OOPS!!! To add a client, it requires " - + "the following format and details as shown below."; - - public static final String MESSAGE_CLIENT_INPUT_EXAMPLE = "Format: add -client n/NAME c/CONTACT_NUMBER e/EMAIL " + + "the following format and details:\n" + + "Format: add -client n/NAME c/CONTACT_NUMBER e/EMAIL " + "b/BUDGET_MONTH\n" + "Example: add -client n/Doja Cat c/93437878 e/doja88@example.com b/2000\n" + "Note: Email is optional"; public static final String MESSAGE_INVALID_SINGAPORE_ADDRESS = "OOPS!!! The address provided is invalid. " + "To add a property, A valid Singapore address must be provided\nwith the following " - + "format and details as shown below."; - - public static final String MESSAGE_VALID_SINGAPORE_ADDRESS_EXAMPLE = "LANDED PROPERTY:\n Format: " + + "format and details:\n" + + "LANDED PROPERTY:\n Format: " + "[Unit Number][Street Name],Singapore[Postal Code]\n" + " Example: 60 Aria Street, Singapore 602580\n" + "BUILDINGS (e.g. HDBs, apartments, condominiums):\n" @@ -81,82 +86,55 @@ public class Messages { /* Delete Property/Client Related Error Messages */ - public static final String MESSAGE_MISSING_SUB_COMMAND_TYPE_FOR_DELETE = "OOPS!!! To delete, " - + "please specify sub-command type.\n" - + "For client: add -client\n" - + "For property: add -property"; - - public static final String MESSAGE_EMPTY_DELETE_DESCRIPTION = "OOPS!!! Please use this format to delete:\n" - + "Client: delete -client ic/CLIENT_INDEX\n" - + "Property: delete -property ip/PROPERTY_INDEX"; - - public static final String MESSAGE_INVALID_CLIENT_INDEX = "OOPS!!! Please enter a valid client index."; - - public static final String MESSAGE_EMPTY_CLIENT_INDEX = "OOPS!!! The client index to delete cannot be empty."; - - public static final String MESSAGE_MISSING_CLIENT_INDEX_FLAG = "OOPS!!! Please provide the client index flag."; + public static final String MESSAGE_DELETE_CLIENT_WRONG_FORMAT = "OOPS!!! Please use this format to delete client:\n" + + "delete -client ic/CLIENT_INDEX\n"; - public static final String MESSAGE_INVALID_CLIENT_INDEX_FLAG_FORMAT = "OOPS!!! Please use this flag format:\n" - + "ic/CLIENT_INDEX"; + public static final String MESSAGE_DELETE_PROPERTY_WRONG_FORMAT = "OOPS!!! Please use this format to delete " + + "property\n" + + "delete -property ip/PROPERTY_INDEX"; - public static final String MESSAGE_INVALID_PROPERTY_INDEX = "OOPS!!! Please enter a valid property index."; - - public static final String MESSAGE_EMPTY_PROPERTY_INDEX = "OOPS!!! The property index to delete cannot be empty."; - - public static final String MESSAGE_MISSING_PROPERTY_INDEX_FLAG = "OOPS!!! Please provide the property index flag."; - - public static final String MESSAGE_INVALID_PROPERTY_INDEX_FLAG_FORMAT = "OOPS!!! Please use this flag format:\n" - + "ip/PROPERTY_INDEX"; /* Pair/Unpair Related Error Messages */ - public static final String MESSAGE_EMPTY_COMMAND_PAIR_UNPAIR = "OOPS!!! The description of a pair/unpair message " - + "cannot be empty"; - - public static final String MESSAGE_NOT_VALID_INDEX = "OOPS!!! Please enter an index that appears within the " - + "property list or client list"; - - public static final String MESSAGE_NOT_INTEGER = "OOPS!!! Please enter an integer"; - - public static final String MESSAGE_PAIR_UNPAIR_WRONG_FORMAT = "OOPS!!! To pair or unpair, it requires " - + "the following format and details as shown below."; - - public static final String MESSAGE_PAIR_UNPAIR_INPUT_EXAMPLE = "Format:\n" + public static final String MESSAGE_PAIR_WRONG_FORMAT = "OOPS!!! To pair, please follow the following format:\n" + " pair ip/PROPERTY_INDEX ic/CLIENT_INDEX\n" + + "Example:\n" + + " pair ip/1 ic/5\n"; + + public static final String MESSAGE_UNPAIR_WRONG_FORMAT = "OOPS!!! To unpair, please follow the following format:\n" + " unpair ip/PROPERTY_INDEX ic/CLIENT_INDEX\n" - + "Examples:\n" - + " pair ip/1 ic/5\n" + + "Example:\n" + " unpair ip/2 ic/1"; + public static final String MESSAGE_CLIENT_ALREADY_PAIRED = "OOPS!! This client is currently renting a property, " + "try pairing with another client "; - public static final String MESSAGE_ALREADY_PAIRED = "OOPS!! This client and this property are already paired " + public static final String MESSAGE_EXISTING_PAIR = "OOPS!! This client and this property are already paired " + "together. You don't need to pair them again."; - public static final String MESSAGE_NO_EXISTING_PAIR = "OOPS!! This property is not being rented by a tenant. " + public static final String MESSAGE_NO_EXISTING_PAIR = "OOPS!! This property is not being rented by the tenant. " + "Unpair unsuccessful."; + + /* Check property/client related Error Messages */ + public static final String MESSAGE_CHECK_PROPERTY_RESULT = "Here are the tenants renting this property:"; - public static final String MESSAGE_CHECK_PROPERTY_WRONG_FORMAT = "Format:\n" + public static final String MESSAGE_CHECK_PROPERTY_WRONG_FORMAT = "OOPS!! To check property, please use the " + + "following format:\n" + " check -property ip/INDEX\n" + "Example:\n" + " check -property ip/5"; - public static final String MESSAGE_MISSING_SUB_COMMAND_TYPE_FOR_CHECK = "OOPS!!! To check, " - + "please specify sub-command type.\n" - + "For property: check -property"; + public static final String MESSAGE_TRY_AGAIN = "Please try again."; - public static final String MESSAGE_EMPTY_CHECK_DESCRIPTION = "OOPS!!! The description for check cannot be empty."; - public static final String MESSAGE_TRY_AGAIN = "Please try again."; + /* List related Error Messages */ public static final String MESSAGE_INCORRECT_LIST_DETAILS = "OOPS!!! Please enter either -client or -property to" + " list clients and properties respectively"; - public static final String MESSAGE_MISSING_LIST_DETAILS = "OOPS!!!" - + " The description for list cannot be empty"; public static final String LINE_BREAK = "----------------------------------------------------------------------" + "----------"; diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 739e46673..c3ab10c23 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -1,74 +1,81 @@ package seedu.duke; import seedu.duke.command.Command; -import seedu.duke.command.CommandAddProperty; import seedu.duke.command.CommandAddClient; +import seedu.duke.command.CommandAddProperty; +import seedu.duke.command.CommandBye; import seedu.duke.command.CommandCheckProperty; import seedu.duke.command.CommandDeleteClient; import seedu.duke.command.CommandDeleteProperty; -import seedu.duke.command.CommandPair; -import seedu.duke.command.CommandUnpair; -import seedu.duke.command.CommandUndefined; import seedu.duke.command.CommandListClients; import seedu.duke.command.CommandListProperties; -import seedu.duke.command.CommandBye; - -import seedu.duke.exception.AlreadyPairedException; +import seedu.duke.command.CommandPair; +import seedu.duke.command.CommandUndefined; +import seedu.duke.command.CommandUnpair; import seedu.duke.exception.ClientAlreadyPairedException; -import seedu.duke.exception.EmptyClientDetailException; -import seedu.duke.exception.EmptyClientIndexDeleteException; -import seedu.duke.exception.EmptyCommandAddDetailException; -import seedu.duke.exception.EmptyCommandCheckDetailException; -import seedu.duke.exception.EmptyCommandDeleteDetailException; -import seedu.duke.exception.EmptyCommandPairUnpairDetailsException; -import seedu.duke.exception.EmptyPropertyDetailException; -import seedu.duke.exception.EmptyPropertyIndexDeleteException; -import seedu.duke.exception.IncorrectAddClientFlagOrderException; -import seedu.duke.exception.IncorrectAddPropertyFlagOrderException; +import seedu.duke.exception.DukeParseException; +import seedu.duke.exception.EmptyDescriptionException; +import seedu.duke.exception.EmptyDetailException; +import seedu.duke.exception.ExistingPairException; +import seedu.duke.exception.ExtraParametersException; import seedu.duke.exception.IncorrectFlagOrderException; -import seedu.duke.exception.IncorrectPairUnpairFlagOrderException; import seedu.duke.exception.InvalidBudgetFormatException; -import seedu.duke.exception.InvalidClientIndexDeleteException; -import seedu.duke.exception.InvalidClientIndexFlagFormatException; import seedu.duke.exception.InvalidContactNumberException; import seedu.duke.exception.InvalidEmailException; -import seedu.duke.exception.MissingCheckPropertyFlagException; +import seedu.duke.exception.InvalidIndexException; import seedu.duke.exception.InvalidPriceFormatException; -import seedu.duke.exception.InvalidPropertyIndexDeleteException; -import seedu.duke.exception.InvalidPropertyIndexFlagFormatException; import seedu.duke.exception.InvalidSingaporeAddressException; -import seedu.duke.exception.MissingClientDetailException; -import seedu.duke.exception.MissingClientFlagException; -import seedu.duke.exception.MissingClientIndexFlagException; import seedu.duke.exception.MissingFlagException; -import seedu.duke.exception.MissingPairUnpairFlagException; -import seedu.duke.exception.MissingPropertyDetailException; -import seedu.duke.exception.MissingPropertyFlagException; -import seedu.duke.exception.MissingPropertyIndexFlagException; import seedu.duke.exception.NoExistingPairException; import seedu.duke.exception.NotIntegerException; -import seedu.duke.exception.InvalidIndexException; -import seedu.duke.exception.UndefinedSubCommandAddTypeException; -import seedu.duke.exception.UndefinedSubCommandCheckTypeException; -import seedu.duke.exception.UndefinedSubCommandDeleteTypeException; -import seedu.duke.exception.IncorrectListDetailsException; -import seedu.duke.exception.MissingListDetailException; -import seedu.duke.exception.ByeParametersPresentException; +import seedu.duke.exception.UndefinedSubCommandTypeException; import java.util.ArrayList; import java.util.regex.Matcher; import java.util.regex.Pattern; +import static seedu.duke.CommandStructure.ADD_CLIENT_FLAGS; +import static seedu.duke.CommandStructure.ADD_PROPERTY_FLAGS; +import static seedu.duke.CommandStructure.CHECK_PROPERTY_FLAGS; +import static seedu.duke.CommandStructure.COMMAND_ADD; +import static seedu.duke.CommandStructure.COMMAND_CHECK; +import static seedu.duke.CommandStructure.COMMAND_DELETE; +import static seedu.duke.CommandStructure.COMMAND_EXIT; +import static seedu.duke.CommandStructure.COMMAND_LIST; +import static seedu.duke.CommandStructure.COMMAND_PAIR; +import static seedu.duke.CommandStructure.COMMAND_UNPAIR; +import static seedu.duke.CommandStructure.DELETE_CLIENT_FLAGS; +import static seedu.duke.CommandStructure.DELETE_PROPERTY_FLAGS; +import static seedu.duke.CommandStructure.PAIR_FLAGS; +import static seedu.duke.CommandStructure.UNPAIR_FLAGS; +import static seedu.duke.Messages.EXCEPTION; +import static seedu.duke.Messages.MESSAGE_ADD_CLIENT_WRONG_FORMAT; +import static seedu.duke.Messages.MESSAGE_ADD_PROPERTY_WRONG_FORMAT; +import static seedu.duke.Messages.MESSAGE_BYE_PARAMETERS_PRESENT; +import static seedu.duke.Messages.MESSAGE_CHECK_PROPERTY_WRONG_FORMAT; +import static seedu.duke.Messages.MESSAGE_CLIENT_ALREADY_PAIRED; +import static seedu.duke.Messages.MESSAGE_DELETE_CLIENT_WRONG_FORMAT; +import static seedu.duke.Messages.MESSAGE_DELETE_PROPERTY_WRONG_FORMAT; +import static seedu.duke.Messages.MESSAGE_EMPTY_DESCRIPTION; +import static seedu.duke.Messages.MESSAGE_EXISTING_PAIR; +import static seedu.duke.Messages.MESSAGE_INCORRECT_LIST_DETAILS; +import static seedu.duke.Messages.MESSAGE_INVALID_BUDGET_FORMAT; +import static seedu.duke.Messages.MESSAGE_INVALID_CONTACT_NUMBER; +import static seedu.duke.Messages.MESSAGE_INVALID_EMAIL; +import static seedu.duke.Messages.MESSAGE_INVALID_INDEX; +import static seedu.duke.Messages.MESSAGE_INVALID_PRICE_FORMAT; +import static seedu.duke.Messages.MESSAGE_INVALID_SINGAPORE_ADDRESS; +import static seedu.duke.Messages.MESSAGE_MISSING_SUB_COMMAND_TYPE; +import static seedu.duke.Messages.MESSAGE_NOT_INTEGER; +import static seedu.duke.Messages.MESSAGE_NO_EXISTING_PAIR; +import static seedu.duke.Messages.MESSAGE_PAIR_WRONG_FORMAT; +import static seedu.duke.Messages.MESSAGE_UNPAIR_WRONG_FORMAT; + public class Parser { private static ClientList clientList; private static PropertyList propertyList; private static PairingList pairingList; - public static final int ADD_PROPERTY_FLAG_SIZE = 4; - public static final int ADD_CLIENT_FLAG_SIZE = 4; - public static final int PAIR_UNPAIR_FLAG_SIZE = 2; - public static final int CHECK_PROPERTY_FLAG_SIZE = 1; - public Parser(ClientList clientL, PropertyList propertyL, PairingList pairingL) { clientList = clientL; @@ -76,64 +83,49 @@ public Parser(ClientList clientL, PropertyList propertyL, PairingList pairingL) pairingList = pairingL; } - public Command parseCommand(String input) throws EmptyCommandAddDetailException, - UndefinedSubCommandAddTypeException, EmptyPropertyDetailException, MissingPropertyFlagException, - IncorrectAddPropertyFlagOrderException, MissingPropertyDetailException, InvalidSingaporeAddressException, - InvalidPriceFormatException, EmptyClientDetailException, MissingClientFlagException, - IncorrectAddClientFlagOrderException, MissingClientDetailException, InvalidContactNumberException, - InvalidEmailException, InvalidBudgetFormatException, UndefinedSubCommandDeleteTypeException, - EmptyCommandDeleteDetailException, InvalidPropertyIndexFlagFormatException, - MissingPropertyIndexFlagException, EmptyPropertyIndexDeleteException, InvalidPropertyIndexDeleteException, - InvalidClientIndexDeleteException, EmptyClientIndexDeleteException, MissingClientIndexFlagException, - InvalidClientIndexFlagFormatException, EmptyCommandPairUnpairDetailsException, - MissingPairUnpairFlagException, IncorrectPairUnpairFlagOrderException, InvalidIndexException, - NotIntegerException, NoExistingPairException, ClientAlreadyPairedException, AlreadyPairedException, - UndefinedSubCommandCheckTypeException, EmptyCommandCheckDetailException, MissingCheckPropertyFlagException, - IncorrectListDetailsException, MissingListDetailException, ByeParametersPresentException { + public Command parseCommand(String input) throws DukeParseException, ExistingPairException, + ClientAlreadyPairedException, NoExistingPairException { ArrayList processedCommandDetails = partitionCommandTypeAndDetails(input); String commandType = processedCommandDetails.get(0); String commandDetails = processedCommandDetails.get(1); + switch (commandType) { - case "add": - checkForEmptyCommandAddDetails(commandDetails); + case COMMAND_ADD: + checkForEmptyDescription(commandDetails); ArrayList processedAddCommandDetails = partitionCommandTypeAndDetails(commandDetails); - String subCommandType = processedAddCommandDetails.get(0); + String subAddCommandType = processedAddCommandDetails.get(0); String clientOrPropertyDescriptions = processedAddCommandDetails.get(1); - if (subCommandType.equals("-property")) { + if (subAddCommandType.equals("-property")) { return prepareForCommandAddProperty(clientOrPropertyDescriptions); - } else if (subCommandType.equals("-client")) { + } else if (subAddCommandType.equals("-client")) { return prepareForCommandAddClient(clientOrPropertyDescriptions); } else { - throw new UndefinedSubCommandAddTypeException(); + throw new UndefinedSubCommandTypeException(MESSAGE_MISSING_SUB_COMMAND_TYPE); } - case "delete": - checkForEmptyCommandDeleteDetails(commandDetails); + case COMMAND_DELETE: + checkForEmptyDescription(commandDetails); ArrayList processedDeleteCommandDetails = partitionCommandTypeAndDetails(commandDetails); String subDeleteCommandType = processedDeleteCommandDetails.get(0); - String indexDescription = processedDeleteCommandDetails.get(1).trim(); + String deleteDescriptions = processedDeleteCommandDetails.get(1).trim(); if (subDeleteCommandType.equals("-property")) { - checkForPropertyIndexFlag(indexDescription); - int propertyIndexToDelete = getPropertyIndexToDelete(indexDescription.substring(3)); - return prepareForCommandDeleteProperty(propertyIndexToDelete, propertyList); + return prepareForCommandDeleteProperty(deleteDescriptions); } else if (subDeleteCommandType.equals("-client")) { - checkForClientIndexFlag(indexDescription); - int clientIndexToDelete = getClientIndexToDelete(indexDescription.substring(3)); - return prepareForCommandDeleteClient(clientIndexToDelete, clientList); + return prepareForCommandDeleteClient(deleteDescriptions); } else { - throw new UndefinedSubCommandDeleteTypeException(); + throw new UndefinedSubCommandTypeException(MESSAGE_MISSING_SUB_COMMAND_TYPE); } - case "pair": - checkForEmptyCommandPairUnpairDetails(commandDetails); + case COMMAND_PAIR: + checkForEmptyDescription(commandDetails); return prepareForCommandPair(commandDetails); - case "unpair": - checkForEmptyCommandPairUnpairDetails(commandDetails); + case COMMAND_UNPAIR: + checkForEmptyDescription(commandDetails); return prepareForCommandUnpair(commandDetails); - case "check": - checkForEmptyCommandCheckDetails(commandDetails); + case COMMAND_CHECK: + checkForEmptyDescription(commandDetails); ArrayList processedCheckCommandDetails = partitionCommandTypeAndDetails(commandDetails); String subCommandCheckType = processedCheckCommandDetails.get(0); String commandCheckClientOrPropertyDescriptions = processedCheckCommandDetails.get(1); @@ -141,14 +133,14 @@ public Command parseCommand(String input) throws EmptyCommandAddDetailException, if (subCommandCheckType.equals("-property")) { return prepareForCommandCheckProperty(commandCheckClientOrPropertyDescriptions); } else { - throw new UndefinedSubCommandCheckTypeException(); + throw new UndefinedSubCommandTypeException(MESSAGE_MISSING_SUB_COMMAND_TYPE); } - case "list": - checkForEmptyListParameters(commandDetails); + case COMMAND_LIST: + checkForEmptyDescription(commandDetails); return prepareForCommandList(commandDetails); - case "bye": + case COMMAND_EXIT: checkForByeParameters(commandDetails); return new CommandBye(); default: @@ -167,153 +159,113 @@ private ArrayList partitionCommandTypeAndDetails(String fullCommandDetai return processedCommandDetails; } - void checkForEmptyListParameters(String commandListDetails) throws MissingListDetailException { - boolean isEmptyListDetail = checkForEmptyDetail(commandListDetails); - if (isEmptyListDetail) { - throw new MissingListDetailException(); + private void checkForEmptyDescription(String commandDetails) throws EmptyDescriptionException { + boolean isEmptyDescription = isEmptyString(commandDetails); + if (isEmptyDescription) { + throw new EmptyDescriptionException(MESSAGE_EMPTY_DESCRIPTION); } } - - /* Add Property/Client Parse Section */ - - private void checkForEmptyCommandAddDetails(String commandAddDetails) throws EmptyCommandAddDetailException { - boolean isEmptyCommandAddDetail = checkForEmptyDetail(commandAddDetails); - if (isEmptyCommandAddDetail) { - throw new EmptyCommandAddDetailException(); + private void checkForEmptyDetails(String commandDetails) throws EmptyDetailException { + boolean isEmptyDetail = isEmptyString(commandDetails); + if (isEmptyDetail) { + throw new EmptyDetailException(EXCEPTION); } } - private Command prepareForCommandAddProperty(String rawPropertyDescriptions) throws - EmptyPropertyDetailException, MissingPropertyFlagException, IncorrectAddPropertyFlagOrderException, - MissingPropertyDetailException, InvalidSingaporeAddressException, InvalidPriceFormatException { - checkForEmptyAddPropertyDetails(rawPropertyDescriptions); - try { - ArrayList propertyDetails = processPropertyDetails(rawPropertyDescriptions); - validatePropertyDetails(propertyDetails); - return new CommandAddProperty(propertyDetails); - } catch (MissingFlagException e) { - throw new MissingPropertyFlagException(); - } catch (IncorrectFlagOrderException e) { - throw new IncorrectAddPropertyFlagOrderException(); - } + private boolean isEmptyString(String commandDetails) { + return commandDetails.trim().isEmpty(); } - private Command prepareForCommandAddClient(String rawClientDescriptions) throws EmptyClientDetailException, - MissingClientFlagException, IncorrectAddClientFlagOrderException, MissingClientDetailException, - InvalidContactNumberException, InvalidEmailException, InvalidBudgetFormatException { - checkForEmptyAddClientDetails(rawClientDescriptions); - try { - ArrayList clientDetails = processClientDetails(rawClientDescriptions); - validateClientDetails(clientDetails); - return new CommandAddClient(clientDetails); - } catch (MissingFlagException e) { - throw new MissingClientFlagException(); - } catch (IncorrectFlagOrderException e) { - throw new IncorrectAddClientFlagOrderException(); - } - } - private void checkForEmptyAddPropertyDetails(String commandAddDescriptions) throws EmptyPropertyDetailException { - boolean isEmptyCommandAddDetail = checkForEmptyDetail(commandAddDescriptions); - if (isEmptyCommandAddDetail) { - throw new EmptyPropertyDetailException(); - } - } + private ArrayList processCommandDetails(String rawCommandDetails, String[] flags) + throws MissingFlagException, IncorrectFlagOrderException { - private void checkForEmptyAddClientDetails(String commandAddDescriptions) throws EmptyClientDetailException { - boolean isEmptyCommandAddDetail = checkForEmptyDetail(commandAddDescriptions); - if (isEmptyCommandAddDetail) { - throw new EmptyClientDetailException(); - } + int[] flagIndexPositions = getFlagIndexPositions(rawCommandDetails, flags); + checkForMissingFlags(flagIndexPositions); + checkFlagsOrder(flagIndexPositions); + return extractCommandDetails(rawCommandDetails, flags, flagIndexPositions); } - private ArrayList processPropertyDetails(String rawPropertyDetails) throws MissingFlagException, - IncorrectFlagOrderException { - String[] addPropertyFlags = {"n/", "a/", "p/", "t/"}; - int[] addPropertyFlagIndexPositions = new int[ADD_PROPERTY_FLAG_SIZE]; - - for (int i = 0; i < addPropertyFlags.length; i++) { - addPropertyFlagIndexPositions[i] = rawPropertyDetails.indexOf(addPropertyFlags[i]); + private ArrayList convertProcessedCommandDetailsToInteger(ArrayList processedCommandDetails) + throws NotIntegerException { + ArrayList integerDetails = new ArrayList<>(); + for (String detail : processedCommandDetails) { + int integer; + try { + integer = Integer.parseInt(detail); + } catch (NumberFormatException e) { + throw new NotIntegerException(EXCEPTION); + } + integerDetails.add(integer - 1); // Convert to 0-index } - - checkForMissingPropertyFlags(addPropertyFlagIndexPositions); - checkForPropertyFlagsOrder(addPropertyFlagIndexPositions); - return extractPropertyDetails(rawPropertyDetails, addPropertyFlagIndexPositions); + return integerDetails; } - private ArrayList processClientDetails(String rawClientDetails) throws MissingFlagException, - IncorrectFlagOrderException { - String[] addClientFlags = {"n/", "c/", "e/", "b/"}; - int[] addClientFlagIndexPositions = new int[ADD_CLIENT_FLAG_SIZE]; + // Command Add Client has a special detail processing method because it has an optional email field + private ArrayList processCommandAddClientDetails(String rawCommandDetails, String[] flags) + throws MissingFlagException, IncorrectFlagOrderException { - for (int i = 0; i < addClientFlags.length; i++) { - addClientFlagIndexPositions[i] = rawClientDetails.indexOf(addClientFlags[i]); - } - - checkForMissingClientFlags(addClientFlagIndexPositions); - checkForClientFlagsOrder(addClientFlagIndexPositions); - return extractClientDetails(rawClientDetails, addClientFlagIndexPositions); + int[] flagIndexPositions = getFlagIndexPositions(rawCommandDetails, flags); + checkForMissingFlags(flagIndexPositions); + checkFlagsOrder(flagIndexPositions); + return extractClientDetails(rawCommandDetails, flagIndexPositions); } - private void checkForMissingPropertyFlags(int[] addPropertyFlagIndexPositions) throws MissingFlagException { - for (int propertyFlagIndex : addPropertyFlagIndexPositions) { - checkForEssentialAddFlag(propertyFlagIndex); + private int[] getFlagIndexPositions(String commandDetails, String[] flags) { + int[] flagIndexPositions = new int[flags.length]; + + for (int i = 0; i < flags.length; i++) { + flagIndexPositions[i] = commandDetails.indexOf(flags[i]); } + return flagIndexPositions; } - private void checkForMissingClientFlags(int[] addClientFlagIndexPositions) throws MissingFlagException { - checkForEssentialAddFlag(addClientFlagIndexPositions[0]); - checkForEssentialAddFlag(addClientFlagIndexPositions[1]); - checkForEssentialAddFlag(addClientFlagIndexPositions[3]); - } - private void checkForEssentialAddFlag(int addClientFlagIndexes) throws MissingFlagException { - boolean hasFlag = (addClientFlagIndexes != -1); - if (!hasFlag) { - throw new MissingFlagException(); + private void checkForMissingFlags(int[] flagIndexPositions) throws MissingFlagException { + for (int flagIndex : flagIndexPositions) { + if (!isFlagPresent(flagIndex)) { + throw new MissingFlagException(EXCEPTION); + } } } - private void checkForPropertyFlagsOrder(int[] addPropertyFlagIndexPositions) throws IncorrectFlagOrderException { - for (int propertyFlagIndex = 0; propertyFlagIndex < ADD_PROPERTY_FLAG_SIZE - 1; propertyFlagIndex++) { - checkForCorrectFlagOrder(addPropertyFlagIndexPositions[propertyFlagIndex], - addPropertyFlagIndexPositions[propertyFlagIndex + 1]); - } + private boolean isFlagPresent(int flagIndexPosition) { + return (flagIndexPosition != -1); } - private void checkForClientFlagsOrder(int[] addClientFlagIndexPositions) throws IncorrectFlagOrderException { - boolean hasEmail = (addClientFlagIndexPositions[2] != -1); - checkForCorrectFlagOrder(addClientFlagIndexPositions[0], addClientFlagIndexPositions[1]); - checkForCorrectFlagOrder(addClientFlagIndexPositions[1], addClientFlagIndexPositions[3]); - if (hasEmail) { - checkForCorrectFlagOrder(addClientFlagIndexPositions[1], addClientFlagIndexPositions[2]); - checkForCorrectFlagOrder(addClientFlagIndexPositions[2], addClientFlagIndexPositions[3]); + private void checkFlagsOrder(int[] flagIndexPositions) throws IncorrectFlagOrderException { + for (int i = 0; i < flagIndexPositions.length - 1; i++) { + checkForCorrectFlagOrder(flagIndexPositions[i], flagIndexPositions[i + 1]); } } private void checkForCorrectFlagOrder(int flagPosition, int nextFlagPosition) throws IncorrectFlagOrderException { boolean hasCorrectOrder = (flagPosition < nextFlagPosition); if (!hasCorrectOrder) { - throw new IncorrectFlagOrderException(); + throw new IncorrectFlagOrderException(EXCEPTION); } } - private ArrayList extractPropertyDetails(String rawPropertyDetails, int[] addPropertyFlagIndexPositions) { - String landlordName = extractDetail(rawPropertyDetails, addPropertyFlagIndexPositions[0] + 2, - addPropertyFlagIndexPositions[1]); - String propertyAddress = extractDetail(rawPropertyDetails, addPropertyFlagIndexPositions[1] + 2, - addPropertyFlagIndexPositions[2]); - String rentingPrice = extractDetail(rawPropertyDetails, addPropertyFlagIndexPositions[2] + 2, - addPropertyFlagIndexPositions[3]); - String unitType = extractDetail(rawPropertyDetails, addPropertyFlagIndexPositions[3] + 2); - - ArrayList processedPropertyDetails = new ArrayList<>(); - processedPropertyDetails.add(landlordName.trim()); - processedPropertyDetails.add(propertyAddress.trim()); - processedPropertyDetails.add(rentingPrice.trim()); - processedPropertyDetails.add(unitType.trim()); - return processedPropertyDetails; + private ArrayList extractCommandDetails(String rawCommandDetails, String[] flags, + int[] flagIndexPositions) { + ArrayList extractedCommandDetails = new ArrayList<>(); + for (int i = 0; i < flags.length; i++) { + String extractedDetail; + if (i == flags.length - 1) { + /* The extracted detail for the last flag starts from the char after the flag, to the end of + rawCommandDetails */ + extractedDetail = extractDetail(rawCommandDetails, flagIndexPositions[i] + flags[i].length()); + } else { + // The extracted detail for non-last starts from the char after the flag, to index before the next flag + extractedDetail = extractDetail( + rawCommandDetails, + flagIndexPositions[i] + flags[i].length(), + flagIndexPositions[i + 1]); + } + extractedCommandDetails.add(extractedDetail.trim()); + } + return extractedCommandDetails; } private ArrayList extractClientDetails(String rawClientDetails, int[] addClientFlagIndexPositions) { @@ -349,11 +301,66 @@ private static String extractDetail(String rawDetails, int beginIndex, int endIn return rawDetails.substring(beginIndex, endIndex).trim(); } - private void validatePropertyDetails(ArrayList propertyDetails) throws MissingPropertyDetailException, + + + /* Add Property/Client Parse Section */ + + private Command prepareForCommandAddProperty(String rawPropertyDescriptions) + throws InvalidSingaporeAddressException, MissingFlagException, InvalidPriceFormatException, + IncorrectFlagOrderException, EmptyDetailException { + + try { + checkForEmptyDetails(rawPropertyDescriptions); + + ArrayList propertyDetails = processCommandDetails(rawPropertyDescriptions, ADD_PROPERTY_FLAGS); + validatePropertyDetails(propertyDetails); + return new CommandAddProperty(propertyDetails); + + } catch (InvalidSingaporeAddressException e) { + throw new InvalidSingaporeAddressException(MESSAGE_INVALID_SINGAPORE_ADDRESS); + } catch (MissingFlagException e) { + throw new MissingFlagException(MESSAGE_ADD_PROPERTY_WRONG_FORMAT); + } catch (IncorrectFlagOrderException e) { + throw new IncorrectFlagOrderException(MESSAGE_ADD_PROPERTY_WRONG_FORMAT); + } catch (InvalidPriceFormatException e) { + throw new InvalidPriceFormatException(MESSAGE_INVALID_PRICE_FORMAT); + } catch (EmptyDetailException e) { + throw new EmptyDetailException(MESSAGE_ADD_PROPERTY_WRONG_FORMAT); + } + } + + private Command prepareForCommandAddClient(String rawClientDescriptions) throws MissingFlagException, + IncorrectFlagOrderException, InvalidContactNumberException, EmptyDetailException, InvalidEmailException, + InvalidBudgetFormatException { + + try { + checkForEmptyDetails(rawClientDescriptions); + + ArrayList clientDetails = processCommandAddClientDetails(rawClientDescriptions, ADD_CLIENT_FLAGS); + validateClientDetails(clientDetails); + return new CommandAddClient(clientDetails); + + } catch (MissingFlagException e) { + throw new MissingFlagException(MESSAGE_ADD_CLIENT_WRONG_FORMAT); + } catch (IncorrectFlagOrderException e) { + throw new IncorrectFlagOrderException(MESSAGE_ADD_CLIENT_WRONG_FORMAT); + } catch (InvalidContactNumberException e) { + throw new InvalidContactNumberException(MESSAGE_INVALID_CONTACT_NUMBER); + } catch (EmptyDetailException e) { + throw new EmptyDetailException(MESSAGE_ADD_CLIENT_WRONG_FORMAT); + } catch (InvalidEmailException e) { + throw new InvalidEmailException(MESSAGE_INVALID_EMAIL); + } catch (InvalidBudgetFormatException e) { + throw new InvalidBudgetFormatException(MESSAGE_INVALID_BUDGET_FORMAT); + } + } + + + private void validatePropertyDetails(ArrayList propertyDetails) throws EmptyDetailException, InvalidSingaporeAddressException, InvalidPriceFormatException { //Checks for Missing Landlord Name, Property Address, Renting Price (SGD/month) and Unit-Type for (String propertyDetail : propertyDetails) { - checkForMissingPropertyDetails(propertyDetail); + checkForEmptyDetails(propertyDetail); } //Checks Format for Address (Singapore) and Renting Price @@ -361,12 +368,12 @@ private void validatePropertyDetails(ArrayList propertyDetails) throws M checkForPriceNumberFormat(propertyDetails.get(2)); } - private void validateClientDetails(ArrayList clientDetails) throws MissingClientDetailException, + private void validateClientDetails(ArrayList clientDetails) throws EmptyDetailException, InvalidContactNumberException, InvalidEmailException, InvalidBudgetFormatException { //Checks for Missing Client Name, Contact Number, Budget Per Month (SGD) - checkForMissingClientDetails(clientDetails.get(0)); - checkForMissingClientDetails(clientDetails.get(1)); - checkForMissingClientDetails(clientDetails.get(3)); + checkForEmptyDetails(clientDetails.get(0)); + checkForEmptyDetails(clientDetails.get(1)); + checkForEmptyDetails(clientDetails.get(3)); //Checks for Contact Number, Email and Budget Format checkForValidSingaporeContactNumber(clientDetails.get(1)); @@ -377,31 +384,13 @@ private void validateClientDetails(ArrayList clientDetails) throws Missi checkForBudgetNumberFormat(clientDetails.get(3)); } - private void checkForMissingPropertyDetails(String propertyDetail) throws MissingPropertyDetailException { - boolean isEmptyDetail = checkForEmptyDetail(propertyDetail); - if (isEmptyDetail) { - throw new MissingPropertyDetailException(); - } - } - - private void checkForMissingClientDetails(String clientDetail) throws MissingClientDetailException { - boolean isEmptyDetail = checkForEmptyDetail(clientDetail); - if (isEmptyDetail) { - throw new MissingClientDetailException(); - } - } - - private boolean checkForEmptyDetail(String commandDetails) { - return commandDetails.trim().isEmpty(); - } - private void checkForValidSingaporeAddress(String address) throws InvalidSingaporeAddressException { boolean hasValidSingaporeLandedPropertyAddress = checkForValidSingaporeLandedPropertyAddress(address); boolean hasValidSingaporeBuildingAddress = checkForValidSingaporeBuildingAddress(address); boolean hasValidSingaporeAddress = hasValidSingaporeLandedPropertyAddress || hasValidSingaporeBuildingAddress; if (!hasValidSingaporeAddress) { - throw new InvalidSingaporeAddressException(); + throw new InvalidSingaporeAddressException(EXCEPTION); } } @@ -458,14 +447,14 @@ private void checkForPriceNumberFormat(String budget) throws InvalidPriceFormatE String regex = "^[1-9]\\d*$"; boolean hasValidPriceNumberFormat = checkForDetailFormat(regex, budget); if (!hasValidPriceNumberFormat) { - throw new InvalidPriceFormatException(); + throw new InvalidPriceFormatException(EXCEPTION); } } private void checkForValidSingaporeContactNumber(String clientContactNumber) throws InvalidContactNumberException { boolean hasValidContactNumber = checkForDetailFormat("^[689]\\d{7}$", clientContactNumber); if (!hasValidContactNumber) { - throw new InvalidContactNumberException(); + throw new InvalidContactNumberException(EXCEPTION); } } @@ -478,7 +467,7 @@ private void checkForValidEmail(String clientEmail) throws InvalidEmailException + "c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])"; boolean hasValidContactNumber = checkForDetailFormat(regex, clientEmail); if (!hasValidContactNumber) { - throw new InvalidEmailException(); + throw new InvalidEmailException(EXCEPTION); } } @@ -487,7 +476,7 @@ private void checkForBudgetNumberFormat(String budget) throws InvalidBudgetForma String regex = "^[1-9]\\d*$"; boolean hasValidBudgetNumberFormat = checkForDetailFormat(regex, budget); if (!hasValidBudgetNumberFormat) { - throw new InvalidBudgetFormatException(); + throw new InvalidBudgetFormatException(EXCEPTION); } } @@ -500,290 +489,215 @@ private boolean checkForDetailFormat(String regex, String detail) { /* Delete Property/Client Parse Section */ - private void checkForEmptyCommandDeleteDetails(String commandAddDetails) throws EmptyCommandDeleteDetailException { - boolean isEmptyCommandAddDetail = checkForEmptyDetail(commandAddDetails); - if (isEmptyCommandAddDetail) { - throw new EmptyCommandDeleteDetailException(); - } - } + private Command prepareForCommandDeleteClient(String rawCommandDescription) throws InvalidIndexException, + MissingFlagException, IncorrectFlagOrderException, NotIntegerException, EmptyDetailException { + try { + checkForEmptyDetails(rawCommandDescription); - private int getClientIndexToDelete(String commandDetails) throws EmptyClientIndexDeleteException { - if (commandDetails.isEmpty()) { - throw new EmptyClientIndexDeleteException(); - } - return Integer.parseInt(commandDetails.trim()) - 1; - } + ArrayList deleteClientDetailsString = processCommandDetails(rawCommandDescription, DELETE_CLIENT_FLAGS); + ArrayList deleteClientDetailsInt = convertProcessedCommandDetailsToInteger(deleteClientDetailsString); - private Command prepareForCommandList(String commandDetails) throws IncorrectListDetailsException { - if (commandDetails.trim().equals("-client")) { - return new CommandListClients(); - } else if (commandDetails.trim().equals("-property")) { - return new CommandListProperties(); - } else { - throw new IncorrectListDetailsException(); - } - } + int clientIndex = deleteClientDetailsInt.get(0); + checkForInvalidClientIndexDelete(clientIndex); + return new CommandDeleteClient(clientIndex); - private void checkForClientIndexFlag(String commandDetails) - throws MissingClientIndexFlagException, InvalidClientIndexFlagFormatException { - if (!commandDetails.contains("ic/")) { - throw new MissingClientIndexFlagException(); - } else { - String clientIndexFlag = commandDetails.substring(0, 3); - if (!clientIndexFlag.equals("ic/")) { - throw new InvalidClientIndexFlagFormatException(); - } + } catch (InvalidIndexException e) { + throw new InvalidIndexException(MESSAGE_INVALID_INDEX); + } catch (MissingFlagException e) { + throw new MissingFlagException(MESSAGE_DELETE_CLIENT_WRONG_FORMAT); + } catch (IncorrectFlagOrderException e) { + throw new IncorrectFlagOrderException(MESSAGE_DELETE_CLIENT_WRONG_FORMAT); + } catch (NotIntegerException e) { + throw new NotIntegerException(MESSAGE_NOT_INTEGER); + } catch (EmptyDetailException e) { + throw new EmptyDetailException(MESSAGE_DELETE_CLIENT_WRONG_FORMAT); } } - private Command prepareForCommandDeleteClient(int clientIndex, ClientList clientList) - throws InvalidClientIndexDeleteException { - checkForInvalidClientIndexDelete(clientIndex, clientList); - return new CommandDeleteClient(clientIndex); - } - - private void checkForInvalidClientIndexDelete(int clientIndex, ClientList clientList) - throws InvalidClientIndexDeleteException { + private void checkForInvalidClientIndexDelete(int clientIndex) throws InvalidIndexException { int currentListSize = clientList.getCurrentListSize(); if (clientIndex < 0 || clientIndex >= currentListSize) { - throw new InvalidClientIndexDeleteException(); + throw new InvalidIndexException(EXCEPTION); } } - private int getPropertyIndexToDelete(String commandDetails) throws EmptyPropertyIndexDeleteException { - if (commandDetails.isEmpty()) { - throw new EmptyPropertyIndexDeleteException(); - } - return Integer.parseInt(commandDetails.trim()) - 1; - } - private void checkForPropertyIndexFlag(String commandDetails) - throws MissingPropertyIndexFlagException, InvalidPropertyIndexFlagFormatException { - if (!commandDetails.contains("ip/")) { - throw new MissingPropertyIndexFlagException(); - } else { - String clientIndexFlag = commandDetails.substring(0, 3); - if (!clientIndexFlag.equals("ip/")) { - throw new InvalidPropertyIndexFlagFormatException(); - } - } - } + private Command prepareForCommandDeleteProperty(String rawCommandDescription) throws MissingFlagException, + InvalidIndexException, IncorrectFlagOrderException, NotIntegerException, EmptyDetailException { - private Command prepareForCommandDeleteProperty(int propertyIndex, PropertyList propertyList) - throws InvalidPropertyIndexDeleteException { - checkForInvalidPropertyIndexDelete(propertyIndex, propertyList); - return new CommandDeleteProperty(propertyIndex); + try { + checkForEmptyDetails(rawCommandDescription); + ArrayList deletePropertyDetailsString = processCommandDetails(rawCommandDescription, + DELETE_PROPERTY_FLAGS); + ArrayList deletePropertyDetailsInt = convertProcessedCommandDetailsToInteger( + deletePropertyDetailsString); + + int propertyIndex = deletePropertyDetailsInt.get(0); + checkForInvalidPropertyIndexDelete(propertyIndex); + return new CommandDeleteProperty(propertyIndex); + } catch (InvalidIndexException e) { + throw new InvalidIndexException(MESSAGE_INVALID_INDEX); + } catch (MissingFlagException e) { + throw new MissingFlagException(MESSAGE_DELETE_PROPERTY_WRONG_FORMAT); + } catch (IncorrectFlagOrderException e) { + throw new IncorrectFlagOrderException(MESSAGE_DELETE_PROPERTY_WRONG_FORMAT); + } catch (NotIntegerException e) { + throw new NotIntegerException(MESSAGE_NOT_INTEGER); + } catch (EmptyDetailException e) { + throw new EmptyDetailException(MESSAGE_DELETE_PROPERTY_WRONG_FORMAT); + } } - private void checkForInvalidPropertyIndexDelete(int propertyIndex, PropertyList propertyList) - throws InvalidPropertyIndexDeleteException { + private void checkForInvalidPropertyIndexDelete(int propertyIndex) throws InvalidIndexException { int currentListSize = propertyList.getCurrentListSize(); if (propertyIndex < 0 || propertyIndex >= currentListSize) { - throw new InvalidPropertyIndexDeleteException(); + throw new InvalidIndexException(EXCEPTION); } } /* Pair/Unpair Parse Section */ - private void checkForEmptyCommandPairUnpairDetails(String commandPairUnpairDetails) - throws EmptyCommandPairUnpairDetailsException { - boolean isEmptyCommandPairUnpairDetail = checkForEmptyDetail(commandPairUnpairDetails); - if (isEmptyCommandPairUnpairDetail) { - throw new EmptyCommandPairUnpairDetailsException(); - } - } - - private Command prepareForCommandPair(String rawPairDescriptions) throws NotIntegerException, - InvalidIndexException, MissingPairUnpairFlagException, IncorrectPairUnpairFlagOrderException, - ClientAlreadyPairedException, AlreadyPairedException { - ArrayList pairDetails = processPairUnpairDetails(rawPairDescriptions); - validatePairDetails(pairDetails); - return new CommandPair(pairDetails); - } - - private Command prepareForCommandUnpair(String rawUnpairDescriptions) throws NotIntegerException, - InvalidIndexException, MissingPairUnpairFlagException, IncorrectPairUnpairFlagOrderException, - NoExistingPairException { - ArrayList unpairDetails = processPairUnpairDetails(rawUnpairDescriptions); - validateUnpairDetails(unpairDetails); - return new CommandUnpair(unpairDetails); - } - - private ArrayList processPairUnpairDetails(String rawPairUnpairDetails) - throws MissingPairUnpairFlagException, IncorrectPairUnpairFlagOrderException, NotIntegerException { - String[] pairUnpairFlags = {"ip/", "ic/"}; - int[] pairUnpairFlagIndexPositions = new int[PAIR_UNPAIR_FLAG_SIZE]; + private Command prepareForCommandPair(String rawPairDescriptions) throws MissingFlagException, + InvalidIndexException, ClientAlreadyPairedException, IncorrectFlagOrderException, NotIntegerException, + ExistingPairException { - for (int i = 0; i < pairUnpairFlags.length; i++) { - pairUnpairFlagIndexPositions[i] = rawPairUnpairDetails.indexOf(pairUnpairFlags[i]); - } - - checkForMissingPairUnpairFlags(pairUnpairFlagIndexPositions); - checkForPairUnpairFlagsOrder(pairUnpairFlagIndexPositions); - return extractPairUnpairDetails(rawPairUnpairDetails, pairUnpairFlagIndexPositions, pairUnpairFlags); - } - - private void checkForMissingPairUnpairFlags(int[] pairUnpairFlagIndexPosition) - throws MissingPairUnpairFlagException { try { - for (int flagIndex : pairUnpairFlagIndexPosition) { - checkForEssentialAddFlag(flagIndex); - } + ArrayList pairDetailsString = processCommandDetails(rawPairDescriptions, PAIR_FLAGS); + ArrayList pairDetailsInt = convertProcessedCommandDetailsToInteger(pairDetailsString); + + validatePairDetails(pairDetailsInt); + return new CommandPair(pairDetailsInt); + } catch (InvalidIndexException e) { + throw new InvalidIndexException(MESSAGE_INVALID_INDEX); + } catch (ClientAlreadyPairedException e) { + throw new ClientAlreadyPairedException(MESSAGE_CLIENT_ALREADY_PAIRED); } catch (MissingFlagException e) { - throw new MissingPairUnpairFlagException(); - } - } - - private void checkForPairUnpairFlagsOrder(int[] pairUnpairFlagIndexPosition) - throws IncorrectPairUnpairFlagOrderException { - try { - checkForCorrectFlagOrder(pairUnpairFlagIndexPosition[0], pairUnpairFlagIndexPosition[1]); + throw new MissingFlagException(MESSAGE_PAIR_WRONG_FORMAT); } catch (IncorrectFlagOrderException e) { - throw new IncorrectPairUnpairFlagOrderException(); + throw new IncorrectFlagOrderException(MESSAGE_PAIR_WRONG_FORMAT); + } catch (NotIntegerException e) { + throw new NotIntegerException(MESSAGE_NOT_INTEGER); + } catch (ExistingPairException e) { + throw new ExistingPairException(MESSAGE_EXISTING_PAIR); } } - private ArrayList extractPairUnpairDetails(String rawPairUnpairDetails, int[] pairFlagIndexPositions, - String[] pairUnpairFlags) throws NotIntegerException { - String propertyIndexString = extractDetail(rawPairUnpairDetails, - pairFlagIndexPositions[0] + pairUnpairFlags[0].length(), - pairFlagIndexPositions[1]); - - String clientIndexString = extractDetail(rawPairUnpairDetails, - pairFlagIndexPositions[1] + pairUnpairFlags[1].length()); - - int propertyIndex; - int clientIndex; + private Command prepareForCommandUnpair(String rawUnpairDescriptions) throws MissingFlagException, + IncorrectFlagOrderException, NotIntegerException, InvalidIndexException, NoExistingPairException { try { - propertyIndex = Integer.parseInt(propertyIndexString); - clientIndex = Integer.parseInt(clientIndexString); - } catch (NumberFormatException e) { - throw new NotIntegerException(); + ArrayList unpairDetailsString = processCommandDetails(rawUnpairDescriptions, UNPAIR_FLAGS); + ArrayList unpairDetailsInt = convertProcessedCommandDetailsToInteger(unpairDetailsString); + + validateUnpairDetails(unpairDetailsInt); + return new CommandUnpair(unpairDetailsInt); + } catch (InvalidIndexException e) { + throw new InvalidIndexException(MESSAGE_INVALID_INDEX); + } catch (NoExistingPairException e) { + throw new NoExistingPairException(MESSAGE_NO_EXISTING_PAIR); + } catch (MissingFlagException e) { + throw new MissingFlagException(MESSAGE_UNPAIR_WRONG_FORMAT); + } catch (IncorrectFlagOrderException e) { + throw new IncorrectFlagOrderException(MESSAGE_UNPAIR_WRONG_FORMAT); + } catch (NotIntegerException e) { + throw new NotIntegerException(MESSAGE_NOT_INTEGER); } - - ArrayList processedPairUnpairDetails = new ArrayList<>(); - processedPairUnpairDetails.add(clientIndex - 1); // convert to 0-index - processedPairUnpairDetails.add(propertyIndex - 1); - return processedPairUnpairDetails; } - private void validatePairDetails(ArrayList pairUnpairDetails) throws InvalidIndexException, - ClientAlreadyPairedException, AlreadyPairedException { - int clientIndex = pairUnpairDetails.get(0); - int propertyIndex = pairUnpairDetails.get(1); - checkForClientPropertyListIndexOutOfBounds(clientIndex, propertyIndex); + + private void validatePairDetails(ArrayList pairDetails) throws InvalidIndexException, + ClientAlreadyPairedException, ExistingPairException { + int propertyIndex = pairDetails.get(0); + int clientIndex = pairDetails.get(1); + checkForClientListIndexOutOfBounds(clientIndex); + checkForPropertyListIndexOutOfBounds(propertyIndex); Client client = clientList.getClientList().get(clientIndex); Property property = propertyList.getPropertyList().get(propertyIndex); if (pairingList.isAlreadyPaired(client, property)) { - throw new AlreadyPairedException(); + throw new ExistingPairException(EXCEPTION); } if (pairingList.isClientPairedWithProperty(client)) { - throw new ClientAlreadyPairedException(); + throw new ClientAlreadyPairedException(EXCEPTION); } } - private void validateUnpairDetails(ArrayList pairUnpairDetails) throws InvalidIndexException, + private void validateUnpairDetails(ArrayList UnpairDetails) throws InvalidIndexException, NoExistingPairException { - int clientIndex = pairUnpairDetails.get(0); - int propertyIndex = pairUnpairDetails.get(1); - checkForClientPropertyListIndexOutOfBounds(clientIndex, propertyIndex); + int propertyIndex = UnpairDetails.get(0); + int clientIndex = UnpairDetails.get(1); + + checkForClientListIndexOutOfBounds(clientIndex); + checkForPropertyListIndexOutOfBounds(propertyIndex); Client client = clientList.getClientList().get(clientIndex); Property property = propertyList.getPropertyList().get(propertyIndex); if (!pairingList.isAlreadyPaired(client, property)) { - throw new NoExistingPairException(); + throw new NoExistingPairException(EXCEPTION); } } - private void checkForClientPropertyListIndexOutOfBounds(int clientIndex, int propertyIndex) - throws InvalidIndexException { - checkForClientListIndexOutOfBounds(clientIndex); - checkForPropertyListIndexOutOfBounds(propertyIndex); - } + + /* Check client/property parse Section */ private void checkForPropertyListIndexOutOfBounds(int propertyIndex) throws InvalidIndexException { if (propertyIndex < 0 || propertyIndex > propertyList.getCurrentListSize() - 1) { - throw new InvalidIndexException(); + throw new InvalidIndexException(EXCEPTION); } } private void checkForClientListIndexOutOfBounds(int clientIndex) throws InvalidIndexException { if (clientIndex < 0 || clientIndex > clientList.getCurrentListSize() - 1) { - throw new InvalidIndexException(); + throw new InvalidIndexException(EXCEPTION); } } - private Command prepareForCommandCheckProperty(String rawPropertyDescriptions) throws NotIntegerException, - InvalidIndexException, MissingCheckPropertyFlagException { + private Command prepareForCommandCheckProperty(String rawCheckDescriptions) throws InvalidIndexException, + MissingFlagException, IncorrectFlagOrderException, NotIntegerException { + try { - ArrayList checkPropertyDetails = processCheckPropertyDetails(rawPropertyDescriptions); - validateCheckPropertyDetails(checkPropertyDetails); - return new CommandCheckProperty(checkPropertyDetails); - } catch (MissingFlagException e) { - throw new MissingCheckPropertyFlagException(); - } - } + ArrayList checkDetailsString = processCommandDetails(rawCheckDescriptions, CHECK_PROPERTY_FLAGS); + ArrayList checkDetailsInt = convertProcessedCommandDetailsToInteger(checkDetailsString); - private void checkForEmptyCommandCheckDetails(String commandCheckDetails) throws EmptyCommandCheckDetailException { - boolean isEmptyCommandCheckDetail = checkForEmptyDetail(commandCheckDetails); - if (isEmptyCommandCheckDetail) { - throw new EmptyCommandCheckDetailException(); + validateCheckPropertyDetails(checkDetailsInt); + return new CommandCheckProperty(checkDetailsInt); + } catch (InvalidIndexException e) { + throw new InvalidIndexException(MESSAGE_INVALID_INDEX); + } catch (MissingFlagException e) { + throw new MissingFlagException(MESSAGE_CHECK_PROPERTY_WRONG_FORMAT); + } catch (IncorrectFlagOrderException e) { + throw new IncorrectFlagOrderException(MESSAGE_CHECK_PROPERTY_WRONG_FORMAT); + } catch (NotIntegerException e) { + throw new NotIntegerException(MESSAGE_NOT_INTEGER); } } - private ArrayList processCheckPropertyDetails(String rawPropertyDetails) throws MissingFlagException, - NotIntegerException { - String[] checkPropertyFlags = {"ip/"}; - int[] checkPropertyFlagIndexPositions = new int[CHECK_PROPERTY_FLAG_SIZE]; - for (int i = 0; i < checkPropertyFlags.length; i++) { - checkPropertyFlagIndexPositions[i] = rawPropertyDetails.indexOf(checkPropertyFlags[i]); - } - - checkForMissingCheckPropertyFlags(checkPropertyFlagIndexPositions); - return extractCheckPropertyDetails(rawPropertyDetails, checkPropertyFlagIndexPositions, checkPropertyFlags); + private void validateCheckPropertyDetails(ArrayList checkPropertyDetails) throws InvalidIndexException { + int propertyIndex = checkPropertyDetails.get(0); + checkForPropertyListIndexOutOfBounds(propertyIndex); } - private void checkForMissingCheckPropertyFlags(int[] checkPropertyFlagIndexPositions) throws MissingFlagException { - checkForEssentialCheckPropertyFlag(checkPropertyFlagIndexPositions[0]); - } - private void checkForEssentialCheckPropertyFlag(int checkPropertyFlagIndexPosition) throws MissingFlagException { - boolean hasFlag = (checkPropertyFlagIndexPosition != -1); - if (!hasFlag) { - throw new MissingFlagException(); - } - } + /* List Property/Client Parse Section */ - private ArrayList extractCheckPropertyDetails(String rawPropertyDetails, - int[] checkPropertyFlagIndexPositions, String[] checkFlags) throws NotIntegerException { - String propertyIndexString = extractDetail(rawPropertyDetails, - checkPropertyFlagIndexPositions[0] + checkFlags[0].length()); - int propertyIndex; - try { - propertyIndex = Integer.parseInt(propertyIndexString); - } catch (NumberFormatException e) { - throw new NotIntegerException(); + private Command prepareForCommandList(String commandDetails) throws UndefinedSubCommandTypeException { + if (commandDetails.trim().equals("-client")) { + return new CommandListClients(); + } else if (commandDetails.trim().equals("-property")) { + return new CommandListProperties(); + } else { + throw new UndefinedSubCommandTypeException(MESSAGE_INCORRECT_LIST_DETAILS); } - ArrayList processedCheckPropertyDetails = new ArrayList<>(); - processedCheckPropertyDetails.add(propertyIndex - 1); - return processedCheckPropertyDetails; - } - - private void validateCheckPropertyDetails(ArrayList checkPropertyDetails) throws InvalidIndexException { - int propertyIndex = checkPropertyDetails.get(0); - checkForPropertyListIndexOutOfBounds(propertyIndex); } - private void checkForByeParameters(String commandDetails) throws ByeParametersPresentException { + private void checkForByeParameters(String commandDetails) throws ExtraParametersException { if (!commandDetails.trim().isEmpty()) { - throw new ByeParametersPresentException(); + throw new ExtraParametersException(MESSAGE_BYE_PARAMETERS_PRESENT); } } diff --git a/src/main/java/seedu/duke/ParserCommandAddClient.java b/src/main/java/seedu/duke/ParserCommandAddClient.java new file mode 100644 index 000000000..0203226e1 --- /dev/null +++ b/src/main/java/seedu/duke/ParserCommandAddClient.java @@ -0,0 +1,4 @@ +package seedu.duke; + +public class ParserCommandAddClient { +} diff --git a/src/main/java/seedu/duke/ParserCommandAddProperty.java b/src/main/java/seedu/duke/ParserCommandAddProperty.java new file mode 100644 index 000000000..7f35aefa1 --- /dev/null +++ b/src/main/java/seedu/duke/ParserCommandAddProperty.java @@ -0,0 +1,4 @@ +package seedu.duke; + +public class ParserCommandAddProperty { +} diff --git a/src/main/java/seedu/duke/ParserCommandDelete.java b/src/main/java/seedu/duke/ParserCommandDelete.java new file mode 100644 index 000000000..e7c3fe650 --- /dev/null +++ b/src/main/java/seedu/duke/ParserCommandDelete.java @@ -0,0 +1,4 @@ +package seedu.duke; + +public class ParserCommandDelete { +} diff --git a/src/main/java/seedu/duke/ParserCommandExit.java b/src/main/java/seedu/duke/ParserCommandExit.java new file mode 100644 index 000000000..1cf774b52 --- /dev/null +++ b/src/main/java/seedu/duke/ParserCommandExit.java @@ -0,0 +1,4 @@ +package seedu.duke; + +public class ParserCommandExit { +} diff --git a/src/main/java/seedu/duke/ParserCommandList.java b/src/main/java/seedu/duke/ParserCommandList.java new file mode 100644 index 000000000..db4c8876b --- /dev/null +++ b/src/main/java/seedu/duke/ParserCommandList.java @@ -0,0 +1,4 @@ +package seedu.duke; + +public class ParserCommandList { +} diff --git a/src/main/java/seedu/duke/ParserCommandPair.java b/src/main/java/seedu/duke/ParserCommandPair.java new file mode 100644 index 000000000..9b0661d76 --- /dev/null +++ b/src/main/java/seedu/duke/ParserCommandPair.java @@ -0,0 +1,4 @@ +package seedu.duke; + +public class ParserCommandPair { +} diff --git a/src/main/java/seedu/duke/ParserCommandUnpair.java b/src/main/java/seedu/duke/ParserCommandUnpair.java new file mode 100644 index 000000000..2d5b3608d --- /dev/null +++ b/src/main/java/seedu/duke/ParserCommandUnpair.java @@ -0,0 +1,4 @@ +package seedu.duke; + +public class ParserCommandUnpair { +} diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index 7d05f1c18..808eedd5a 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -1,58 +1,22 @@ package seedu.duke; +import seedu.duke.exception.DukeException; + import java.util.ArrayList; import java.util.Scanner; -import static seedu.duke.Messages.MESSAGE_ALREADY_PAIRED; -import static seedu.duke.Messages.MESSAGE_EMPTY_PROPERTY_INDEX; -import static seedu.duke.Messages.MESSAGE_INVALID_PROPERTY_INDEX; -import static seedu.duke.Messages.MESSAGE_INVALID_PROPERTY_INDEX_FLAG_FORMAT; -import static seedu.duke.Messages.MESSAGE_MISSING_PROPERTY_INDEX_FLAG; -import static seedu.duke.Messages.MESSAGE_PROPERTY_DELETED; -import static seedu.duke.Messages.MESSAGE_WELCOME; -import static seedu.duke.Messages.MESSAGE_PROPERTY_ADDED; -import static seedu.duke.Messages.MESSAGE_ADD_CLIENT_WRONG_FORMAT; +import static seedu.duke.Messages.LINE_BREAK; import static seedu.duke.Messages.MESSAGE_CHECK_PROPERTY_RESULT; -import static seedu.duke.Messages.MESSAGE_CHECK_PROPERTY_WRONG_FORMAT; import static seedu.duke.Messages.MESSAGE_CLIENT_ADDED; -import static seedu.duke.Messages.MESSAGE_CLIENT_ALREADY_PAIRED; import static seedu.duke.Messages.MESSAGE_CLIENT_DELETED; -import static seedu.duke.Messages.MESSAGE_CLIENT_INPUT_EXAMPLE; import static seedu.duke.Messages.MESSAGE_COMMAND_UNDEFINED; -import static seedu.duke.Messages.MESSAGE_EMPTY_ADD_DESCRIPTION; -import static seedu.duke.Messages.MESSAGE_EMPTY_CHECK_DESCRIPTION; +import static seedu.duke.Messages.MESSAGE_NUMBER_OF_LIST_RESULTS; import static seedu.duke.Messages.MESSAGE_PAIRED; +import static seedu.duke.Messages.MESSAGE_PROPERTY_ADDED; +import static seedu.duke.Messages.MESSAGE_PROPERTY_DELETED; import static seedu.duke.Messages.MESSAGE_UNPAIRED; -import static seedu.duke.Messages.MESSAGE_NO_EXISTING_PAIR; -import static seedu.duke.Messages.MESSAGE_MISSING_SUB_COMMAND_TYPE_FOR_ADD; -import static seedu.duke.Messages.MESSAGE_EMPTY_PROPERTY_DESCRIPTION; -import static seedu.duke.Messages.MESSAGE_EMPTY_CLIENT_DESCRIPTION; -import static seedu.duke.Messages.MESSAGE_EMPTY_COMMAND_PAIR_UNPAIR; -import static seedu.duke.Messages.MESSAGE_EMPTY_CLIENT_INDEX; -import static seedu.duke.Messages.MESSAGE_EMPTY_DELETE_DESCRIPTION; -import static seedu.duke.Messages.MESSAGE_INVALID_BUDGET_FORMAT; -import static seedu.duke.Messages.MESSAGE_INVALID_CLIENT_INDEX; -import static seedu.duke.Messages.MESSAGE_INVALID_CLIENT_INDEX_FLAG_FORMAT; -import static seedu.duke.Messages.MESSAGE_INVALID_CONTACT_NUMBER; -import static seedu.duke.Messages.MESSAGE_INVALID_EMAIL; -import static seedu.duke.Messages.MESSAGE_MISSING_CLIENT_INDEX_FLAG; -import static seedu.duke.Messages.MESSAGE_MISSING_SUB_COMMAND_TYPE_FOR_CHECK; -import static seedu.duke.Messages.MESSAGE_MISSING_SUB_COMMAND_TYPE_FOR_DELETE; -import static seedu.duke.Messages.MESSAGE_NUMBER_OF_LIST_RESULTS; -import static seedu.duke.Messages.MESSAGE_TRY_AGAIN; -import static seedu.duke.Messages.MESSAGE_NOT_INTEGER; -import static seedu.duke.Messages.MESSAGE_ADD_PROPERTY_WRONG_FORMAT; -import static seedu.duke.Messages.MESSAGE_PROPERTY_INPUT_EXAMPLE; -import static seedu.duke.Messages.MESSAGE_INVALID_SINGAPORE_ADDRESS; -import static seedu.duke.Messages.MESSAGE_VALID_SINGAPORE_ADDRESS_EXAMPLE; -import static seedu.duke.Messages.MESSAGE_INVALID_PRICE_FORMAT; -import static seedu.duke.Messages.MESSAGE_NOT_VALID_INDEX; -import static seedu.duke.Messages.MESSAGE_PAIR_UNPAIR_WRONG_FORMAT; -import static seedu.duke.Messages.MESSAGE_PAIR_UNPAIR_INPUT_EXAMPLE; -import static seedu.duke.Messages.MESSAGE_INCORRECT_LIST_DETAILS; -import static seedu.duke.Messages.MESSAGE_MISSING_LIST_DETAILS; -import static seedu.duke.Messages.LINE_BREAK; -import static seedu.duke.Messages.MESSAGE_BYE_PARAMETERS_PRESENT; +import static seedu.duke.Messages.MESSAGE_WELCOME; + /** * Handler for all interactions between the user and the command line. @@ -103,56 +67,6 @@ public void showClientAddedConfirmationMessage(ClientList clientList) { showToUser(" " + clientList.getClientList().get(currentListSize - 1)); } - public void showMissingCommandAddDetailMessage() { - showToUser(MESSAGE_EMPTY_ADD_DESCRIPTION); - } - - public void showUndefinedSubCommandAddTypeMessage() { - showToUser(MESSAGE_MISSING_SUB_COMMAND_TYPE_FOR_ADD); - } - - public void showAddPropertyWrongFormatMessage() { - showToUser(MESSAGE_ADD_PROPERTY_WRONG_FORMAT); - showToUser(MESSAGE_PROPERTY_INPUT_EXAMPLE); - showToUser(MESSAGE_TRY_AGAIN); - } - - public void showAddClientWrongFormatMessage() { - showToUser(MESSAGE_ADD_CLIENT_WRONG_FORMAT); - showToUser(MESSAGE_CLIENT_INPUT_EXAMPLE); - showToUser(MESSAGE_TRY_AGAIN); - } - - public void showInvalidSingaporeAddressMessage() { - showToUser(MESSAGE_INVALID_SINGAPORE_ADDRESS); - showToUser(MESSAGE_VALID_SINGAPORE_ADDRESS_EXAMPLE); - showToUser(MESSAGE_TRY_AGAIN); - } - - public void showInvalidPriceFormatMessage() { - showToUser(MESSAGE_INVALID_PRICE_FORMAT); - } - - public void showInvalidContactNumberMessage() { - showToUser(MESSAGE_INVALID_CONTACT_NUMBER); - } - - public void showInvalidEmailMessage() { - showToUser(MESSAGE_INVALID_EMAIL); - } - - public void showInvalidBudgetFormatMessage() { - showToUser(MESSAGE_INVALID_BUDGET_FORMAT); - } - - public void showEmptyPropertyDetailMessage() { - showToUser(MESSAGE_EMPTY_PROPERTY_DESCRIPTION); - } - - public void showEmptyClientDetailMessage() { - showToUser(MESSAGE_EMPTY_CLIENT_DESCRIPTION); - } - /* Delete-Command-related showMessage methods. */ @@ -166,46 +80,6 @@ public void showClientDeletedConfirmationMessage(Client deletedClient) { showToUser(" " + deletedClient); } - public void showUndefinedSubCommandDeleteTypeMessage() { - showToUser(MESSAGE_MISSING_SUB_COMMAND_TYPE_FOR_DELETE); - } - - public void showMissingCommandDeleteDetailMessage() { - showToUser(MESSAGE_EMPTY_DELETE_DESCRIPTION); - } - - public void showInvalidPropertyIndexDeleteMessage() { - showToUser(MESSAGE_INVALID_PROPERTY_INDEX); - } - - public void showEmptyPropertyIndexDeleteMessage() { - showToUser(MESSAGE_EMPTY_PROPERTY_INDEX); - } - - public void showMissingPropertyIndexFlagMessage() { - showToUser(MESSAGE_MISSING_PROPERTY_INDEX_FLAG); - } - - public void showInvalidPropertyIndexFlagFormatMessage() { - showToUser(MESSAGE_INVALID_PROPERTY_INDEX_FLAG_FORMAT); - } - - public void showInvalidClientIndexDeleteMessage() { - showToUser(MESSAGE_INVALID_CLIENT_INDEX); - } - - public void showEmptyClientIndexDeleteMessage() { - showToUser(MESSAGE_EMPTY_CLIENT_INDEX); - } - - public void showMissingClientIndexFlagMessage() { - showToUser(MESSAGE_MISSING_CLIENT_INDEX_FLAG); - } - - public void showInvalidClientIndexFlagFormatMessage() { - showToUser(MESSAGE_INVALID_CLIENT_INDEX_FLAG_FORMAT); - } - /* Pair/Unpair-Command-related showMessage methods. */ @@ -219,51 +93,9 @@ public void showUnpairedConfirmationMessage(Client client, Property property) { showToUser(" " + client.getClientName() + " and " + property.getPropertyAddress()); } - public void showEmptyCommandPairUnpairDetailsMessage() { - showToUser(MESSAGE_EMPTY_COMMAND_PAIR_UNPAIR); - } - - public void showNotValidIndexMessage() { - showToUser(MESSAGE_NOT_VALID_INDEX); - } - - public void showNotIntegerMessage() { - showToUser(MESSAGE_NOT_INTEGER); - } - - public void showPairUnpairWrongFormatMessage() { - showToUser(MESSAGE_PAIR_UNPAIR_WRONG_FORMAT); - showToUser(MESSAGE_PAIR_UNPAIR_INPUT_EXAMPLE); - showToUser(MESSAGE_TRY_AGAIN); - } - - public void showClientAlreadyPairedMessage() { - showToUser(MESSAGE_CLIENT_ALREADY_PAIRED); - } - - public void showAlreadyPairedMessage() { - showToUser(MESSAGE_ALREADY_PAIRED); - } - - public void showNoExistingPairMessage() { - showToUser(MESSAGE_NO_EXISTING_PAIR); - } - /* Check-Command-related showMessage methods. */ - public void showCheckPropertyWrongFormatMessage() { - showToUser(MESSAGE_CHECK_PROPERTY_WRONG_FORMAT); - } - - public void showUndefinedSubCommandCheckTypeMessage() { - showToUser(MESSAGE_MISSING_SUB_COMMAND_TYPE_FOR_CHECK); - } - - public void showEmptyCommandCheckDetailException() { - showToUser(MESSAGE_EMPTY_CHECK_DESCRIPTION); - } - public void displayOneClient(Client client, int i) { System.out.println(i + "."); System.out.println(client.toString()); @@ -276,27 +108,18 @@ public void displayOneProperty(Property property, int i) { System.out.println(LINE_BREAK); } - public void showByeParametersPresentMessage() { - showToUser(MESSAGE_BYE_PARAMETERS_PRESENT); - } - - public void showIncorrectListDetailsMessage() { - showToUser(MESSAGE_INCORRECT_LIST_DETAILS); - } - - public void showMissingListDetailsMessage() { - showToUser(MESSAGE_MISSING_LIST_DETAILS); - } - public void showCheckProperty(ArrayList tenants) { showToUser(MESSAGE_CHECK_PROPERTY_RESULT); int count = 0; for (Client tenant : tenants) { - // Remove brackets at first and last indexes of tenant(client) string - String tenantInfo = tenant.toString().substring(1, tenant.toString().length() - 1); + String tenantInfo = tenant.toString(); showToUser(String.format(" %d. %s", ++count, tenantInfo)); } showToUser(MESSAGE_NUMBER_OF_LIST_RESULTS + count); } + + public void showExceptionMessage(DukeException e) { + showToUser(e.toString()); + } } diff --git a/src/main/java/seedu/duke/command/CommandPair.java b/src/main/java/seedu/duke/command/CommandPair.java index fa9d98987..d68ff63e3 100644 --- a/src/main/java/seedu/duke/command/CommandPair.java +++ b/src/main/java/seedu/duke/command/CommandPair.java @@ -25,8 +25,8 @@ public class CommandPair extends Command { * @param commandPairDetails Parsed client and property indexes from the user's input. */ public CommandPair(ArrayList commandPairDetails) { - this.clientIndex = commandPairDetails.get(0); - this.propertyIndex = commandPairDetails.get(1); + this.propertyIndex = commandPairDetails.get(0); + this.clientIndex = commandPairDetails.get(1); } /** diff --git a/src/main/java/seedu/duke/command/CommandUnpair.java b/src/main/java/seedu/duke/command/CommandUnpair.java index 7fa59a504..7eac38b44 100644 --- a/src/main/java/seedu/duke/command/CommandUnpair.java +++ b/src/main/java/seedu/duke/command/CommandUnpair.java @@ -24,8 +24,8 @@ public class CommandUnpair extends Command { * @param commandUnpairDetails Parsed client and property indexes from the user's input. */ public CommandUnpair(ArrayList commandUnpairDetails) { - this.clientIndex = commandUnpairDetails.get(0); - this.propertyIndex = commandUnpairDetails.get(1); + this.propertyIndex = commandUnpairDetails.get(0); + this.clientIndex = commandUnpairDetails.get(1); } /** diff --git a/src/main/java/seedu/duke/exception/AlreadyPairedException.java b/src/main/java/seedu/duke/exception/AlreadyPairedException.java index f26daec7f..1612044ab 100644 --- a/src/main/java/seedu/duke/exception/AlreadyPairedException.java +++ b/src/main/java/seedu/duke/exception/AlreadyPairedException.java @@ -1,4 +1,15 @@ package seedu.duke.exception; -public class AlreadyPairedException extends DukeException { +public class AlreadyPairedException extends DukeCommandException { + + private final String message; + + public AlreadyPairedException(String message) { + this.message = message; + } + + @Override + public String toString() { + return message; + } } diff --git a/src/main/java/seedu/duke/exception/ByeParametersPresentException.java b/src/main/java/seedu/duke/exception/ByeParametersPresentException.java deleted file mode 100644 index 0ab4c2ac4..000000000 --- a/src/main/java/seedu/duke/exception/ByeParametersPresentException.java +++ /dev/null @@ -1,4 +0,0 @@ -package seedu.duke.exception; - -public class ByeParametersPresentException extends DukeException{ -} diff --git a/src/main/java/seedu/duke/exception/ClientAlreadyPairedException.java b/src/main/java/seedu/duke/exception/ClientAlreadyPairedException.java index 90269131b..57aef436c 100644 --- a/src/main/java/seedu/duke/exception/ClientAlreadyPairedException.java +++ b/src/main/java/seedu/duke/exception/ClientAlreadyPairedException.java @@ -1,4 +1,15 @@ package seedu.duke.exception; -public class ClientAlreadyPairedException extends DukeException { +public class ClientAlreadyPairedException extends DukeCommandException { + + private final String message; + + public ClientAlreadyPairedException(String message) { + this.message = message; + } + + @Override + public String toString() { + return message; + } } diff --git a/src/main/java/seedu/duke/exception/DukeCommandException.java b/src/main/java/seedu/duke/exception/DukeCommandException.java new file mode 100644 index 000000000..611cc7782 --- /dev/null +++ b/src/main/java/seedu/duke/exception/DukeCommandException.java @@ -0,0 +1,4 @@ +package seedu.duke.exception; + +public abstract class DukeCommandException extends DukeException { +} diff --git a/src/main/java/seedu/duke/exception/DukeException.java b/src/main/java/seedu/duke/exception/DukeException.java index 73913a7b4..5b6743d45 100644 --- a/src/main/java/seedu/duke/exception/DukeException.java +++ b/src/main/java/seedu/duke/exception/DukeException.java @@ -4,4 +4,5 @@ * Represents exceptions local to Duke. */ public abstract class DukeException extends Exception { + } diff --git a/src/main/java/seedu/duke/exception/DukeParseException.java b/src/main/java/seedu/duke/exception/DukeParseException.java new file mode 100644 index 000000000..1e797d945 --- /dev/null +++ b/src/main/java/seedu/duke/exception/DukeParseException.java @@ -0,0 +1,4 @@ +package seedu.duke.exception; + +public abstract class DukeParseException extends DukeException { +} diff --git a/src/main/java/seedu/duke/exception/EmptyClientDetailException.java b/src/main/java/seedu/duke/exception/EmptyClientDetailException.java deleted file mode 100644 index c91bf6170..000000000 --- a/src/main/java/seedu/duke/exception/EmptyClientDetailException.java +++ /dev/null @@ -1,7 +0,0 @@ -package seedu.duke.exception; - -/** - * Represents exception when no client description is given when adding client. - */ -public class EmptyClientDetailException extends DukeException { -} diff --git a/src/main/java/seedu/duke/exception/EmptyClientIndexDeleteException.java b/src/main/java/seedu/duke/exception/EmptyClientIndexDeleteException.java deleted file mode 100644 index f04e2ce20..000000000 --- a/src/main/java/seedu/duke/exception/EmptyClientIndexDeleteException.java +++ /dev/null @@ -1,7 +0,0 @@ -package seedu.duke.exception; - -/** - * Represents exception when client index to delete is empty. - */ -public class EmptyClientIndexDeleteException extends DukeException { -} diff --git a/src/main/java/seedu/duke/exception/EmptyCommandAddDetailException.java b/src/main/java/seedu/duke/exception/EmptyCommandAddDetailException.java deleted file mode 100644 index f67613046..000000000 --- a/src/main/java/seedu/duke/exception/EmptyCommandAddDetailException.java +++ /dev/null @@ -1,7 +0,0 @@ -package seedu.duke.exception; - -/** - * Represents exception when no information is provided when adding (property/client). - */ -public class EmptyCommandAddDetailException extends DukeException { -} diff --git a/src/main/java/seedu/duke/exception/EmptyCommandCheckDetailException.java b/src/main/java/seedu/duke/exception/EmptyCommandCheckDetailException.java deleted file mode 100644 index eb36169a4..000000000 --- a/src/main/java/seedu/duke/exception/EmptyCommandCheckDetailException.java +++ /dev/null @@ -1,4 +0,0 @@ -package seedu.duke.exception; - -public class EmptyCommandCheckDetailException extends DukeException { -} diff --git a/src/main/java/seedu/duke/exception/EmptyCommandDeleteDetailException.java b/src/main/java/seedu/duke/exception/EmptyCommandDeleteDetailException.java deleted file mode 100644 index 578061753..000000000 --- a/src/main/java/seedu/duke/exception/EmptyCommandDeleteDetailException.java +++ /dev/null @@ -1,7 +0,0 @@ -package seedu.duke.exception; - -/** - * Represents exception when no information is provided when deleting (property/client). - */ -public class EmptyCommandDeleteDetailException extends DukeException { -} diff --git a/src/main/java/seedu/duke/exception/EmptyCommandPairUnpairDetailsException.java b/src/main/java/seedu/duke/exception/EmptyCommandPairUnpairDetailsException.java deleted file mode 100644 index 4b23cc0cf..000000000 --- a/src/main/java/seedu/duke/exception/EmptyCommandPairUnpairDetailsException.java +++ /dev/null @@ -1,4 +0,0 @@ -package seedu.duke.exception; - -public class EmptyCommandPairUnpairDetailsException extends DukeException { -} diff --git a/src/main/java/seedu/duke/exception/EmptyDescriptionException.java b/src/main/java/seedu/duke/exception/EmptyDescriptionException.java new file mode 100644 index 000000000..463eadebd --- /dev/null +++ b/src/main/java/seedu/duke/exception/EmptyDescriptionException.java @@ -0,0 +1,18 @@ +package seedu.duke.exception; + +/** + * Represents exception when no client description is given when adding client. + */ +public class EmptyDescriptionException extends DukeParseException { + + private final String message; + + public EmptyDescriptionException(String message) { + this.message = message; + } + + @Override + public String toString() { + return message; + } +} diff --git a/src/main/java/seedu/duke/exception/EmptyDetailException.java b/src/main/java/seedu/duke/exception/EmptyDetailException.java new file mode 100644 index 000000000..2022e0b49 --- /dev/null +++ b/src/main/java/seedu/duke/exception/EmptyDetailException.java @@ -0,0 +1,18 @@ +package seedu.duke.exception; + +/** + * Represents exception when no client description is given when adding client. + */ +public class EmptyDetailException extends DukeParseException { + + private final String message; + + public EmptyDetailException(String message) { + this.message = message; + } + + @Override + public String toString() { + return message; + } +} diff --git a/src/main/java/seedu/duke/exception/EmptyPropertyDetailException.java b/src/main/java/seedu/duke/exception/EmptyPropertyDetailException.java deleted file mode 100644 index 76bcf025a..000000000 --- a/src/main/java/seedu/duke/exception/EmptyPropertyDetailException.java +++ /dev/null @@ -1,7 +0,0 @@ -package seedu.duke.exception; - -/** - * Represents exception when no property description is given when adding property. - */ -public class EmptyPropertyDetailException extends DukeException { -} diff --git a/src/main/java/seedu/duke/exception/EmptyPropertyIndexDeleteException.java b/src/main/java/seedu/duke/exception/EmptyPropertyIndexDeleteException.java deleted file mode 100644 index 8ce95cd7d..000000000 --- a/src/main/java/seedu/duke/exception/EmptyPropertyIndexDeleteException.java +++ /dev/null @@ -1,7 +0,0 @@ -package seedu.duke.exception; - -/** - * Represents exception when property index to delete is empty. - */ -public class EmptyPropertyIndexDeleteException extends DukeException { -} diff --git a/src/main/java/seedu/duke/exception/ExistingPairException.java b/src/main/java/seedu/duke/exception/ExistingPairException.java index a378fc6ff..0c4201968 100644 --- a/src/main/java/seedu/duke/exception/ExistingPairException.java +++ b/src/main/java/seedu/duke/exception/ExistingPairException.java @@ -1,4 +1,15 @@ package seedu.duke.exception; -public class ExistingPairException extends DukeException { +public class ExistingPairException extends DukeCommandException { + + private final String message; + + public ExistingPairException(String message) { + this.message = message; + } + + @Override + public String toString() { + return message; + } } diff --git a/src/main/java/seedu/duke/exception/ExtraParametersException.java b/src/main/java/seedu/duke/exception/ExtraParametersException.java new file mode 100644 index 000000000..c7b0d635d --- /dev/null +++ b/src/main/java/seedu/duke/exception/ExtraParametersException.java @@ -0,0 +1,15 @@ +package seedu.duke.exception; + +public class ExtraParametersException extends DukeParseException { + + private final String message; + + public ExtraParametersException(String message) { + this.message = message; + } + + @Override + public String toString() { + return message; + } +} diff --git a/src/main/java/seedu/duke/exception/IncorrectAddClientFlagOrderException.java b/src/main/java/seedu/duke/exception/IncorrectAddClientFlagOrderException.java deleted file mode 100644 index b9828f701..000000000 --- a/src/main/java/seedu/duke/exception/IncorrectAddClientFlagOrderException.java +++ /dev/null @@ -1,7 +0,0 @@ -package seedu.duke.exception; - -/** - * Represents exception when incorrect flag order is given when adding client. - */ -public class IncorrectAddClientFlagOrderException extends IncorrectFlagOrderException { -} diff --git a/src/main/java/seedu/duke/exception/IncorrectAddPropertyFlagOrderException.java b/src/main/java/seedu/duke/exception/IncorrectAddPropertyFlagOrderException.java deleted file mode 100644 index be0f6a581..000000000 --- a/src/main/java/seedu/duke/exception/IncorrectAddPropertyFlagOrderException.java +++ /dev/null @@ -1,7 +0,0 @@ -package seedu.duke.exception; - -/** - * Represents exception when incorrect flag order is given when adding property. - */ -public class IncorrectAddPropertyFlagOrderException extends IncorrectFlagOrderException { -} diff --git a/src/main/java/seedu/duke/exception/IncorrectFlagOrderException.java b/src/main/java/seedu/duke/exception/IncorrectFlagOrderException.java index 126466270..4ba8fa9e2 100644 --- a/src/main/java/seedu/duke/exception/IncorrectFlagOrderException.java +++ b/src/main/java/seedu/duke/exception/IncorrectFlagOrderException.java @@ -3,5 +3,16 @@ /** * Represents exception when incorrect flag order is given by user. */ -public class IncorrectFlagOrderException extends DukeException { +public class IncorrectFlagOrderException extends DukeParseException { + + private final String message; + + public IncorrectFlagOrderException(String message) { + this.message = message; + } + + @Override + public String toString() { + return message; + } } diff --git a/src/main/java/seedu/duke/exception/IncorrectListDetailsException.java b/src/main/java/seedu/duke/exception/IncorrectListDetailsException.java deleted file mode 100644 index 7289c022b..000000000 --- a/src/main/java/seedu/duke/exception/IncorrectListDetailsException.java +++ /dev/null @@ -1,7 +0,0 @@ -package seedu.duke.exception; - -/** - * Represents exception when List details are incorrectly entered by the user. - */ -public class IncorrectListDetailsException extends DukeException { -} \ No newline at end of file diff --git a/src/main/java/seedu/duke/exception/IncorrectPairUnpairFlagOrderException.java b/src/main/java/seedu/duke/exception/IncorrectPairUnpairFlagOrderException.java deleted file mode 100644 index 73aaa75e2..000000000 --- a/src/main/java/seedu/duke/exception/IncorrectPairUnpairFlagOrderException.java +++ /dev/null @@ -1,4 +0,0 @@ -package seedu.duke.exception; - -public class IncorrectPairUnpairFlagOrderException extends IncorrectFlagOrderException { -} diff --git a/src/main/java/seedu/duke/exception/InvalidBudgetFormatException.java b/src/main/java/seedu/duke/exception/InvalidBudgetFormatException.java index 64700e957..d16011046 100644 --- a/src/main/java/seedu/duke/exception/InvalidBudgetFormatException.java +++ b/src/main/java/seedu/duke/exception/InvalidBudgetFormatException.java @@ -3,5 +3,16 @@ /** * Represents exception when incorrect format for budget is given when adding client. */ -public class InvalidBudgetFormatException extends DukeException { +public class InvalidBudgetFormatException extends DukeParseException { + + private final String message; + + public InvalidBudgetFormatException(String message) { + this.message = message; + } + + @Override + public String toString() { + return message; + } } diff --git a/src/main/java/seedu/duke/exception/InvalidClientIndexDeleteException.java b/src/main/java/seedu/duke/exception/InvalidClientIndexDeleteException.java deleted file mode 100644 index ca7462307..000000000 --- a/src/main/java/seedu/duke/exception/InvalidClientIndexDeleteException.java +++ /dev/null @@ -1,7 +0,0 @@ -package seedu.duke.exception; - -/** - * Represents exception when an invalid client index is provided. - */ -public class InvalidClientIndexDeleteException extends DukeException { -} diff --git a/src/main/java/seedu/duke/exception/InvalidClientIndexFlagFormatException.java b/src/main/java/seedu/duke/exception/InvalidClientIndexFlagFormatException.java deleted file mode 100644 index fcc292092..000000000 --- a/src/main/java/seedu/duke/exception/InvalidClientIndexFlagFormatException.java +++ /dev/null @@ -1,7 +0,0 @@ -package seedu.duke.exception; - -/** - * Represents exception when an invalid client index flag format is provided. - */ -public class InvalidClientIndexFlagFormatException extends DukeException { -} diff --git a/src/main/java/seedu/duke/exception/InvalidContactNumberException.java b/src/main/java/seedu/duke/exception/InvalidContactNumberException.java index 9697a892e..93e6f7dd0 100644 --- a/src/main/java/seedu/duke/exception/InvalidContactNumberException.java +++ b/src/main/java/seedu/duke/exception/InvalidContactNumberException.java @@ -3,5 +3,16 @@ /** * Represents exception when incorrect contact number (Singapore) format is given when adding client. */ -public class InvalidContactNumberException extends DukeException { +public class InvalidContactNumberException extends DukeParseException { + + private final String message; + + public InvalidContactNumberException(String message) { + this.message = message; + } + + @Override + public String toString() { + return message; + } } diff --git a/src/main/java/seedu/duke/exception/InvalidEmailException.java b/src/main/java/seedu/duke/exception/InvalidEmailException.java index b8419b592..65c4b9d46 100644 --- a/src/main/java/seedu/duke/exception/InvalidEmailException.java +++ b/src/main/java/seedu/duke/exception/InvalidEmailException.java @@ -3,5 +3,16 @@ /** * Represents exception when incorrect email format is given when adding client. */ -public class InvalidEmailException extends DukeException { +public class InvalidEmailException extends DukeParseException { + + private final String message; + + public InvalidEmailException(String message) { + this.message = message; + } + + @Override + public String toString() { + return message; + } } diff --git a/src/main/java/seedu/duke/exception/InvalidIndexException.java b/src/main/java/seedu/duke/exception/InvalidIndexException.java index 82d94ec43..10fd8734a 100644 --- a/src/main/java/seedu/duke/exception/InvalidIndexException.java +++ b/src/main/java/seedu/duke/exception/InvalidIndexException.java @@ -1,4 +1,15 @@ package seedu.duke.exception; -public class InvalidIndexException extends DukeException { +public class InvalidIndexException extends DukeParseException { + + private final String message; + + public InvalidIndexException(String message) { + this.message = message; + } + + @Override + public String toString() { + return message; + } } diff --git a/src/main/java/seedu/duke/exception/InvalidPriceFormatException.java b/src/main/java/seedu/duke/exception/InvalidPriceFormatException.java index 54070951a..6905f491b 100644 --- a/src/main/java/seedu/duke/exception/InvalidPriceFormatException.java +++ b/src/main/java/seedu/duke/exception/InvalidPriceFormatException.java @@ -3,5 +3,16 @@ /** * Represents exception when incorrect format for renting_price/month is given when adding property. */ -public class InvalidPriceFormatException extends DukeException { +public class InvalidPriceFormatException extends DukeParseException { + + private final String message; + + public InvalidPriceFormatException(String message) { + this.message = message; + } + + @Override + public String toString() { + return message; + } } diff --git a/src/main/java/seedu/duke/exception/InvalidPropertyIndexDeleteException.java b/src/main/java/seedu/duke/exception/InvalidPropertyIndexDeleteException.java deleted file mode 100644 index 932f9d0f1..000000000 --- a/src/main/java/seedu/duke/exception/InvalidPropertyIndexDeleteException.java +++ /dev/null @@ -1,7 +0,0 @@ -package seedu.duke.exception; - -/** - * Represents exception when an invalid property index is provided. - */ -public class InvalidPropertyIndexDeleteException extends DukeException { -} diff --git a/src/main/java/seedu/duke/exception/InvalidPropertyIndexFlagFormatException.java b/src/main/java/seedu/duke/exception/InvalidPropertyIndexFlagFormatException.java deleted file mode 100644 index 7c381225f..000000000 --- a/src/main/java/seedu/duke/exception/InvalidPropertyIndexFlagFormatException.java +++ /dev/null @@ -1,7 +0,0 @@ -package seedu.duke.exception; - -/** - * Represents exception when an invalid property index flag format is provided. - */ -public class InvalidPropertyIndexFlagFormatException extends DukeException { -} diff --git a/src/main/java/seedu/duke/exception/InvalidSingaporeAddressException.java b/src/main/java/seedu/duke/exception/InvalidSingaporeAddressException.java index a78b6b7d6..7ee46ec67 100644 --- a/src/main/java/seedu/duke/exception/InvalidSingaporeAddressException.java +++ b/src/main/java/seedu/duke/exception/InvalidSingaporeAddressException.java @@ -3,5 +3,16 @@ /** * Represents exception when invalid Singapore Address is provided when adding property. */ -public class InvalidSingaporeAddressException extends DukeException { +public class InvalidSingaporeAddressException extends DukeParseException { + + private final String message; + + public InvalidSingaporeAddressException(String message) { + this.message = message; + } + + @Override + public String toString() { + return message; + } } diff --git a/src/main/java/seedu/duke/exception/MissingCheckPropertyFlagException.java b/src/main/java/seedu/duke/exception/MissingCheckPropertyFlagException.java deleted file mode 100644 index f55c7614b..000000000 --- a/src/main/java/seedu/duke/exception/MissingCheckPropertyFlagException.java +++ /dev/null @@ -1,4 +0,0 @@ -package seedu.duke.exception; - -public class MissingCheckPropertyFlagException extends DukeException { -} diff --git a/src/main/java/seedu/duke/exception/MissingClientDetailException.java b/src/main/java/seedu/duke/exception/MissingClientDetailException.java deleted file mode 100644 index 478f7cacb..000000000 --- a/src/main/java/seedu/duke/exception/MissingClientDetailException.java +++ /dev/null @@ -1,9 +0,0 @@ -package seedu.duke.exception; - -import seedu.duke.exception.DukeException; - -/** - * Represents exception when there is missing client details when adding client. - */ -public class MissingClientDetailException extends DukeException { -} diff --git a/src/main/java/seedu/duke/exception/MissingClientFlagException.java b/src/main/java/seedu/duke/exception/MissingClientFlagException.java deleted file mode 100644 index c823727d4..000000000 --- a/src/main/java/seedu/duke/exception/MissingClientFlagException.java +++ /dev/null @@ -1,7 +0,0 @@ -package seedu.duke.exception; - -/** - * Represents exception when there is missing client flags when adding client. - */ -public class MissingClientFlagException extends MissingFlagException { -} diff --git a/src/main/java/seedu/duke/exception/MissingClientIndexFlagException.java b/src/main/java/seedu/duke/exception/MissingClientIndexFlagException.java deleted file mode 100644 index aedb3cef9..000000000 --- a/src/main/java/seedu/duke/exception/MissingClientIndexFlagException.java +++ /dev/null @@ -1,7 +0,0 @@ -package seedu.duke.exception; - -/** - * Represents exception when client index flag is missing. - */ -public class MissingClientIndexFlagException extends DukeException { -} diff --git a/src/main/java/seedu/duke/exception/MissingFlagException.java b/src/main/java/seedu/duke/exception/MissingFlagException.java index 527c83242..ac8c0b791 100644 --- a/src/main/java/seedu/duke/exception/MissingFlagException.java +++ b/src/main/java/seedu/duke/exception/MissingFlagException.java @@ -1,9 +1,18 @@ package seedu.duke.exception; -import seedu.duke.exception.DukeException; - /** * Represents exception when flags required for command are missing. */ -public class MissingFlagException extends DukeException { +public class MissingFlagException extends DukeParseException { + + private final String message; + + public MissingFlagException(String message) { + this.message = message; + } + + @Override + public String toString() { + return message; + } } diff --git a/src/main/java/seedu/duke/exception/MissingListDetailException.java b/src/main/java/seedu/duke/exception/MissingListDetailException.java deleted file mode 100644 index 771fdd772..000000000 --- a/src/main/java/seedu/duke/exception/MissingListDetailException.java +++ /dev/null @@ -1,7 +0,0 @@ -package seedu.duke.exception; - -/** - * Represents an exception when list details entered by the user are missing. - */ -public class MissingListDetailException extends DukeException { -} diff --git a/src/main/java/seedu/duke/exception/MissingPairUnpairDetailException.java b/src/main/java/seedu/duke/exception/MissingPairUnpairDetailException.java deleted file mode 100644 index 7ac5f38ff..000000000 --- a/src/main/java/seedu/duke/exception/MissingPairUnpairDetailException.java +++ /dev/null @@ -1,4 +0,0 @@ -package seedu.duke.exception; - -public class MissingPairUnpairDetailException extends MissingFlagException { -} diff --git a/src/main/java/seedu/duke/exception/MissingPairUnpairFlagException.java b/src/main/java/seedu/duke/exception/MissingPairUnpairFlagException.java deleted file mode 100644 index 403421e9a..000000000 --- a/src/main/java/seedu/duke/exception/MissingPairUnpairFlagException.java +++ /dev/null @@ -1,4 +0,0 @@ -package seedu.duke.exception; - -public class MissingPairUnpairFlagException extends MissingFlagException{ -} diff --git a/src/main/java/seedu/duke/exception/MissingPropertyDetailException.java b/src/main/java/seedu/duke/exception/MissingPropertyDetailException.java deleted file mode 100644 index f00f2efbc..000000000 --- a/src/main/java/seedu/duke/exception/MissingPropertyDetailException.java +++ /dev/null @@ -1,7 +0,0 @@ -package seedu.duke.exception; - -/** - * Represents exception when there is missing property details when adding property. - */ -public class MissingPropertyDetailException extends DukeException { -} diff --git a/src/main/java/seedu/duke/exception/MissingPropertyFlagException.java b/src/main/java/seedu/duke/exception/MissingPropertyFlagException.java deleted file mode 100644 index 758f2df40..000000000 --- a/src/main/java/seedu/duke/exception/MissingPropertyFlagException.java +++ /dev/null @@ -1,7 +0,0 @@ -package seedu.duke.exception; - -/** - * Represents exception when there is missing property flags when adding property. - */ -public class MissingPropertyFlagException extends MissingFlagException { -} diff --git a/src/main/java/seedu/duke/exception/MissingPropertyIndexFlagException.java b/src/main/java/seedu/duke/exception/MissingPropertyIndexFlagException.java deleted file mode 100644 index b162f9189..000000000 --- a/src/main/java/seedu/duke/exception/MissingPropertyIndexFlagException.java +++ /dev/null @@ -1,7 +0,0 @@ -package seedu.duke.exception; - -/** - * Represents exception when property index flag is missing. - */ -public class MissingPropertyIndexFlagException extends DukeException { -} diff --git a/src/main/java/seedu/duke/exception/NoExistingPairException.java b/src/main/java/seedu/duke/exception/NoExistingPairException.java index 13d470ba5..c44604194 100644 --- a/src/main/java/seedu/duke/exception/NoExistingPairException.java +++ b/src/main/java/seedu/duke/exception/NoExistingPairException.java @@ -1,4 +1,15 @@ package seedu.duke.exception; -public class NoExistingPairException extends DukeException { +public class NoExistingPairException extends DukeCommandException { + + private final String message; + + public NoExistingPairException(String message) { + this.message = message; + } + + @Override + public String toString() { + return message; + } } diff --git a/src/main/java/seedu/duke/exception/NotIntegerException.java b/src/main/java/seedu/duke/exception/NotIntegerException.java index 7ba93e1f5..ef5c4e690 100644 --- a/src/main/java/seedu/duke/exception/NotIntegerException.java +++ b/src/main/java/seedu/duke/exception/NotIntegerException.java @@ -1,4 +1,15 @@ package seedu.duke.exception; -public class NotIntegerException extends DukeException { +public class NotIntegerException extends DukeParseException { + + private final String message; + + public NotIntegerException(String message) { + this.message = message; + } + + @Override + public String toString() { + return message; + } } diff --git a/src/main/java/seedu/duke/exception/UndefinedSubCommandAddTypeException.java b/src/main/java/seedu/duke/exception/UndefinedSubCommandAddTypeException.java deleted file mode 100644 index b2e7b4ba3..000000000 --- a/src/main/java/seedu/duke/exception/UndefinedSubCommandAddTypeException.java +++ /dev/null @@ -1,9 +0,0 @@ -package seedu.duke.exception; - -import seedu.duke.exception.DukeException; - -/** - * Represents exception when sub command type required for command add is missing (-property/-client). - */ -public class UndefinedSubCommandAddTypeException extends DukeException { -} diff --git a/src/main/java/seedu/duke/exception/UndefinedSubCommandCheckTypeException.java b/src/main/java/seedu/duke/exception/UndefinedSubCommandCheckTypeException.java deleted file mode 100644 index 20b13c647..000000000 --- a/src/main/java/seedu/duke/exception/UndefinedSubCommandCheckTypeException.java +++ /dev/null @@ -1,4 +0,0 @@ -package seedu.duke.exception; - -public class UndefinedSubCommandCheckTypeException extends DukeException { -} diff --git a/src/main/java/seedu/duke/exception/UndefinedSubCommandDeleteTypeException.java b/src/main/java/seedu/duke/exception/UndefinedSubCommandDeleteTypeException.java deleted file mode 100644 index ff840d14f..000000000 --- a/src/main/java/seedu/duke/exception/UndefinedSubCommandDeleteTypeException.java +++ /dev/null @@ -1,7 +0,0 @@ -package seedu.duke.exception; - -/** - * Represents exception when sub command type required for command delete is missing (-property/-client). - */ -public class UndefinedSubCommandDeleteTypeException extends DukeException { -} diff --git a/src/main/java/seedu/duke/exception/UndefinedSubCommandTypeException.java b/src/main/java/seedu/duke/exception/UndefinedSubCommandTypeException.java new file mode 100644 index 000000000..6b96e5d5c --- /dev/null +++ b/src/main/java/seedu/duke/exception/UndefinedSubCommandTypeException.java @@ -0,0 +1,18 @@ +package seedu.duke.exception; + +/** + * Represents exception when sub command type required for command add is missing (-property/-client). + */ +public class UndefinedSubCommandTypeException extends DukeParseException { + + private final String message; + + public UndefinedSubCommandTypeException(String message) { + this.message = message; + } + + @Override + public String toString() { + return message; + } +} From deb1f32d731c3012ef78f506b1c3d2c7593de606 Mon Sep 17 00:00:00 2001 From: ngdeqi Date: Sun, 16 Oct 2022 22:27:24 +0800 Subject: [PATCH 080/325] Fix CI errors --- src/main/java/seedu/duke/Parser.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index c3ab10c23..0e693b20c 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -494,8 +494,10 @@ private Command prepareForCommandDeleteClient(String rawCommandDescription) thro try { checkForEmptyDetails(rawCommandDescription); - ArrayList deleteClientDetailsString = processCommandDetails(rawCommandDescription, DELETE_CLIENT_FLAGS); - ArrayList deleteClientDetailsInt = convertProcessedCommandDetailsToInteger(deleteClientDetailsString); + ArrayList deleteClientDetailsString = processCommandDetails(rawCommandDescription, + DELETE_CLIENT_FLAGS); + ArrayList deleteClientDetailsInt = convertProcessedCommandDetailsToInteger( + deleteClientDetailsString); int clientIndex = deleteClientDetailsInt.get(0); checkForInvalidClientIndexDelete(clientIndex); @@ -624,10 +626,10 @@ private void validatePairDetails(ArrayList pairDetails) throws InvalidI } } - private void validateUnpairDetails(ArrayList UnpairDetails) throws InvalidIndexException, + private void validateUnpairDetails(ArrayList unpairDetails) throws InvalidIndexException, NoExistingPairException { - int propertyIndex = UnpairDetails.get(0); - int clientIndex = UnpairDetails.get(1); + int propertyIndex = unpairDetails.get(0); + int clientIndex = unpairDetails.get(1); checkForClientListIndexOutOfBounds(clientIndex); checkForPropertyListIndexOutOfBounds(propertyIndex); From 21f36dc2e17844a6c3b25313b28b18b21ba528dd Mon Sep 17 00:00:00 2001 From: ngdeqi Date: Sun, 16 Oct 2022 22:29:49 +0800 Subject: [PATCH 081/325] Delete extra parser classes --- src/main/java/seedu/duke/ParserCommandAddClient.java | 4 ---- src/main/java/seedu/duke/ParserCommandAddProperty.java | 4 ---- src/main/java/seedu/duke/ParserCommandDelete.java | 4 ---- src/main/java/seedu/duke/ParserCommandExit.java | 4 ---- src/main/java/seedu/duke/ParserCommandList.java | 4 ---- src/main/java/seedu/duke/ParserCommandPair.java | 4 ---- src/main/java/seedu/duke/ParserCommandUnpair.java | 4 ---- 7 files changed, 28 deletions(-) delete mode 100644 src/main/java/seedu/duke/ParserCommandAddClient.java delete mode 100644 src/main/java/seedu/duke/ParserCommandAddProperty.java delete mode 100644 src/main/java/seedu/duke/ParserCommandDelete.java delete mode 100644 src/main/java/seedu/duke/ParserCommandExit.java delete mode 100644 src/main/java/seedu/duke/ParserCommandList.java delete mode 100644 src/main/java/seedu/duke/ParserCommandPair.java delete mode 100644 src/main/java/seedu/duke/ParserCommandUnpair.java diff --git a/src/main/java/seedu/duke/ParserCommandAddClient.java b/src/main/java/seedu/duke/ParserCommandAddClient.java deleted file mode 100644 index 0203226e1..000000000 --- a/src/main/java/seedu/duke/ParserCommandAddClient.java +++ /dev/null @@ -1,4 +0,0 @@ -package seedu.duke; - -public class ParserCommandAddClient { -} diff --git a/src/main/java/seedu/duke/ParserCommandAddProperty.java b/src/main/java/seedu/duke/ParserCommandAddProperty.java deleted file mode 100644 index 7f35aefa1..000000000 --- a/src/main/java/seedu/duke/ParserCommandAddProperty.java +++ /dev/null @@ -1,4 +0,0 @@ -package seedu.duke; - -public class ParserCommandAddProperty { -} diff --git a/src/main/java/seedu/duke/ParserCommandDelete.java b/src/main/java/seedu/duke/ParserCommandDelete.java deleted file mode 100644 index e7c3fe650..000000000 --- a/src/main/java/seedu/duke/ParserCommandDelete.java +++ /dev/null @@ -1,4 +0,0 @@ -package seedu.duke; - -public class ParserCommandDelete { -} diff --git a/src/main/java/seedu/duke/ParserCommandExit.java b/src/main/java/seedu/duke/ParserCommandExit.java deleted file mode 100644 index 1cf774b52..000000000 --- a/src/main/java/seedu/duke/ParserCommandExit.java +++ /dev/null @@ -1,4 +0,0 @@ -package seedu.duke; - -public class ParserCommandExit { -} diff --git a/src/main/java/seedu/duke/ParserCommandList.java b/src/main/java/seedu/duke/ParserCommandList.java deleted file mode 100644 index db4c8876b..000000000 --- a/src/main/java/seedu/duke/ParserCommandList.java +++ /dev/null @@ -1,4 +0,0 @@ -package seedu.duke; - -public class ParserCommandList { -} diff --git a/src/main/java/seedu/duke/ParserCommandPair.java b/src/main/java/seedu/duke/ParserCommandPair.java deleted file mode 100644 index 9b0661d76..000000000 --- a/src/main/java/seedu/duke/ParserCommandPair.java +++ /dev/null @@ -1,4 +0,0 @@ -package seedu.duke; - -public class ParserCommandPair { -} diff --git a/src/main/java/seedu/duke/ParserCommandUnpair.java b/src/main/java/seedu/duke/ParserCommandUnpair.java deleted file mode 100644 index 2d5b3608d..000000000 --- a/src/main/java/seedu/duke/ParserCommandUnpair.java +++ /dev/null @@ -1,4 +0,0 @@ -package seedu.duke; - -public class ParserCommandUnpair { -} From 9342311bfa3703f89afe08b20e83b568f024594e Mon Sep 17 00:00:00 2001 From: "MSI\\User" Date: Mon, 17 Oct 2022 17:32:40 +0800 Subject: [PATCH 082/325] Remove brackets when loading to pairingList --- src/main/java/seedu/duke/Storage.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/seedu/duke/Storage.java b/src/main/java/seedu/duke/Storage.java index 1f1f767b5..2a9f6aac8 100644 --- a/src/main/java/seedu/duke/Storage.java +++ b/src/main/java/seedu/duke/Storage.java @@ -19,6 +19,8 @@ public class Storage { private static final String SEPARATOR = " | "; private static final String COLON = " : "; private static final String EMPTY_STRING = ""; + private static final String OPEN_BRACKET = "["; + private static final String CLOSE_BRACKET = "]"; private static final String LOG_ADD_CLIENT_LABEL = "Client has been added to text file as: "; private static final String LOG_ADD_PROPERTY_LABEL = "Property has been added to text file as: "; private static final String LOG_ADD_PAIRING_LABEL = "Pairings has been added to text file as: "; @@ -209,16 +211,16 @@ public void loadPair(PairingList pairingList, File pairFile) { String[] propertyParameters = pairingParameters[1].split("\\s\\|\\s"); //Client Information - String clientName = clientParamters[0]; + String clientName = clientParamters[0].replace(OPEN_BRACKET, EMPTY_STRING); String clientContactNumber = clientParamters[1]; String clientEmail = clientParamters[2]; - String clientBudget = clientParamters[3]; + String clientBudget = clientParamters[3].replace(CLOSE_BRACKET, EMPTY_STRING); //Property Information - String landLordName = propertyParameters[0]; + String landLordName = propertyParameters[0].replace(OPEN_BRACKET,EMPTY_STRING); String propertyAddress = propertyParameters[1]; String rentalPrice = propertyParameters[2]; - String unitType = propertyParameters[3]; + String unitType = propertyParameters[3].replace(CLOSE_BRACKET,EMPTY_STRING); From 2b1e0d1e841e71b63c3a1118ac06fae1df26a515 Mon Sep 17 00:00:00 2001 From: "MSI\\User" Date: Tue, 18 Oct 2022 07:45:27 +0800 Subject: [PATCH 083/325] Refactor parser class --- src/main/java/seedu/duke/Duke.java | 20 +- src/main/java/seedu/duke/Parser.java | 706 ------------------ .../duke/parsermanager/ParseAddClient.java | 196 +++++ .../duke/parsermanager/ParseAddProperty.java | 238 ++++++ .../parsermanager/ParseCheckProperty.java | 148 ++++ .../duke/parsermanager/ParseDeleteClient.java | 163 ++++ .../parsermanager/ParseDeleteProperty.java | 159 ++++ .../seedu/duke/parsermanager/ParseExit.java | 31 + .../duke/parsermanager/ParseListClient.java | 34 + .../duke/parsermanager/ParseListProperty.java | 33 + .../seedu/duke/parsermanager/ParsePair.java | 204 +++++ .../duke/parsermanager/ParseUndefined.java | 15 + .../seedu/duke/parsermanager/ParseUnpair.java | 192 +++++ .../java/seedu/duke/parsermanager/Parser.java | 26 + .../duke/parsermanager/ParserManager.java | 129 ++++ 15 files changed, 1580 insertions(+), 714 deletions(-) delete mode 100644 src/main/java/seedu/duke/Parser.java create mode 100644 src/main/java/seedu/duke/parsermanager/ParseAddClient.java create mode 100644 src/main/java/seedu/duke/parsermanager/ParseAddProperty.java create mode 100644 src/main/java/seedu/duke/parsermanager/ParseCheckProperty.java create mode 100644 src/main/java/seedu/duke/parsermanager/ParseDeleteClient.java create mode 100644 src/main/java/seedu/duke/parsermanager/ParseDeleteProperty.java create mode 100644 src/main/java/seedu/duke/parsermanager/ParseExit.java create mode 100644 src/main/java/seedu/duke/parsermanager/ParseListClient.java create mode 100644 src/main/java/seedu/duke/parsermanager/ParseListProperty.java create mode 100644 src/main/java/seedu/duke/parsermanager/ParsePair.java create mode 100644 src/main/java/seedu/duke/parsermanager/ParseUndefined.java create mode 100644 src/main/java/seedu/duke/parsermanager/ParseUnpair.java create mode 100644 src/main/java/seedu/duke/parsermanager/Parser.java create mode 100644 src/main/java/seedu/duke/parsermanager/ParserManager.java diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 93bd76104..36c4b4261 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -1,14 +1,13 @@ package seedu.duke; import seedu.duke.command.Command; -import seedu.duke.command.CommandBye; +import seedu.duke.command.CommandBye; import seedu.duke.exception.DukeException; - -import java.io.IOException; +import seedu.duke.parsermanager.Parser; +import seedu.duke.parsermanager.ParserManager; public class Duke { - private Parser parser; private Ui ui; private Storage storage; private PropertyList propertyList; @@ -20,14 +19,15 @@ public Duke() { this.propertyList = new PropertyList(); this.clientList = new ClientList(); this.pairingList = new PairingList(); - this.parser = new Parser(clientList, propertyList, pairingList); this.storage = new Storage(clientList, propertyList, pairingList); } - public void run() throws IOException { + public void run() { Command command; + Parser parser; + ParserManager parserManager = new ParserManager(clientList, propertyList, pairingList); boolean isCommandBye = false; ui.showWelcomeMessage(); @@ -36,9 +36,13 @@ public void run() throws IOException { try { //System.exit(0); //to pass CI String userInputText = ui.readCommand(); - command = parser.parseCommand(userInputText); + + + parser = parserManager.parseCommand(userInputText); + command = parser.parseCommand(); command.execute(ui, storage, propertyList, clientList, pairingList); isCommandBye = (command instanceof CommandBye); + } catch (DukeException e) { ui.showExceptionMessage(e); } @@ -48,7 +52,7 @@ public void run() throws IOException { /** * Main entry-point for the java.duke.Duke application. */ - public static void main(String[] args) throws IOException { + public static void main(String[] args) { new Duke().run(); } } diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java deleted file mode 100644 index 0e693b20c..000000000 --- a/src/main/java/seedu/duke/Parser.java +++ /dev/null @@ -1,706 +0,0 @@ -package seedu.duke; - -import seedu.duke.command.Command; -import seedu.duke.command.CommandAddClient; -import seedu.duke.command.CommandAddProperty; -import seedu.duke.command.CommandBye; -import seedu.duke.command.CommandCheckProperty; -import seedu.duke.command.CommandDeleteClient; -import seedu.duke.command.CommandDeleteProperty; -import seedu.duke.command.CommandListClients; -import seedu.duke.command.CommandListProperties; -import seedu.duke.command.CommandPair; -import seedu.duke.command.CommandUndefined; -import seedu.duke.command.CommandUnpair; -import seedu.duke.exception.ClientAlreadyPairedException; -import seedu.duke.exception.DukeParseException; -import seedu.duke.exception.EmptyDescriptionException; -import seedu.duke.exception.EmptyDetailException; -import seedu.duke.exception.ExistingPairException; -import seedu.duke.exception.ExtraParametersException; -import seedu.duke.exception.IncorrectFlagOrderException; -import seedu.duke.exception.InvalidBudgetFormatException; -import seedu.duke.exception.InvalidContactNumberException; -import seedu.duke.exception.InvalidEmailException; -import seedu.duke.exception.InvalidIndexException; -import seedu.duke.exception.InvalidPriceFormatException; -import seedu.duke.exception.InvalidSingaporeAddressException; -import seedu.duke.exception.MissingFlagException; -import seedu.duke.exception.NoExistingPairException; -import seedu.duke.exception.NotIntegerException; -import seedu.duke.exception.UndefinedSubCommandTypeException; - -import java.util.ArrayList; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import static seedu.duke.CommandStructure.ADD_CLIENT_FLAGS; -import static seedu.duke.CommandStructure.ADD_PROPERTY_FLAGS; -import static seedu.duke.CommandStructure.CHECK_PROPERTY_FLAGS; -import static seedu.duke.CommandStructure.COMMAND_ADD; -import static seedu.duke.CommandStructure.COMMAND_CHECK; -import static seedu.duke.CommandStructure.COMMAND_DELETE; -import static seedu.duke.CommandStructure.COMMAND_EXIT; -import static seedu.duke.CommandStructure.COMMAND_LIST; -import static seedu.duke.CommandStructure.COMMAND_PAIR; -import static seedu.duke.CommandStructure.COMMAND_UNPAIR; -import static seedu.duke.CommandStructure.DELETE_CLIENT_FLAGS; -import static seedu.duke.CommandStructure.DELETE_PROPERTY_FLAGS; -import static seedu.duke.CommandStructure.PAIR_FLAGS; -import static seedu.duke.CommandStructure.UNPAIR_FLAGS; -import static seedu.duke.Messages.EXCEPTION; -import static seedu.duke.Messages.MESSAGE_ADD_CLIENT_WRONG_FORMAT; -import static seedu.duke.Messages.MESSAGE_ADD_PROPERTY_WRONG_FORMAT; -import static seedu.duke.Messages.MESSAGE_BYE_PARAMETERS_PRESENT; -import static seedu.duke.Messages.MESSAGE_CHECK_PROPERTY_WRONG_FORMAT; -import static seedu.duke.Messages.MESSAGE_CLIENT_ALREADY_PAIRED; -import static seedu.duke.Messages.MESSAGE_DELETE_CLIENT_WRONG_FORMAT; -import static seedu.duke.Messages.MESSAGE_DELETE_PROPERTY_WRONG_FORMAT; -import static seedu.duke.Messages.MESSAGE_EMPTY_DESCRIPTION; -import static seedu.duke.Messages.MESSAGE_EXISTING_PAIR; -import static seedu.duke.Messages.MESSAGE_INCORRECT_LIST_DETAILS; -import static seedu.duke.Messages.MESSAGE_INVALID_BUDGET_FORMAT; -import static seedu.duke.Messages.MESSAGE_INVALID_CONTACT_NUMBER; -import static seedu.duke.Messages.MESSAGE_INVALID_EMAIL; -import static seedu.duke.Messages.MESSAGE_INVALID_INDEX; -import static seedu.duke.Messages.MESSAGE_INVALID_PRICE_FORMAT; -import static seedu.duke.Messages.MESSAGE_INVALID_SINGAPORE_ADDRESS; -import static seedu.duke.Messages.MESSAGE_MISSING_SUB_COMMAND_TYPE; -import static seedu.duke.Messages.MESSAGE_NOT_INTEGER; -import static seedu.duke.Messages.MESSAGE_NO_EXISTING_PAIR; -import static seedu.duke.Messages.MESSAGE_PAIR_WRONG_FORMAT; -import static seedu.duke.Messages.MESSAGE_UNPAIR_WRONG_FORMAT; - -public class Parser { - private static ClientList clientList; - private static PropertyList propertyList; - private static PairingList pairingList; - - - public Parser(ClientList clientL, PropertyList propertyL, PairingList pairingL) { - clientList = clientL; - propertyList = propertyL; - pairingList = pairingL; - } - - public Command parseCommand(String input) throws DukeParseException, ExistingPairException, - ClientAlreadyPairedException, NoExistingPairException { - ArrayList processedCommandDetails = partitionCommandTypeAndDetails(input); - String commandType = processedCommandDetails.get(0); - String commandDetails = processedCommandDetails.get(1); - - switch (commandType) { - case COMMAND_ADD: - checkForEmptyDescription(commandDetails); - ArrayList processedAddCommandDetails = partitionCommandTypeAndDetails(commandDetails); - String subAddCommandType = processedAddCommandDetails.get(0); - String clientOrPropertyDescriptions = processedAddCommandDetails.get(1); - if (subAddCommandType.equals("-property")) { - return prepareForCommandAddProperty(clientOrPropertyDescriptions); - } else if (subAddCommandType.equals("-client")) { - return prepareForCommandAddClient(clientOrPropertyDescriptions); - } else { - throw new UndefinedSubCommandTypeException(MESSAGE_MISSING_SUB_COMMAND_TYPE); - } - - case COMMAND_DELETE: - checkForEmptyDescription(commandDetails); - ArrayList processedDeleteCommandDetails = partitionCommandTypeAndDetails(commandDetails); - String subDeleteCommandType = processedDeleteCommandDetails.get(0); - String deleteDescriptions = processedDeleteCommandDetails.get(1).trim(); - if (subDeleteCommandType.equals("-property")) { - return prepareForCommandDeleteProperty(deleteDescriptions); - } else if (subDeleteCommandType.equals("-client")) { - return prepareForCommandDeleteClient(deleteDescriptions); - } else { - throw new UndefinedSubCommandTypeException(MESSAGE_MISSING_SUB_COMMAND_TYPE); - } - - case COMMAND_PAIR: - checkForEmptyDescription(commandDetails); - return prepareForCommandPair(commandDetails); - - case COMMAND_UNPAIR: - checkForEmptyDescription(commandDetails); - return prepareForCommandUnpair(commandDetails); - - case COMMAND_CHECK: - checkForEmptyDescription(commandDetails); - ArrayList processedCheckCommandDetails = partitionCommandTypeAndDetails(commandDetails); - String subCommandCheckType = processedCheckCommandDetails.get(0); - String commandCheckClientOrPropertyDescriptions = processedCheckCommandDetails.get(1); - - if (subCommandCheckType.equals("-property")) { - return prepareForCommandCheckProperty(commandCheckClientOrPropertyDescriptions); - } else { - throw new UndefinedSubCommandTypeException(MESSAGE_MISSING_SUB_COMMAND_TYPE); - } - - case COMMAND_LIST: - checkForEmptyDescription(commandDetails); - return prepareForCommandList(commandDetails); - - case COMMAND_EXIT: - checkForByeParameters(commandDetails); - return new CommandBye(); - default: - return new CommandUndefined(); - } - } - - private ArrayList partitionCommandTypeAndDetails(String fullCommandDetails) { - String[] inputDetails = fullCommandDetails.trim().split(" ", 2); - // This is the type of command/sub-command that will be executed - String commandType = inputDetails[0]; - String commandDetails = fullCommandDetails.replaceFirst(commandType, "").trim(); - ArrayList processedCommandDetails = new ArrayList<>(); - processedCommandDetails.add(commandType); - processedCommandDetails.add(commandDetails); - return processedCommandDetails; - } - - private void checkForEmptyDescription(String commandDetails) throws EmptyDescriptionException { - boolean isEmptyDescription = isEmptyString(commandDetails); - if (isEmptyDescription) { - throw new EmptyDescriptionException(MESSAGE_EMPTY_DESCRIPTION); - } - } - - private void checkForEmptyDetails(String commandDetails) throws EmptyDetailException { - boolean isEmptyDetail = isEmptyString(commandDetails); - if (isEmptyDetail) { - throw new EmptyDetailException(EXCEPTION); - } - } - - private boolean isEmptyString(String commandDetails) { - return commandDetails.trim().isEmpty(); - } - - - private ArrayList processCommandDetails(String rawCommandDetails, String[] flags) - throws MissingFlagException, IncorrectFlagOrderException { - - int[] flagIndexPositions = getFlagIndexPositions(rawCommandDetails, flags); - checkForMissingFlags(flagIndexPositions); - checkFlagsOrder(flagIndexPositions); - return extractCommandDetails(rawCommandDetails, flags, flagIndexPositions); - } - - private ArrayList convertProcessedCommandDetailsToInteger(ArrayList processedCommandDetails) - throws NotIntegerException { - ArrayList integerDetails = new ArrayList<>(); - for (String detail : processedCommandDetails) { - int integer; - try { - integer = Integer.parseInt(detail); - } catch (NumberFormatException e) { - throw new NotIntegerException(EXCEPTION); - } - integerDetails.add(integer - 1); // Convert to 0-index - } - return integerDetails; - } - - // Command Add Client has a special detail processing method because it has an optional email field - private ArrayList processCommandAddClientDetails(String rawCommandDetails, String[] flags) - throws MissingFlagException, IncorrectFlagOrderException { - - int[] flagIndexPositions = getFlagIndexPositions(rawCommandDetails, flags); - checkForMissingFlags(flagIndexPositions); - checkFlagsOrder(flagIndexPositions); - return extractClientDetails(rawCommandDetails, flagIndexPositions); - } - - private int[] getFlagIndexPositions(String commandDetails, String[] flags) { - int[] flagIndexPositions = new int[flags.length]; - - for (int i = 0; i < flags.length; i++) { - flagIndexPositions[i] = commandDetails.indexOf(flags[i]); - } - return flagIndexPositions; - } - - - private void checkForMissingFlags(int[] flagIndexPositions) throws MissingFlagException { - for (int flagIndex : flagIndexPositions) { - if (!isFlagPresent(flagIndex)) { - throw new MissingFlagException(EXCEPTION); - } - } - } - - private boolean isFlagPresent(int flagIndexPosition) { - return (flagIndexPosition != -1); - } - - private void checkFlagsOrder(int[] flagIndexPositions) throws IncorrectFlagOrderException { - for (int i = 0; i < flagIndexPositions.length - 1; i++) { - checkForCorrectFlagOrder(flagIndexPositions[i], flagIndexPositions[i + 1]); - } - } - - private void checkForCorrectFlagOrder(int flagPosition, int nextFlagPosition) throws IncorrectFlagOrderException { - boolean hasCorrectOrder = (flagPosition < nextFlagPosition); - if (!hasCorrectOrder) { - throw new IncorrectFlagOrderException(EXCEPTION); - } - } - - private ArrayList extractCommandDetails(String rawCommandDetails, String[] flags, - int[] flagIndexPositions) { - ArrayList extractedCommandDetails = new ArrayList<>(); - for (int i = 0; i < flags.length; i++) { - String extractedDetail; - if (i == flags.length - 1) { - /* The extracted detail for the last flag starts from the char after the flag, to the end of - rawCommandDetails */ - extractedDetail = extractDetail(rawCommandDetails, flagIndexPositions[i] + flags[i].length()); - } else { - // The extracted detail for non-last starts from the char after the flag, to index before the next flag - extractedDetail = extractDetail( - rawCommandDetails, - flagIndexPositions[i] + flags[i].length(), - flagIndexPositions[i + 1]); - } - extractedCommandDetails.add(extractedDetail.trim()); - } - return extractedCommandDetails; - } - - private ArrayList extractClientDetails(String rawClientDetails, int[] addClientFlagIndexPositions) { - boolean hasEmail = (addClientFlagIndexPositions[2] != -1); - String clientContactNumber; - String clientEmail = ""; - if (hasEmail) { - clientContactNumber = extractDetail(rawClientDetails, addClientFlagIndexPositions[1] + 2, - addClientFlagIndexPositions[2]); - clientEmail = extractDetail(rawClientDetails, addClientFlagIndexPositions[2] + 2, - addClientFlagIndexPositions[3]); - } else { - clientContactNumber = extractDetail(rawClientDetails, addClientFlagIndexPositions[1] + 2, - addClientFlagIndexPositions[3]); - } - String clientName = extractDetail(rawClientDetails, addClientFlagIndexPositions[0] + 2, - addClientFlagIndexPositions[1]); - String clientBudgetPerMonth = extractDetail(rawClientDetails, addClientFlagIndexPositions[3] + 2); - - ArrayList processedClientDetails = new ArrayList<>(); - processedClientDetails.add(clientName.trim()); - processedClientDetails.add(clientContactNumber.trim()); - processedClientDetails.add(clientEmail.trim()); - processedClientDetails.add(clientBudgetPerMonth.trim()); - return processedClientDetails; - } - - private static String extractDetail(String rawDetails, int beginIndex) { - return rawDetails.substring(beginIndex).trim(); - } - - private static String extractDetail(String rawDetails, int beginIndex, int endIndex) { - return rawDetails.substring(beginIndex, endIndex).trim(); - } - - - - /* Add Property/Client Parse Section */ - - private Command prepareForCommandAddProperty(String rawPropertyDescriptions) - throws InvalidSingaporeAddressException, MissingFlagException, InvalidPriceFormatException, - IncorrectFlagOrderException, EmptyDetailException { - - try { - checkForEmptyDetails(rawPropertyDescriptions); - - ArrayList propertyDetails = processCommandDetails(rawPropertyDescriptions, ADD_PROPERTY_FLAGS); - validatePropertyDetails(propertyDetails); - return new CommandAddProperty(propertyDetails); - - } catch (InvalidSingaporeAddressException e) { - throw new InvalidSingaporeAddressException(MESSAGE_INVALID_SINGAPORE_ADDRESS); - } catch (MissingFlagException e) { - throw new MissingFlagException(MESSAGE_ADD_PROPERTY_WRONG_FORMAT); - } catch (IncorrectFlagOrderException e) { - throw new IncorrectFlagOrderException(MESSAGE_ADD_PROPERTY_WRONG_FORMAT); - } catch (InvalidPriceFormatException e) { - throw new InvalidPriceFormatException(MESSAGE_INVALID_PRICE_FORMAT); - } catch (EmptyDetailException e) { - throw new EmptyDetailException(MESSAGE_ADD_PROPERTY_WRONG_FORMAT); - } - } - - private Command prepareForCommandAddClient(String rawClientDescriptions) throws MissingFlagException, - IncorrectFlagOrderException, InvalidContactNumberException, EmptyDetailException, InvalidEmailException, - InvalidBudgetFormatException { - - try { - checkForEmptyDetails(rawClientDescriptions); - - ArrayList clientDetails = processCommandAddClientDetails(rawClientDescriptions, ADD_CLIENT_FLAGS); - validateClientDetails(clientDetails); - return new CommandAddClient(clientDetails); - - } catch (MissingFlagException e) { - throw new MissingFlagException(MESSAGE_ADD_CLIENT_WRONG_FORMAT); - } catch (IncorrectFlagOrderException e) { - throw new IncorrectFlagOrderException(MESSAGE_ADD_CLIENT_WRONG_FORMAT); - } catch (InvalidContactNumberException e) { - throw new InvalidContactNumberException(MESSAGE_INVALID_CONTACT_NUMBER); - } catch (EmptyDetailException e) { - throw new EmptyDetailException(MESSAGE_ADD_CLIENT_WRONG_FORMAT); - } catch (InvalidEmailException e) { - throw new InvalidEmailException(MESSAGE_INVALID_EMAIL); - } catch (InvalidBudgetFormatException e) { - throw new InvalidBudgetFormatException(MESSAGE_INVALID_BUDGET_FORMAT); - } - } - - - private void validatePropertyDetails(ArrayList propertyDetails) throws EmptyDetailException, - InvalidSingaporeAddressException, InvalidPriceFormatException { - //Checks for Missing Landlord Name, Property Address, Renting Price (SGD/month) and Unit-Type - for (String propertyDetail : propertyDetails) { - checkForEmptyDetails(propertyDetail); - } - - //Checks Format for Address (Singapore) and Renting Price - checkForValidSingaporeAddress(propertyDetails.get(1)); - checkForPriceNumberFormat(propertyDetails.get(2)); - } - - private void validateClientDetails(ArrayList clientDetails) throws EmptyDetailException, - InvalidContactNumberException, InvalidEmailException, InvalidBudgetFormatException { - //Checks for Missing Client Name, Contact Number, Budget Per Month (SGD) - checkForEmptyDetails(clientDetails.get(0)); - checkForEmptyDetails(clientDetails.get(1)); - checkForEmptyDetails(clientDetails.get(3)); - - //Checks for Contact Number, Email and Budget Format - checkForValidSingaporeContactNumber(clientDetails.get(1)); - boolean hasEmail = !clientDetails.get(2).isEmpty(); - if (hasEmail) { - checkForValidEmail(clientDetails.get(2)); - } - checkForBudgetNumberFormat(clientDetails.get(3)); - } - - private void checkForValidSingaporeAddress(String address) throws InvalidSingaporeAddressException { - boolean hasValidSingaporeLandedPropertyAddress = checkForValidSingaporeLandedPropertyAddress(address); - boolean hasValidSingaporeBuildingAddress = checkForValidSingaporeBuildingAddress(address); - - boolean hasValidSingaporeAddress = hasValidSingaporeLandedPropertyAddress || hasValidSingaporeBuildingAddress; - if (!hasValidSingaporeAddress) { - throw new InvalidSingaporeAddressException(EXCEPTION); - } - } - - private boolean checkForValidSingaporeLandedPropertyAddress(String address) { - String landedPropertyUnitNumberRegex = "^([0-9]{1,4})([A-Z]?) "; - String streetNameRegex = "[^.!@#$%^&*()_+=<>\\s\\n?`~0-9,{}|-]([a-zA-Z\\s]+)[^.!@#$%^&*()_+=<>\\s\\n?`~0-9," - + "{}|-]"; - String streetNumberRegex = " ([1-9]{1}[0-9]{0,3})"; - String postalCodeRegex = ", (Singapore [0-9]{6})$"; - - String landedPropertyAddressRegex = landedPropertyUnitNumberRegex + streetNameRegex + postalCodeRegex; - String landedPropertyAddressWithStreetNumberRegex = landedPropertyUnitNumberRegex + streetNameRegex - + streetNumberRegex + postalCodeRegex; - - boolean hasValidLandedPropertyAddress = checkForDetailFormat(landedPropertyAddressRegex, address); - boolean hasValidLandedPropertyAddressWithStreetNumber - = checkForDetailFormat(landedPropertyAddressWithStreetNumberRegex, address); - return hasValidLandedPropertyAddress || hasValidLandedPropertyAddressWithStreetNumber; - } - - private boolean checkForValidSingaporeBuildingAddress(String address) { - String buildingBlockNumberRegex = "^([0-9]{1,4})([A-Z]?) "; - String streetNameRegex = "[^.!@#$%^&*()_+=<>\\s\\n?`~0-9,{}|-]([a-zA-Z\\s]+)[^.!@#$%^&*()_+=<>\\s\\n?`~0-9," - + "{}|-]"; - String streetNumberRegex = " ([1-9]{1}[0-9]{0,3})"; - String buildingUnitFloorAndNumberRegex = " #(([0]{1}[1-9]{1})|([1-9]{1}[0-9]{1,2}))-(([0]{1}[1-9]{1})|([1-9]" - + "{1}[0-9]{1,3}))([A-Z]?)"; - String buildingNameRegex = " [^.!@#$%^&*()_+=<>\\s\\n?`~0-9,{}|-]([a-zA-Z\\s]+)[^.!@#$%^&*()_+=<>\\s\\n?`~0-9" - + ",{}|-]"; - String postalCodeRegex = ", (Singapore [0-9]{6})$"; - - String buildingAddressRegex = buildingBlockNumberRegex + streetNameRegex + buildingUnitFloorAndNumberRegex - + postalCodeRegex; - String buildingAddressWithStreetNumberRegex = buildingBlockNumberRegex + streetNameRegex + streetNumberRegex - + buildingUnitFloorAndNumberRegex + postalCodeRegex; - String buildingAddressWithBuildingNameRegex = buildingBlockNumberRegex + streetNameRegex - + buildingUnitFloorAndNumberRegex + buildingNameRegex + postalCodeRegex; - String buildingAddressWithStreetNumberAndBuildingNameRegex = buildingBlockNumberRegex + streetNameRegex - + streetNumberRegex + buildingUnitFloorAndNumberRegex + buildingNameRegex + postalCodeRegex; - - boolean hasValidBuildingAddress = checkForDetailFormat(buildingAddressRegex, address); - boolean hasValidBuildingAddressWithStreetNumber - = checkForDetailFormat(buildingAddressWithStreetNumberRegex, address); - boolean hasValidBuildingAddressWithBuildingName - = checkForDetailFormat(buildingAddressWithBuildingNameRegex, address); - boolean hasValidBuildingAddressWithStreetNumberAndBuildingName - = checkForDetailFormat(buildingAddressWithStreetNumberAndBuildingNameRegex, address); - return hasValidBuildingAddress || hasValidBuildingAddressWithStreetNumber - || hasValidBuildingAddressWithBuildingName || hasValidBuildingAddressWithStreetNumberAndBuildingName; - } - - private void checkForPriceNumberFormat(String budget) throws InvalidPriceFormatException { - //Accepts only positive whole number - String regex = "^[1-9]\\d*$"; - boolean hasValidPriceNumberFormat = checkForDetailFormat(regex, budget); - if (!hasValidPriceNumberFormat) { - throw new InvalidPriceFormatException(EXCEPTION); - } - } - - private void checkForValidSingaporeContactNumber(String clientContactNumber) throws InvalidContactNumberException { - boolean hasValidContactNumber = checkForDetailFormat("^[689]\\d{7}$", clientContactNumber); - if (!hasValidContactNumber) { - throw new InvalidContactNumberException(EXCEPTION); - } - } - - private void checkForValidEmail(String clientEmail) throws InvalidEmailException { - //General Email Regex (RFC 5322 Official Standard) - String regex = "(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\" - + "x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-" - + "9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-" - + "9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0" - + "c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])"; - boolean hasValidContactNumber = checkForDetailFormat(regex, clientEmail); - if (!hasValidContactNumber) { - throw new InvalidEmailException(EXCEPTION); - } - } - - private void checkForBudgetNumberFormat(String budget) throws InvalidBudgetFormatException { - //Accepts only positive whole number - String regex = "^[1-9]\\d*$"; - boolean hasValidBudgetNumberFormat = checkForDetailFormat(regex, budget); - if (!hasValidBudgetNumberFormat) { - throw new InvalidBudgetFormatException(EXCEPTION); - } - } - - private boolean checkForDetailFormat(String regex, String detail) { - Pattern pattern = Pattern.compile(regex); - Matcher matcher = pattern.matcher(detail); - return matcher.matches(); - } - - - /* Delete Property/Client Parse Section */ - - private Command prepareForCommandDeleteClient(String rawCommandDescription) throws InvalidIndexException, - MissingFlagException, IncorrectFlagOrderException, NotIntegerException, EmptyDetailException { - try { - checkForEmptyDetails(rawCommandDescription); - - ArrayList deleteClientDetailsString = processCommandDetails(rawCommandDescription, - DELETE_CLIENT_FLAGS); - ArrayList deleteClientDetailsInt = convertProcessedCommandDetailsToInteger( - deleteClientDetailsString); - - int clientIndex = deleteClientDetailsInt.get(0); - checkForInvalidClientIndexDelete(clientIndex); - return new CommandDeleteClient(clientIndex); - - } catch (InvalidIndexException e) { - throw new InvalidIndexException(MESSAGE_INVALID_INDEX); - } catch (MissingFlagException e) { - throw new MissingFlagException(MESSAGE_DELETE_CLIENT_WRONG_FORMAT); - } catch (IncorrectFlagOrderException e) { - throw new IncorrectFlagOrderException(MESSAGE_DELETE_CLIENT_WRONG_FORMAT); - } catch (NotIntegerException e) { - throw new NotIntegerException(MESSAGE_NOT_INTEGER); - } catch (EmptyDetailException e) { - throw new EmptyDetailException(MESSAGE_DELETE_CLIENT_WRONG_FORMAT); - } - } - - private void checkForInvalidClientIndexDelete(int clientIndex) throws InvalidIndexException { - int currentListSize = clientList.getCurrentListSize(); - if (clientIndex < 0 || clientIndex >= currentListSize) { - throw new InvalidIndexException(EXCEPTION); - } - } - - - private Command prepareForCommandDeleteProperty(String rawCommandDescription) throws MissingFlagException, - InvalidIndexException, IncorrectFlagOrderException, NotIntegerException, EmptyDetailException { - - try { - checkForEmptyDetails(rawCommandDescription); - ArrayList deletePropertyDetailsString = processCommandDetails(rawCommandDescription, - DELETE_PROPERTY_FLAGS); - ArrayList deletePropertyDetailsInt = convertProcessedCommandDetailsToInteger( - deletePropertyDetailsString); - - int propertyIndex = deletePropertyDetailsInt.get(0); - checkForInvalidPropertyIndexDelete(propertyIndex); - return new CommandDeleteProperty(propertyIndex); - } catch (InvalidIndexException e) { - throw new InvalidIndexException(MESSAGE_INVALID_INDEX); - } catch (MissingFlagException e) { - throw new MissingFlagException(MESSAGE_DELETE_PROPERTY_WRONG_FORMAT); - } catch (IncorrectFlagOrderException e) { - throw new IncorrectFlagOrderException(MESSAGE_DELETE_PROPERTY_WRONG_FORMAT); - } catch (NotIntegerException e) { - throw new NotIntegerException(MESSAGE_NOT_INTEGER); - } catch (EmptyDetailException e) { - throw new EmptyDetailException(MESSAGE_DELETE_PROPERTY_WRONG_FORMAT); - } - } - - private void checkForInvalidPropertyIndexDelete(int propertyIndex) throws InvalidIndexException { - int currentListSize = propertyList.getCurrentListSize(); - if (propertyIndex < 0 || propertyIndex >= currentListSize) { - throw new InvalidIndexException(EXCEPTION); - } - } - - /* Pair/Unpair Parse Section */ - - private Command prepareForCommandPair(String rawPairDescriptions) throws MissingFlagException, - InvalidIndexException, ClientAlreadyPairedException, IncorrectFlagOrderException, NotIntegerException, - ExistingPairException { - - try { - ArrayList pairDetailsString = processCommandDetails(rawPairDescriptions, PAIR_FLAGS); - ArrayList pairDetailsInt = convertProcessedCommandDetailsToInteger(pairDetailsString); - - validatePairDetails(pairDetailsInt); - return new CommandPair(pairDetailsInt); - } catch (InvalidIndexException e) { - throw new InvalidIndexException(MESSAGE_INVALID_INDEX); - } catch (ClientAlreadyPairedException e) { - throw new ClientAlreadyPairedException(MESSAGE_CLIENT_ALREADY_PAIRED); - } catch (MissingFlagException e) { - throw new MissingFlagException(MESSAGE_PAIR_WRONG_FORMAT); - } catch (IncorrectFlagOrderException e) { - throw new IncorrectFlagOrderException(MESSAGE_PAIR_WRONG_FORMAT); - } catch (NotIntegerException e) { - throw new NotIntegerException(MESSAGE_NOT_INTEGER); - } catch (ExistingPairException e) { - throw new ExistingPairException(MESSAGE_EXISTING_PAIR); - } - } - - private Command prepareForCommandUnpair(String rawUnpairDescriptions) throws MissingFlagException, - IncorrectFlagOrderException, NotIntegerException, InvalidIndexException, NoExistingPairException { - - try { - ArrayList unpairDetailsString = processCommandDetails(rawUnpairDescriptions, UNPAIR_FLAGS); - ArrayList unpairDetailsInt = convertProcessedCommandDetailsToInteger(unpairDetailsString); - - validateUnpairDetails(unpairDetailsInt); - return new CommandUnpair(unpairDetailsInt); - } catch (InvalidIndexException e) { - throw new InvalidIndexException(MESSAGE_INVALID_INDEX); - } catch (NoExistingPairException e) { - throw new NoExistingPairException(MESSAGE_NO_EXISTING_PAIR); - } catch (MissingFlagException e) { - throw new MissingFlagException(MESSAGE_UNPAIR_WRONG_FORMAT); - } catch (IncorrectFlagOrderException e) { - throw new IncorrectFlagOrderException(MESSAGE_UNPAIR_WRONG_FORMAT); - } catch (NotIntegerException e) { - throw new NotIntegerException(MESSAGE_NOT_INTEGER); - } - } - - - private void validatePairDetails(ArrayList pairDetails) throws InvalidIndexException, - ClientAlreadyPairedException, ExistingPairException { - int propertyIndex = pairDetails.get(0); - int clientIndex = pairDetails.get(1); - checkForClientListIndexOutOfBounds(clientIndex); - checkForPropertyListIndexOutOfBounds(propertyIndex); - - Client client = clientList.getClientList().get(clientIndex); - Property property = propertyList.getPropertyList().get(propertyIndex); - - if (pairingList.isAlreadyPaired(client, property)) { - throw new ExistingPairException(EXCEPTION); - } - - if (pairingList.isClientPairedWithProperty(client)) { - throw new ClientAlreadyPairedException(EXCEPTION); - } - } - - private void validateUnpairDetails(ArrayList unpairDetails) throws InvalidIndexException, - NoExistingPairException { - int propertyIndex = unpairDetails.get(0); - int clientIndex = unpairDetails.get(1); - - checkForClientListIndexOutOfBounds(clientIndex); - checkForPropertyListIndexOutOfBounds(propertyIndex); - - Client client = clientList.getClientList().get(clientIndex); - Property property = propertyList.getPropertyList().get(propertyIndex); - - if (!pairingList.isAlreadyPaired(client, property)) { - throw new NoExistingPairException(EXCEPTION); - } - } - - - /* Check client/property parse Section */ - - private void checkForPropertyListIndexOutOfBounds(int propertyIndex) throws InvalidIndexException { - if (propertyIndex < 0 || propertyIndex > propertyList.getCurrentListSize() - 1) { - throw new InvalidIndexException(EXCEPTION); - } - } - - private void checkForClientListIndexOutOfBounds(int clientIndex) throws InvalidIndexException { - if (clientIndex < 0 || clientIndex > clientList.getCurrentListSize() - 1) { - throw new InvalidIndexException(EXCEPTION); - } - } - - private Command prepareForCommandCheckProperty(String rawCheckDescriptions) throws InvalidIndexException, - MissingFlagException, IncorrectFlagOrderException, NotIntegerException { - - try { - ArrayList checkDetailsString = processCommandDetails(rawCheckDescriptions, CHECK_PROPERTY_FLAGS); - ArrayList checkDetailsInt = convertProcessedCommandDetailsToInteger(checkDetailsString); - - validateCheckPropertyDetails(checkDetailsInt); - return new CommandCheckProperty(checkDetailsInt); - } catch (InvalidIndexException e) { - throw new InvalidIndexException(MESSAGE_INVALID_INDEX); - } catch (MissingFlagException e) { - throw new MissingFlagException(MESSAGE_CHECK_PROPERTY_WRONG_FORMAT); - } catch (IncorrectFlagOrderException e) { - throw new IncorrectFlagOrderException(MESSAGE_CHECK_PROPERTY_WRONG_FORMAT); - } catch (NotIntegerException e) { - throw new NotIntegerException(MESSAGE_NOT_INTEGER); - } - } - - - private void validateCheckPropertyDetails(ArrayList checkPropertyDetails) throws InvalidIndexException { - int propertyIndex = checkPropertyDetails.get(0); - checkForPropertyListIndexOutOfBounds(propertyIndex); - } - - - /* List Property/Client Parse Section */ - - - private Command prepareForCommandList(String commandDetails) throws UndefinedSubCommandTypeException { - if (commandDetails.trim().equals("-client")) { - return new CommandListClients(); - } else if (commandDetails.trim().equals("-property")) { - return new CommandListProperties(); - } else { - throw new UndefinedSubCommandTypeException(MESSAGE_INCORRECT_LIST_DETAILS); - } - } - - private void checkForByeParameters(String commandDetails) throws ExtraParametersException { - if (!commandDetails.trim().isEmpty()) { - throw new ExtraParametersException(MESSAGE_BYE_PARAMETERS_PRESENT); - } - } - -} diff --git a/src/main/java/seedu/duke/parsermanager/ParseAddClient.java b/src/main/java/seedu/duke/parsermanager/ParseAddClient.java new file mode 100644 index 000000000..248ffa28d --- /dev/null +++ b/src/main/java/seedu/duke/parsermanager/ParseAddClient.java @@ -0,0 +1,196 @@ +package seedu.duke.parsermanager; + +import seedu.duke.command.Command; +import seedu.duke.command.CommandAddClient; +import seedu.duke.exception.EmptyDetailException; +import seedu.duke.exception.IncorrectFlagOrderException; +import seedu.duke.exception.InvalidBudgetFormatException; +import seedu.duke.exception.InvalidContactNumberException; +import seedu.duke.exception.InvalidEmailException; +import seedu.duke.exception.MissingFlagException; + +import java.util.ArrayList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static seedu.duke.CommandStructure.ADD_CLIENT_FLAGS; +import static seedu.duke.Messages.EXCEPTION; +import static seedu.duke.Messages.MESSAGE_ADD_CLIENT_WRONG_FORMAT; +import static seedu.duke.Messages.MESSAGE_INVALID_BUDGET_FORMAT; +import static seedu.duke.Messages.MESSAGE_INVALID_CONTACT_NUMBER; +import static seedu.duke.Messages.MESSAGE_INVALID_EMAIL; + +public class ParseAddClient extends Parser { + private final String commandDescription; + + public ParseAddClient(String addCommandDescription) { + this.commandDescription = addCommandDescription; + } + + + public Command parseCommand() throws MissingFlagException, IncorrectFlagOrderException, EmptyDetailException, + InvalidContactNumberException, InvalidEmailException, InvalidBudgetFormatException { + try { + checkForEmptyDetails(commandDescription); + + ArrayList clientDetails = processCommandAddClientDetails(commandDescription); + validateClientDetails(clientDetails); + return new CommandAddClient(clientDetails); + + } catch (MissingFlagException e) { + throw new MissingFlagException(MESSAGE_ADD_CLIENT_WRONG_FORMAT); + } catch (IncorrectFlagOrderException e) { + throw new IncorrectFlagOrderException(MESSAGE_ADD_CLIENT_WRONG_FORMAT); + } catch (InvalidContactNumberException e) { + throw new InvalidContactNumberException(MESSAGE_INVALID_CONTACT_NUMBER); + } catch (EmptyDetailException e) { + throw new EmptyDetailException(MESSAGE_ADD_CLIENT_WRONG_FORMAT); + } catch (InvalidEmailException e) { + throw new InvalidEmailException(MESSAGE_INVALID_EMAIL); + } catch (InvalidBudgetFormatException e) { + throw new InvalidBudgetFormatException(MESSAGE_INVALID_BUDGET_FORMAT); + } + } + + private void checkForEmptyDetails(String commandDetail) throws EmptyDetailException { + boolean isEmptyDetail = isEmptyString(commandDetail); + if (isEmptyDetail) { + throw new EmptyDetailException(EXCEPTION); + } + } + + private boolean isEmptyString(String commandDetail) { + return commandDetail.trim().isEmpty(); + } + + private ArrayList processCommandAddClientDetails(String rawCommandDetail) + throws MissingFlagException, IncorrectFlagOrderException { + + int[] flagIndexPositions = getFlagIndexPositions(rawCommandDetail); + checkForMissingFlags(flagIndexPositions); + checkFlagsOrder(flagIndexPositions); + return extractClientDetails(rawCommandDetail, flagIndexPositions); + } + + private void validateClientDetails(ArrayList clientDetails) throws EmptyDetailException, + InvalidContactNumberException, InvalidEmailException, InvalidBudgetFormatException { + //Checks for Missing Client Name, Contact Number, Budget Per Month (SGD) + checkForEmptyDetails(clientDetails.get(0)); + checkForEmptyDetails(clientDetails.get(1)); + checkForEmptyDetails(clientDetails.get(3)); + + //Checks for Contact Number, Email and Budget Format + checkForValidSingaporeContactNumber(clientDetails.get(1)); + boolean hasEmail = !clientDetails.get(2).isEmpty(); + if (hasEmail) { + checkForValidEmail(clientDetails.get(2)); + } + checkForBudgetNumberFormat(clientDetails.get(3)); + } + + private int[] getFlagIndexPositions(String commandDetail) { + String[] flags = ADD_CLIENT_FLAGS; + int[] flagIndexPositions = new int[flags.length]; + + for (int i = 0; i < flags.length; i++) { + flagIndexPositions[i] = commandDetail.indexOf(flags[i]); + } + return flagIndexPositions; + } + + private void checkForMissingFlags(int[] flagIndexPositions) throws MissingFlagException { + for (int flagIndex : flagIndexPositions) { + if (!isFlagPresent(flagIndex)) { + throw new MissingFlagException(EXCEPTION); + } + } + } + + private void checkFlagsOrder(int[] flagIndexPositions) throws IncorrectFlagOrderException { + for (int i = 0; i < flagIndexPositions.length - 1; i++) { + checkForCorrectFlagOrder(flagIndexPositions[i], flagIndexPositions[i + 1]); + } + } + + private ArrayList extractClientDetails(String rawClientDetail, int[] addClientFlagIndexPositions) { + boolean hasEmail = (addClientFlagIndexPositions[2] != -1); + String clientContactNumber; + String clientEmail = ""; + if (hasEmail) { + clientContactNumber = extractDetail(rawClientDetail, addClientFlagIndexPositions[1] + 2, + addClientFlagIndexPositions[2]); + clientEmail = extractDetail(rawClientDetail, addClientFlagIndexPositions[2] + 2, + addClientFlagIndexPositions[3]); + } else { + clientContactNumber = extractDetail(rawClientDetail, addClientFlagIndexPositions[1] + 2, + addClientFlagIndexPositions[3]); + } + String clientName = extractDetail(rawClientDetail, addClientFlagIndexPositions[0] + 2, + addClientFlagIndexPositions[1]); + String clientBudgetPerMonth = extractDetail(rawClientDetail, addClientFlagIndexPositions[3] + 2); + + ArrayList processedClientDetails = new ArrayList<>(); + processedClientDetails.add(clientName.trim()); + processedClientDetails.add(clientContactNumber.trim()); + processedClientDetails.add(clientEmail.trim()); + processedClientDetails.add(clientBudgetPerMonth.trim()); + return processedClientDetails; + } + + private void checkForValidSingaporeContactNumber(String clientContactNumber) throws InvalidContactNumberException { + boolean hasValidContactNumber = checkForDetailFormat("^[689]\\d{7}$", clientContactNumber); + if (!hasValidContactNumber) { + throw new InvalidContactNumberException(EXCEPTION); + } + } + + private void checkForValidEmail(String clientEmail) throws InvalidEmailException { + //General Email Regex (RFC 5322 Official Standard) + String regex = "(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\" + + "x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-" + + "9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-" + + "9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0" + + "c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])"; + boolean hasValidContactNumber = checkForDetailFormat(regex, clientEmail); + if (!hasValidContactNumber) { + throw new InvalidEmailException(EXCEPTION); + } + } + + private void checkForBudgetNumberFormat(String budget) throws InvalidBudgetFormatException { + //Accepts only positive whole number + String regex = "^[1-9]\\d*$"; + boolean hasValidBudgetNumberFormat = checkForDetailFormat(regex, budget); + if (!hasValidBudgetNumberFormat) { + throw new InvalidBudgetFormatException(EXCEPTION); + } + } + + private boolean isFlagPresent(int flagIndexPosition) { + return (flagIndexPosition != -1); + } + + private void checkForCorrectFlagOrder(int flagPosition, int nextFlagPosition) throws IncorrectFlagOrderException { + boolean hasCorrectOrder = (flagPosition < nextFlagPosition); + if (!hasCorrectOrder) { + throw new IncorrectFlagOrderException(EXCEPTION); + } + } + + private static String extractDetail(String rawDetail, int beginIndex) { + return rawDetail.substring(beginIndex).trim(); + } + + private static String extractDetail(String rawDetail, int beginIndex, int endIndex) { + return rawDetail.substring(beginIndex, endIndex).trim(); + } + + private boolean checkForDetailFormat(String regex, String detail) { + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(detail); + return matcher.matches(); + } + + + +} diff --git a/src/main/java/seedu/duke/parsermanager/ParseAddProperty.java b/src/main/java/seedu/duke/parsermanager/ParseAddProperty.java new file mode 100644 index 000000000..47f841866 --- /dev/null +++ b/src/main/java/seedu/duke/parsermanager/ParseAddProperty.java @@ -0,0 +1,238 @@ +package seedu.duke.parsermanager; + +import seedu.duke.command.Command; +import seedu.duke.command.CommandAddProperty; +import seedu.duke.exception.EmptyDescriptionException; +import seedu.duke.exception.EmptyDetailException; +import seedu.duke.exception.IncorrectFlagOrderException; +import seedu.duke.exception.InvalidPriceFormatException; +import seedu.duke.exception.InvalidSingaporeAddressException; +import seedu.duke.exception.MissingFlagException; + +import java.util.ArrayList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static seedu.duke.CommandStructure.ADD_PROPERTY_FLAGS; +import static seedu.duke.Messages.EXCEPTION; +import static seedu.duke.Messages.MESSAGE_ADD_PROPERTY_WRONG_FORMAT; +import static seedu.duke.Messages.MESSAGE_EMPTY_DESCRIPTION; +import static seedu.duke.Messages.MESSAGE_INVALID_PRICE_FORMAT; +import static seedu.duke.Messages.MESSAGE_INVALID_SINGAPORE_ADDRESS; + +public class ParseAddProperty extends Parser { + private final String commandDescription; + + public ParseAddProperty(String addCommandDescription) { + this.commandDescription = addCommandDescription; + } + + public Command parseCommand() throws EmptyDescriptionException, InvalidSingaporeAddressException, + MissingFlagException, IncorrectFlagOrderException, InvalidPriceFormatException, EmptyDetailException { + + checkForEmptyDescription(commandDescription); + ArrayList propertyDetails; + try { + + checkForEmptyDetails(commandDescription); + + propertyDetails = processCommandDetails(commandDescription); + validatePropertyDetails(propertyDetails); + + return new CommandAddProperty(propertyDetails); + + } catch (InvalidSingaporeAddressException e) { + throw new InvalidSingaporeAddressException(MESSAGE_INVALID_SINGAPORE_ADDRESS); + } catch (MissingFlagException e) { + throw new MissingFlagException(MESSAGE_ADD_PROPERTY_WRONG_FORMAT); + } catch (IncorrectFlagOrderException e) { + throw new IncorrectFlagOrderException(MESSAGE_ADD_PROPERTY_WRONG_FORMAT); + } catch (InvalidPriceFormatException e) { + throw new InvalidPriceFormatException(MESSAGE_INVALID_PRICE_FORMAT); + } catch (EmptyDetailException e) { + throw new EmptyDetailException(MESSAGE_ADD_PROPERTY_WRONG_FORMAT); + } + + + } + + private void checkForEmptyDescription(String commandDetail) throws EmptyDescriptionException { + boolean isEmptyDescription = isEmptyString(commandDetail); + if (isEmptyDescription) { + throw new EmptyDescriptionException(MESSAGE_EMPTY_DESCRIPTION); + } + } + + private boolean isEmptyString(String commandDetail) { + String trimmedString = commandDetail.trim(); + + return trimmedString.isEmpty(); + } + + private void checkForEmptyDetails(String commandDetail) throws EmptyDetailException { + boolean isEmptyDetail = isEmptyString(commandDetail); + if (isEmptyDetail) { + throw new EmptyDetailException(EXCEPTION); + } + } + + private ArrayList processCommandDetails(String rawCommandDetail) + throws MissingFlagException, IncorrectFlagOrderException { + + String[] flags = ADD_PROPERTY_FLAGS; + int[] flagIndexPositions = getFlagIndexPositions(rawCommandDetail, flags); + checkForMissingFlags(flagIndexPositions); + checkFlagsOrder(flagIndexPositions); + return extractCommandDetails(rawCommandDetail, flags, flagIndexPositions); + } + + private void validatePropertyDetails(ArrayList propertyDetails) throws EmptyDetailException, + InvalidSingaporeAddressException, InvalidPriceFormatException { + //Checks for Missing Landlord Name, Property Address, Renting Price (SGD/month) and Unit-Type + for (String propertyDetail : propertyDetails) { + checkForEmptyDetails(propertyDetail); + } + + //Checks Format for Address (Singapore) and Renting Price + checkForValidSingaporeAddress(propertyDetails.get(1)); + checkForPriceNumberFormat(propertyDetails.get(2)); + } + + private int[] getFlagIndexPositions(String commandDetail, String[] flags) { + int[] flagIndexPositions = new int[flags.length]; + + for (int i = 0; i < flags.length; i++) { + flagIndexPositions[i] = commandDetail.indexOf(flags[i]); + } + return flagIndexPositions; + } + + private void checkForMissingFlags(int[] flagIndexPositions) throws MissingFlagException { + for (int flagIndex : flagIndexPositions) { + if (!isFlagPresent(flagIndex)) { + throw new MissingFlagException(EXCEPTION); + } + } + } + + private void checkFlagsOrder(int[] flagIndexPositions) throws IncorrectFlagOrderException { + for (int i = 0; i < flagIndexPositions.length - 1; i++) { + checkForCorrectFlagOrder(flagIndexPositions[i], flagIndexPositions[i + 1]); + } + } + + private ArrayList extractCommandDetails(String rawCommandDetail, String[] flags, + int[] flagIndexPositions) { + ArrayList extractedCommandDetails = new ArrayList<>(); + for (int i = 0; i < flags.length; i++) { + String extractedDetail; + if (i == flags.length - 1) { + /* The extracted detail for the last flag starts from the char after the flag, to the end of + rawCommandDetails */ + extractedDetail = extractDetail(rawCommandDetail, flagIndexPositions[i] + flags[i].length()); + } else { + // The extracted detail for non-last starts from the char after the flag, to index before the next flag + extractedDetail = extractDetail( + rawCommandDetail, + flagIndexPositions[i] + flags[i].length(), + flagIndexPositions[i + 1]); + } + extractedCommandDetails.add(extractedDetail.trim()); + } + return extractedCommandDetails; + } + + private void checkForValidSingaporeAddress(String address) throws InvalidSingaporeAddressException { + boolean hasValidSingaporeLandedPropertyAddress = checkForValidSingaporeLandedPropertyAddress(address); + boolean hasValidSingaporeBuildingAddress = checkForValidSingaporeBuildingAddress(address); + + boolean hasValidSingaporeAddress = hasValidSingaporeLandedPropertyAddress || hasValidSingaporeBuildingAddress; + if (!hasValidSingaporeAddress) { + throw new InvalidSingaporeAddressException(EXCEPTION); + } + } + + private void checkForPriceNumberFormat(String budget) throws InvalidPriceFormatException { + //Accepts only positive whole number + String regex = "^[1-9]\\d*$"; + boolean hasValidPriceNumberFormat = checkForDetailFormat(regex, budget); + if (!hasValidPriceNumberFormat) { + throw new InvalidPriceFormatException(EXCEPTION); + } + } + + private boolean isFlagPresent(int flagIndexPosition) { + return (flagIndexPosition != -1); + } + + private void checkForCorrectFlagOrder(int flagPosition, int nextFlagPosition) throws IncorrectFlagOrderException { + boolean hasCorrectOrder = (flagPosition < nextFlagPosition); + if (!hasCorrectOrder) { + throw new IncorrectFlagOrderException(EXCEPTION); + } + } + + private static String extractDetail(String rawDetail, int beginIndex) { + return rawDetail.substring(beginIndex).trim(); + } + + private static String extractDetail(String rawDetail, int beginIndex, int endIndex) { + return rawDetail.substring(beginIndex, endIndex).trim(); + } + + private boolean checkForValidSingaporeLandedPropertyAddress(String address) { + String landedPropertyUnitNumberRegex = "^([0-9]{1,4})([A-Z]?) "; + String streetNameRegex = "[^.!@#$%^&*()_+=<>\\s\\n?`~0-9,{}|-]([a-zA-Z\\s]+)[^.!@#$%^&*()_+=<>\\s\\n?`~0-9," + + "{}|-]"; + String streetNumberRegex = " ([1-9]{1}[0-9]{0,3})"; + String postalCodeRegex = ", (Singapore [0-9]{6})$"; + + String landedPropertyAddressRegex = landedPropertyUnitNumberRegex + streetNameRegex + postalCodeRegex; + String landedPropertyAddressWithStreetNumberRegex = landedPropertyUnitNumberRegex + streetNameRegex + + streetNumberRegex + postalCodeRegex; + + boolean hasValidLandedPropertyAddress = checkForDetailFormat(landedPropertyAddressRegex, address); + boolean hasValidLandedPropertyAddressWithStreetNumber + = checkForDetailFormat(landedPropertyAddressWithStreetNumberRegex, address); + return hasValidLandedPropertyAddress || hasValidLandedPropertyAddressWithStreetNumber; + } + + private boolean checkForValidSingaporeBuildingAddress(String address) { + String buildingBlockNumberRegex = "^([0-9]{1,4})([A-Z]?) "; + String streetNameRegex = "[^.!@#$%^&*()_+=<>\\s\\n?`~0-9,{}|-]([a-zA-Z\\s]+)[^.!@#$%^&*()_+=<>\\s\\n?`~0-9," + + "{}|-]"; + String streetNumberRegex = " ([1-9]{1}[0-9]{0,3})"; + String buildingUnitFloorAndNumberRegex = " #(([0]{1}[1-9]{1})|([1-9]{1}[0-9]{1,2}))-(([0]{1}[1-9]{1})|([1-9]" + + "{1}[0-9]{1,3}))([A-Z]?)"; + String buildingNameRegex = " [^.!@#$%^&*()_+=<>\\s\\n?`~0-9,{}|-]([a-zA-Z\\s]+)[^.!@#$%^&*()_+=<>\\s\\n?`~0-9" + + ",{}|-]"; + String postalCodeRegex = ", (Singapore [0-9]{6})$"; + + String buildingAddressRegex = buildingBlockNumberRegex + streetNameRegex + buildingUnitFloorAndNumberRegex + + postalCodeRegex; + String buildingAddressWithStreetNumberRegex = buildingBlockNumberRegex + streetNameRegex + streetNumberRegex + + buildingUnitFloorAndNumberRegex + postalCodeRegex; + String buildingAddressWithBuildingNameRegex = buildingBlockNumberRegex + streetNameRegex + + buildingUnitFloorAndNumberRegex + buildingNameRegex + postalCodeRegex; + String buildingAddressWithStreetNumberAndBuildingNameRegex = buildingBlockNumberRegex + streetNameRegex + + streetNumberRegex + buildingUnitFloorAndNumberRegex + buildingNameRegex + postalCodeRegex; + + boolean hasValidBuildingAddress = checkForDetailFormat(buildingAddressRegex, address); + boolean hasValidBuildingAddressWithStreetNumber + = checkForDetailFormat(buildingAddressWithStreetNumberRegex, address); + boolean hasValidBuildingAddressWithBuildingName + = checkForDetailFormat(buildingAddressWithBuildingNameRegex, address); + boolean hasValidBuildingAddressWithStreetNumberAndBuildingName + = checkForDetailFormat(buildingAddressWithStreetNumberAndBuildingNameRegex, address); + return hasValidBuildingAddress || hasValidBuildingAddressWithStreetNumber + || hasValidBuildingAddressWithBuildingName || hasValidBuildingAddressWithStreetNumberAndBuildingName; + } + + private boolean checkForDetailFormat(String regex, String detail) { + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(detail); + return matcher.matches(); + } + + +} diff --git a/src/main/java/seedu/duke/parsermanager/ParseCheckProperty.java b/src/main/java/seedu/duke/parsermanager/ParseCheckProperty.java new file mode 100644 index 000000000..81ae512f0 --- /dev/null +++ b/src/main/java/seedu/duke/parsermanager/ParseCheckProperty.java @@ -0,0 +1,148 @@ +package seedu.duke.parsermanager; + +import seedu.duke.PropertyList; +import seedu.duke.command.Command; +import seedu.duke.command.CommandCheckProperty; +import seedu.duke.exception.IncorrectFlagOrderException; +import seedu.duke.exception.InvalidIndexException; +import seedu.duke.exception.MissingFlagException; +import seedu.duke.exception.NotIntegerException; + +import java.util.ArrayList; + +import static seedu.duke.CommandStructure.CHECK_PROPERTY_FLAGS; +import static seedu.duke.Messages.EXCEPTION; +import static seedu.duke.Messages.MESSAGE_CHECK_PROPERTY_WRONG_FORMAT; +import static seedu.duke.Messages.MESSAGE_INVALID_INDEX; +import static seedu.duke.Messages.MESSAGE_NOT_INTEGER; + +public class ParseCheckProperty extends Parser { + private final String commandDescription; + private final PropertyList propertyList; + + public ParseCheckProperty(String checkCommandDescription, PropertyList propertyList) { + this.commandDescription = checkCommandDescription; + this.propertyList = propertyList; + } + + @Override + public Command parseCommand() throws InvalidIndexException, MissingFlagException, + IncorrectFlagOrderException, NotIntegerException { + try { + ArrayList checkDetailsString = processCommandDetails(commandDescription); + ArrayList checkDetailsInt = convertProcessedCommandDetailsToInteger(checkDetailsString); + + validateCheckPropertyDetails(checkDetailsInt); + return new CommandCheckProperty(checkDetailsInt); + } catch (InvalidIndexException e) { + throw new InvalidIndexException(MESSAGE_INVALID_INDEX); + } catch (MissingFlagException e) { + throw new MissingFlagException(MESSAGE_CHECK_PROPERTY_WRONG_FORMAT); + } catch (IncorrectFlagOrderException e) { + throw new IncorrectFlagOrderException(MESSAGE_CHECK_PROPERTY_WRONG_FORMAT); + } catch (NotIntegerException e) { + throw new NotIntegerException(MESSAGE_NOT_INTEGER); + } + } + + private ArrayList processCommandDetails(String rawCommandDetail) + throws MissingFlagException, IncorrectFlagOrderException { + + String[] flags = CHECK_PROPERTY_FLAGS; + int[] flagIndexPositions = getFlagIndexPositions(rawCommandDetail, flags); + checkForMissingFlags(flagIndexPositions); + checkFlagsOrder(flagIndexPositions); + return extractCommandDetails(rawCommandDetail, flags, flagIndexPositions); + } + + private ArrayList convertProcessedCommandDetailsToInteger(ArrayList processedCommandDetails) + throws NotIntegerException { + ArrayList integerDetails = new ArrayList<>(); + for (String detail : processedCommandDetails) { + int integer; + try { + integer = Integer.parseInt(detail); + } catch (NumberFormatException e) { + throw new NotIntegerException(EXCEPTION); + } + integerDetails.add(integer - 1); // Convert to 0-index + } + return integerDetails; + } + + private void validateCheckPropertyDetails(ArrayList checkPropertyDetails) throws InvalidIndexException { + int propertyIndex = checkPropertyDetails.get(0); + checkForPropertyListIndexOutOfBounds(propertyIndex); + } + + private int[] getFlagIndexPositions(String commandDetail, String[] flags) { + int[] flagIndexPositions = new int[flags.length]; + + for (int i = 0; i < flags.length; i++) { + flagIndexPositions[i] = commandDetail.indexOf(flags[i]); + } + return flagIndexPositions; + } + + private void checkForMissingFlags(int[] flagIndexPositions) throws MissingFlagException { + for (int flagIndex : flagIndexPositions) { + if (!isFlagPresent(flagIndex)) { + throw new MissingFlagException(EXCEPTION); + } + } + } + + private void checkFlagsOrder(int[] flagIndexPositions) throws IncorrectFlagOrderException { + for (int i = 0; i < flagIndexPositions.length - 1; i++) { + checkForCorrectFlagOrder(flagIndexPositions[i], flagIndexPositions[i + 1]); + } + } + + private ArrayList extractCommandDetails(String rawCommandDetail, String[] flags, + int[] flagIndexPositions) { + ArrayList extractedCommandDetails = new ArrayList<>(); + for (int i = 0; i < flags.length; i++) { + String extractedDetail; + if (i == flags.length - 1) { + /* The extracted detail for the last flag starts from the char after the flag, to the end of + rawCommandDetails */ + extractedDetail = extractDetail(rawCommandDetail, flagIndexPositions[i] + flags[i].length()); + } else { + // The extracted detail for non-last starts from the char after the flag, to index before the next flag + extractedDetail = extractDetail( + rawCommandDetail, + flagIndexPositions[i] + flags[i].length(), + flagIndexPositions[i + 1]); + } + extractedCommandDetails.add(extractedDetail.trim()); + } + return extractedCommandDetails; + } + + private void checkForPropertyListIndexOutOfBounds(int propertyIndex) throws InvalidIndexException { + if (propertyIndex < 0 || propertyIndex > propertyList.getCurrentListSize() - 1) { + throw new InvalidIndexException(EXCEPTION); + } + } + + private boolean isFlagPresent(int flagIndexPosition) { + return (flagIndexPosition != -1); + } + + private void checkForCorrectFlagOrder(int flagPosition, int nextFlagPosition) throws IncorrectFlagOrderException { + boolean hasCorrectOrder = (flagPosition < nextFlagPosition); + if (!hasCorrectOrder) { + throw new IncorrectFlagOrderException(EXCEPTION); + } + } + + private static String extractDetail(String rawDetail, int beginIndex) { + return rawDetail.substring(beginIndex).trim(); + } + + private static String extractDetail(String rawDetail, int beginIndex, int endIndex) { + return rawDetail.substring(beginIndex, endIndex).trim(); + } + + +} diff --git a/src/main/java/seedu/duke/parsermanager/ParseDeleteClient.java b/src/main/java/seedu/duke/parsermanager/ParseDeleteClient.java new file mode 100644 index 000000000..5c4339cc2 --- /dev/null +++ b/src/main/java/seedu/duke/parsermanager/ParseDeleteClient.java @@ -0,0 +1,163 @@ +package seedu.duke.parsermanager; + +import seedu.duke.ClientList; +import seedu.duke.command.Command; +import seedu.duke.command.CommandDeleteClient; +import seedu.duke.exception.EmptyDetailException; +import seedu.duke.exception.IncorrectFlagOrderException; +import seedu.duke.exception.InvalidIndexException; +import seedu.duke.exception.MissingFlagException; +import seedu.duke.exception.NotIntegerException; + +import java.util.ArrayList; + +import static seedu.duke.CommandStructure.DELETE_CLIENT_FLAGS; +import static seedu.duke.Messages.EXCEPTION; +import static seedu.duke.Messages.MESSAGE_DELETE_CLIENT_WRONG_FORMAT; +import static seedu.duke.Messages.MESSAGE_INVALID_INDEX; +import static seedu.duke.Messages.MESSAGE_NOT_INTEGER; + +public class ParseDeleteClient extends Parser { + private final String commandDescription; + private final ClientList clientList; + + public ParseDeleteClient(String deleteCommandDescription, ClientList clientList) { + this.commandDescription = deleteCommandDescription; + this.clientList = clientList; + } + + @Override + public Command parseCommand() throws InvalidIndexException, MissingFlagException, IncorrectFlagOrderException, + NotIntegerException, EmptyDetailException { + try { + checkForEmptyDetails(commandDescription); + + ArrayList deleteClientDetailsString = processCommandDetails(commandDescription); + ArrayList deleteClientDetailsInt = convertProcessedCommandDetailsToInteger( + deleteClientDetailsString); + + int clientIndex = deleteClientDetailsInt.get(0); + checkForInvalidClientIndexDelete(clientIndex); + return new CommandDeleteClient(clientIndex); + + } catch (InvalidIndexException e) { + throw new InvalidIndexException(MESSAGE_INVALID_INDEX); + } catch (MissingFlagException e) { + throw new MissingFlagException(MESSAGE_DELETE_CLIENT_WRONG_FORMAT); + } catch (IncorrectFlagOrderException e) { + throw new IncorrectFlagOrderException(MESSAGE_DELETE_CLIENT_WRONG_FORMAT); + } catch (NotIntegerException e) { + throw new NotIntegerException(MESSAGE_NOT_INTEGER); + } catch (EmptyDetailException e) { + throw new EmptyDetailException(MESSAGE_DELETE_CLIENT_WRONG_FORMAT); + } + } + + private void checkForEmptyDetails(String commandDetail) throws EmptyDetailException { + boolean isEmptyDetail = isEmptyString(commandDetail); + if (isEmptyDetail) { + throw new EmptyDetailException(EXCEPTION); + } + } + + private ArrayList processCommandDetails(String rawCommandDetail) + throws MissingFlagException, IncorrectFlagOrderException { + + String[] flags = DELETE_CLIENT_FLAGS; + int[] flagIndexPositions = getFlagIndexPositions(rawCommandDetail, flags); + checkForMissingFlags(flagIndexPositions); + checkFlagsOrder(flagIndexPositions); + return extractCommandDetails(rawCommandDetail, flags, flagIndexPositions); + } + + private boolean isEmptyString(String commandDetail) { + return commandDetail.trim().isEmpty(); + } + + private ArrayList convertProcessedCommandDetailsToInteger(ArrayList processedCommandDetail) + throws NotIntegerException { + ArrayList integerDetails = new ArrayList<>(); + for (String detail : processedCommandDetail) { + int integer; + try { + integer = Integer.parseInt(detail); + } catch (NumberFormatException e) { + throw new NotIntegerException(EXCEPTION); + } + integerDetails.add(integer - 1); // Convert to 0-index + } + return integerDetails; + } + + private void checkForInvalidClientIndexDelete(int clientIndex) throws InvalidIndexException { + int currentListSize = clientList.getCurrentListSize(); + if (clientIndex < 0 || clientIndex >= currentListSize) { + throw new InvalidIndexException(EXCEPTION); + } + } + + private int[] getFlagIndexPositions(String commandDetail, String[] flags) { + int[] flagIndexPositions = new int[flags.length]; + + for (int i = 0; i < flags.length; i++) { + flagIndexPositions[i] = commandDetail.indexOf(flags[i]); + } + return flagIndexPositions; + } + + private void checkForMissingFlags(int[] flagIndexPositions) throws MissingFlagException { + for (int flagIndex : flagIndexPositions) { + if (!isFlagPresent(flagIndex)) { + throw new MissingFlagException(EXCEPTION); + } + } + } + + private void checkFlagsOrder(int[] flagIndexPositions) throws IncorrectFlagOrderException { + for (int i = 0; i < flagIndexPositions.length - 1; i++) { + checkForCorrectFlagOrder(flagIndexPositions[i], flagIndexPositions[i + 1]); + } + } + + private ArrayList extractCommandDetails(String rawCommandDetail, String[] flags, + int[] flagIndexPositions) { + ArrayList extractedCommandDetails = new ArrayList<>(); + for (int i = 0; i < flags.length; i++) { + String extractedDetail; + if (i == flags.length - 1) { + /* The extracted detail for the last flag starts from the char after the flag, to the end of + rawCommandDetails */ + extractedDetail = extractDetail(rawCommandDetail, flagIndexPositions[i] + flags[i].length()); + } else { + // The extracted detail for non-last starts from the char after the flag, to index before the next flag + extractedDetail = extractDetail( + rawCommandDetail, + flagIndexPositions[i] + flags[i].length(), + flagIndexPositions[i + 1]); + } + extractedCommandDetails.add(extractedDetail.trim()); + } + return extractedCommandDetails; + } + + private boolean isFlagPresent(int flagIndexPosition) { + return (flagIndexPosition != -1); + } + + private void checkForCorrectFlagOrder(int flagPosition, int nextFlagPosition) throws IncorrectFlagOrderException { + boolean hasCorrectOrder = (flagPosition < nextFlagPosition); + if (!hasCorrectOrder) { + throw new IncorrectFlagOrderException(EXCEPTION); + } + } + + private static String extractDetail(String rawDetail, int beginIndex) { + return rawDetail.substring(beginIndex).trim(); + } + + private static String extractDetail(String rawDetail, int beginIndex, int endIndex) { + return rawDetail.substring(beginIndex, endIndex).trim(); + } + + +} diff --git a/src/main/java/seedu/duke/parsermanager/ParseDeleteProperty.java b/src/main/java/seedu/duke/parsermanager/ParseDeleteProperty.java new file mode 100644 index 000000000..a76a68fb3 --- /dev/null +++ b/src/main/java/seedu/duke/parsermanager/ParseDeleteProperty.java @@ -0,0 +1,159 @@ +package seedu.duke.parsermanager; + +import seedu.duke.PropertyList; +import seedu.duke.command.Command; +import seedu.duke.command.CommandDeleteProperty; +import seedu.duke.exception.EmptyDetailException; +import seedu.duke.exception.IncorrectFlagOrderException; +import seedu.duke.exception.InvalidIndexException; +import seedu.duke.exception.MissingFlagException; +import seedu.duke.exception.NotIntegerException; + +import java.util.ArrayList; + +import static seedu.duke.CommandStructure.DELETE_PROPERTY_FLAGS; +import static seedu.duke.Messages.EXCEPTION; +import static seedu.duke.Messages.MESSAGE_DELETE_PROPERTY_WRONG_FORMAT; +import static seedu.duke.Messages.MESSAGE_INVALID_INDEX; +import static seedu.duke.Messages.MESSAGE_NOT_INTEGER; + +public class ParseDeleteProperty extends Parser { + private final String commandDescription; + private final PropertyList propertyList; + + public ParseDeleteProperty(String deleteCommandDescription, PropertyList propertyList) { + this.commandDescription = deleteCommandDescription; + this.propertyList = propertyList; + } + + @Override + public Command parseCommand() throws InvalidIndexException, MissingFlagException, IncorrectFlagOrderException, + NotIntegerException, EmptyDetailException { + try { + checkForEmptyDetails(commandDescription); + ArrayList deletePropertyDetailsString = processCommandDetails(commandDescription); + ArrayList deletePropertyDetailsInt = convertProcessedCommandDetailsToInteger( + deletePropertyDetailsString); + + int propertyIndex = deletePropertyDetailsInt.get(0); + checkForInvalidPropertyIndexDelete(propertyIndex); + return new CommandDeleteProperty(propertyIndex); + } catch (InvalidIndexException e) { + throw new InvalidIndexException(MESSAGE_INVALID_INDEX); + } catch (MissingFlagException e) { + throw new MissingFlagException(MESSAGE_DELETE_PROPERTY_WRONG_FORMAT); + } catch (IncorrectFlagOrderException e) { + throw new IncorrectFlagOrderException(MESSAGE_DELETE_PROPERTY_WRONG_FORMAT); + } catch (NotIntegerException e) { + throw new NotIntegerException(MESSAGE_NOT_INTEGER); + } catch (EmptyDetailException e) { + throw new EmptyDetailException(MESSAGE_DELETE_PROPERTY_WRONG_FORMAT); + } + } + + private void checkForEmptyDetails(String commandDetail) throws EmptyDetailException { + boolean isEmptyDetail = isStringEmpty(commandDetail); + if (isEmptyDetail) { + throw new EmptyDetailException(EXCEPTION); + } + } + + private ArrayList processCommandDetails(String rawCommandDetail) + throws MissingFlagException, IncorrectFlagOrderException { + + String[] flags = DELETE_PROPERTY_FLAGS; + int[] flagIndexPositions = getFlagIndexPositions(rawCommandDetail, flags); + checkForMissingFlags(flagIndexPositions); + checkFlagsOrder(flagIndexPositions); + return extractCommandDetails(rawCommandDetail, flags, flagIndexPositions); + } + + private ArrayList convertProcessedCommandDetailsToInteger(ArrayList processedCommandDetails) + throws NotIntegerException { + ArrayList integerDetails = new ArrayList<>(); + for (String detail : processedCommandDetails) { + int integer; + try { + integer = Integer.parseInt(detail); + } catch (NumberFormatException e) { + throw new NotIntegerException(EXCEPTION); + } + integerDetails.add(integer - 1); // Convert to 0-index + } + return integerDetails; + } + + private void checkForInvalidPropertyIndexDelete(int propertyIndex) throws InvalidIndexException { + int currentListSize = propertyList.getCurrentListSize(); + if (propertyIndex < 0 || propertyIndex >= currentListSize) { + throw new InvalidIndexException(EXCEPTION); + } + } + + private boolean isStringEmpty(String commandDetail) { + return commandDetail.trim().isEmpty(); + } + + private int[] getFlagIndexPositions(String commandDetails, String[] flags) { + int[] flagIndexPositions = new int[flags.length]; + + for (int i = 0; i < flags.length; i++) { + flagIndexPositions[i] = commandDetails.indexOf(flags[i]); + } + return flagIndexPositions; + } + + private void checkForMissingFlags(int[] flagIndexPositions) throws MissingFlagException { + for (int flagIndex : flagIndexPositions) { + if (!isFlagPresent(flagIndex)) { + throw new MissingFlagException(EXCEPTION); + } + } + } + + private void checkFlagsOrder(int[] flagIndexPositions) throws IncorrectFlagOrderException { + for (int i = 0; i < flagIndexPositions.length - 1; i++) { + checkForCorrectFlagOrder(flagIndexPositions[i], flagIndexPositions[i + 1]); + } + } + + private ArrayList extractCommandDetails(String rawCommandDetail, String[] flags, + int[] flagIndexPositions) { + ArrayList extractedCommandDetails = new ArrayList<>(); + for (int i = 0; i < flags.length; i++) { + String extractedDetail; + if (i == flags.length - 1) { + /* The extracted detail for the last flag starts from the char after the flag, to the end of + rawCommandDetails */ + extractedDetail = extractDetail(rawCommandDetail, flagIndexPositions[i] + flags[i].length()); + } else { + // The extracted detail for non-last starts from the char after the flag, to index before the next flag + extractedDetail = extractDetail( + rawCommandDetail, + flagIndexPositions[i] + flags[i].length(), + flagIndexPositions[i + 1]); + } + extractedCommandDetails.add(extractedDetail.trim()); + } + return extractedCommandDetails; + } + + private boolean isFlagPresent(int flagIndexPosition) { + return (flagIndexPosition != -1); + } + + private void checkForCorrectFlagOrder(int flagPosition, int nextFlagPosition) throws IncorrectFlagOrderException { + boolean hasCorrectOrder = (flagPosition < nextFlagPosition); + if (!hasCorrectOrder) { + throw new IncorrectFlagOrderException(EXCEPTION); + } + } + + private static String extractDetail(String rawDetail, int beginIndex) { + return rawDetail.substring(beginIndex).trim(); + } + + private static String extractDetail(String rawDetail, int beginIndex, int endIndex) { + return rawDetail.substring(beginIndex, endIndex).trim(); + } +} diff --git a/src/main/java/seedu/duke/parsermanager/ParseExit.java b/src/main/java/seedu/duke/parsermanager/ParseExit.java new file mode 100644 index 000000000..9d68b0356 --- /dev/null +++ b/src/main/java/seedu/duke/parsermanager/ParseExit.java @@ -0,0 +1,31 @@ +package seedu.duke.parsermanager; + +import seedu.duke.command.Command; +import seedu.duke.command.CommandBye; +import seedu.duke.exception.ExtraParametersException; + +import static seedu.duke.Messages.MESSAGE_BYE_PARAMETERS_PRESENT; + +public class ParseExit extends Parser { + + private final String commandDetail; + + public ParseExit(String exitCommandDescription) { + this.commandDetail = exitCommandDescription; + } + + @Override + public Command parseCommand() throws ExtraParametersException { + checkForEmptyDescription(commandDetail); + return new CommandBye(); + } + + private void checkForEmptyDescription(String commandDetail) throws ExtraParametersException { + boolean isNotEmpty = !commandDetail.trim().isEmpty(); + + if (isNotEmpty) { + throw new ExtraParametersException(MESSAGE_BYE_PARAMETERS_PRESENT); + } + + } +} diff --git a/src/main/java/seedu/duke/parsermanager/ParseListClient.java b/src/main/java/seedu/duke/parsermanager/ParseListClient.java new file mode 100644 index 000000000..c0894df0c --- /dev/null +++ b/src/main/java/seedu/duke/parsermanager/ParseListClient.java @@ -0,0 +1,34 @@ +package seedu.duke.parsermanager; + +import seedu.duke.command.Command; +import seedu.duke.command.CommandListClients; +import seedu.duke.exception.EmptyDescriptionException; + +import static seedu.duke.Messages.MESSAGE_EMPTY_DESCRIPTION; + +public class ParseListClient extends Parser { + private final String commandDetail; + + public ParseListClient(String listClientCommandDescription) { + this.commandDetail = listClientCommandDescription; + } + + @Override + public Command parseCommand() throws EmptyDescriptionException { + checkForEmptyDescription(commandDetail); + return new CommandListClients(); + } + + private void checkForEmptyDescription(String commandDetail) throws EmptyDescriptionException { + boolean isEmptyDescription = isEmptyString(commandDetail); + if (isEmptyDescription) { + throw new EmptyDescriptionException(MESSAGE_EMPTY_DESCRIPTION); + } + } + + private boolean isEmptyString(String commandDetail) { + return commandDetail.trim().isEmpty(); + } + + +} diff --git a/src/main/java/seedu/duke/parsermanager/ParseListProperty.java b/src/main/java/seedu/duke/parsermanager/ParseListProperty.java new file mode 100644 index 000000000..ec11f9b09 --- /dev/null +++ b/src/main/java/seedu/duke/parsermanager/ParseListProperty.java @@ -0,0 +1,33 @@ +package seedu.duke.parsermanager; + +import seedu.duke.command.Command; +import seedu.duke.command.CommandListProperties; +import seedu.duke.exception.EmptyDescriptionException; + +import static seedu.duke.Messages.MESSAGE_EMPTY_DESCRIPTION; + +public class ParseListProperty extends Parser { + + private final String commandDetail; + + public ParseListProperty(String listPropertyCommandDescription) { + this.commandDetail = listPropertyCommandDescription; + } + + @Override + public Command parseCommand() throws EmptyDescriptionException { + checkForEmptyDescription(commandDetail); + return new CommandListProperties(); + } + + private void checkForEmptyDescription(String commandDetail) throws EmptyDescriptionException { + boolean isEmptyDescription = isEmptyString(commandDetail); + if (isEmptyDescription) { + throw new EmptyDescriptionException(MESSAGE_EMPTY_DESCRIPTION); + } + } + + private boolean isEmptyString(String commandDetail) { + return commandDetail.trim().isEmpty(); + } +} diff --git a/src/main/java/seedu/duke/parsermanager/ParsePair.java b/src/main/java/seedu/duke/parsermanager/ParsePair.java new file mode 100644 index 000000000..0ae81ca26 --- /dev/null +++ b/src/main/java/seedu/duke/parsermanager/ParsePair.java @@ -0,0 +1,204 @@ +package seedu.duke.parsermanager; + +import seedu.duke.Client; +import seedu.duke.ClientList; +import seedu.duke.PairingList; +import seedu.duke.Property; +import seedu.duke.PropertyList; +import seedu.duke.command.Command; +import seedu.duke.command.CommandPair; +import seedu.duke.exception.ClientAlreadyPairedException; +import seedu.duke.exception.EmptyDescriptionException; +import seedu.duke.exception.ExistingPairException; +import seedu.duke.exception.IncorrectFlagOrderException; +import seedu.duke.exception.InvalidIndexException; +import seedu.duke.exception.MissingFlagException; +import seedu.duke.exception.NotIntegerException; + +import java.util.ArrayList; + +import static seedu.duke.CommandStructure.PAIR_FLAGS; +import static seedu.duke.Messages.EXCEPTION; +import static seedu.duke.Messages.MESSAGE_CLIENT_ALREADY_PAIRED; +import static seedu.duke.Messages.MESSAGE_EMPTY_DESCRIPTION; +import static seedu.duke.Messages.MESSAGE_EXISTING_PAIR; +import static seedu.duke.Messages.MESSAGE_INVALID_INDEX; +import static seedu.duke.Messages.MESSAGE_NOT_INTEGER; +import static seedu.duke.Messages.MESSAGE_PAIR_WRONG_FORMAT; + +public class ParsePair extends Parser { + private final String commandDescription; + private static ClientList clientList; + private static PropertyList propertyList; + private static PairingList pairingList; + + public ParsePair(String pairCommandDescription, ClientList clientL, + PropertyList propertyL, PairingList pairingL) { + commandDescription = pairCommandDescription; + clientList = clientL; + propertyList = propertyL; + pairingList = pairingL; + } + + @Override + public Command parseCommand() throws InvalidIndexException, ClientAlreadyPairedException, MissingFlagException, + IncorrectFlagOrderException, NotIntegerException, ExistingPairException, EmptyDescriptionException { + try { + + checkForEmptyDescription(commandDescription); + ArrayList pairDetailsString = processCommandDetails(commandDescription); + ArrayList pairDetailsInt = convertProcessedCommandDetailsToInteger(pairDetailsString); + + validatePairDetails(pairDetailsInt); + return new CommandPair(pairDetailsInt); + } catch (InvalidIndexException e) { + throw new InvalidIndexException(MESSAGE_INVALID_INDEX); + } catch (ClientAlreadyPairedException e) { + throw new ClientAlreadyPairedException(MESSAGE_CLIENT_ALREADY_PAIRED); + } catch (MissingFlagException e) { + throw new MissingFlagException(MESSAGE_PAIR_WRONG_FORMAT); + } catch (IncorrectFlagOrderException e) { + throw new IncorrectFlagOrderException(MESSAGE_PAIR_WRONG_FORMAT); + } catch (NotIntegerException e) { + throw new NotIntegerException(MESSAGE_NOT_INTEGER); + } catch (ExistingPairException e) { + throw new ExistingPairException(MESSAGE_EXISTING_PAIR); + } + } + + private void checkForEmptyDescription(String commandDetail) throws EmptyDescriptionException { + boolean isEmptyDescription = isEmptyString(commandDetail); + if (isEmptyDescription) { + throw new EmptyDescriptionException(MESSAGE_EMPTY_DESCRIPTION); + } + } + + private boolean isEmptyString(String commandDetail) { + return commandDetail.trim().isEmpty(); + } + + + private ArrayList processCommandDetails(String rawCommandDetail) + throws MissingFlagException, IncorrectFlagOrderException { + + String[] flags = PAIR_FLAGS; + int[] flagIndexPositions = getFlagIndexPositions(rawCommandDetail, flags); + checkForMissingFlags(flagIndexPositions); + checkFlagsOrder(flagIndexPositions); + return extractCommandDetails(rawCommandDetail, flags, flagIndexPositions); + } + + private ArrayList convertProcessedCommandDetailsToInteger(ArrayList processedCommandDetails) + throws NotIntegerException { + ArrayList integerDetails = new ArrayList<>(); + for (String detail : processedCommandDetails) { + int integer; + try { + integer = Integer.parseInt(detail); + } catch (NumberFormatException e) { + throw new NotIntegerException(EXCEPTION); + } + integerDetails.add(integer - 1); // Convert to 0-index + } + return integerDetails; + } + + private void validatePairDetails(ArrayList pairDetails) throws InvalidIndexException, + ClientAlreadyPairedException, ExistingPairException { + int propertyIndex = pairDetails.get(0); + int clientIndex = pairDetails.get(1); + checkForClientListIndexOutOfBounds(clientIndex); + checkForPropertyListIndexOutOfBounds(propertyIndex); + + Client client = clientList.getClientList().get(clientIndex); + Property property = propertyList.getPropertyList().get(propertyIndex); + + if (pairingList.isAlreadyPaired(client, property)) { + throw new ExistingPairException(EXCEPTION); + } + + if (pairingList.isClientPairedWithProperty(client)) { + throw new ClientAlreadyPairedException(EXCEPTION); + } + } + + private int[] getFlagIndexPositions(String commandDetail, String[] flags) { + int[] flagIndexPositions = new int[flags.length]; + + for (int i = 0; i < flags.length; i++) { + flagIndexPositions[i] = commandDetail.indexOf(flags[i]); + } + return flagIndexPositions; + } + + private void checkForMissingFlags(int[] flagIndexPositions) throws MissingFlagException { + for (int flagIndex : flagIndexPositions) { + if (!isFlagPresent(flagIndex)) { + throw new MissingFlagException(EXCEPTION); + } + } + } + + private void checkFlagsOrder(int[] flagIndexPositions) throws IncorrectFlagOrderException { + for (int i = 0; i < flagIndexPositions.length - 1; i++) { + checkForCorrectFlagOrder(flagIndexPositions[i], flagIndexPositions[i + 1]); + } + } + + private ArrayList extractCommandDetails(String rawCommandDetail, String[] flags, + int[] flagIndexPositions) { + ArrayList extractedCommandDetails = new ArrayList<>(); + for (int i = 0; i < flags.length; i++) { + String extractedDetail; + if (i == flags.length - 1) { + /* The extracted detail for the last flag starts from the char after the flag, to the end of + rawCommandDetails */ + extractedDetail = extractDetail(rawCommandDetail, flagIndexPositions[i] + flags[i].length()); + } else { + // The extracted detail for non-last starts from the char after the flag, to index before the next flag + extractedDetail = extractDetail( + rawCommandDetail, + flagIndexPositions[i] + flags[i].length(), + flagIndexPositions[i + 1]); + } + extractedCommandDetails.add(extractedDetail.trim()); + } + return extractedCommandDetails; + } + + private void checkForClientListIndexOutOfBounds(int clientIndex) throws InvalidIndexException { + if (clientIndex < 0 || clientIndex > clientList.getCurrentListSize() - 1) { + throw new InvalidIndexException(EXCEPTION); + } + } + + private void checkForPropertyListIndexOutOfBounds(int propertyIndex) throws InvalidIndexException { + if (propertyIndex < 0 || propertyIndex > propertyList.getCurrentListSize() - 1) { + throw new InvalidIndexException(EXCEPTION); + } + } + + private boolean isFlagPresent(int flagIndexPosition) { + return (flagIndexPosition != -1); + } + + private void checkForCorrectFlagOrder(int flagPosition, int nextFlagPosition) throws IncorrectFlagOrderException { + boolean hasCorrectOrder = (flagPosition < nextFlagPosition); + if (!hasCorrectOrder) { + throw new IncorrectFlagOrderException(EXCEPTION); + } + } + + private static String extractDetail(String rawDetail, int beginIndex) { + return rawDetail.substring(beginIndex).trim(); + } + + private static String extractDetail(String rawDetail, int beginIndex, int endIndex) { + return rawDetail.substring(beginIndex, endIndex).trim(); + } + + + + + +} diff --git a/src/main/java/seedu/duke/parsermanager/ParseUndefined.java b/src/main/java/seedu/duke/parsermanager/ParseUndefined.java new file mode 100644 index 000000000..fd8c81044 --- /dev/null +++ b/src/main/java/seedu/duke/parsermanager/ParseUndefined.java @@ -0,0 +1,15 @@ +package seedu.duke.parsermanager; + +import seedu.duke.command.Command; +import seedu.duke.command.CommandUndefined; + +public class ParseUndefined extends Parser { + public ParseUndefined() { + + } + + @Override + public Command parseCommand() { + return new CommandUndefined(); + } +} diff --git a/src/main/java/seedu/duke/parsermanager/ParseUnpair.java b/src/main/java/seedu/duke/parsermanager/ParseUnpair.java new file mode 100644 index 000000000..da61d005a --- /dev/null +++ b/src/main/java/seedu/duke/parsermanager/ParseUnpair.java @@ -0,0 +1,192 @@ +package seedu.duke.parsermanager; + +import seedu.duke.Client; +import seedu.duke.ClientList; +import seedu.duke.PairingList; +import seedu.duke.Property; +import seedu.duke.PropertyList; +import seedu.duke.command.Command; +import seedu.duke.command.CommandUnpair; +import seedu.duke.exception.EmptyDescriptionException; +import seedu.duke.exception.IncorrectFlagOrderException; +import seedu.duke.exception.InvalidIndexException; +import seedu.duke.exception.MissingFlagException; +import seedu.duke.exception.NoExistingPairException; +import seedu.duke.exception.NotIntegerException; + +import java.util.ArrayList; + +import static seedu.duke.CommandStructure.UNPAIR_FLAGS; +import static seedu.duke.Messages.EXCEPTION; +import static seedu.duke.Messages.MESSAGE_EMPTY_DESCRIPTION; +import static seedu.duke.Messages.MESSAGE_INVALID_INDEX; +import static seedu.duke.Messages.MESSAGE_NOT_INTEGER; +import static seedu.duke.Messages.MESSAGE_NO_EXISTING_PAIR; +import static seedu.duke.Messages.MESSAGE_UNPAIR_WRONG_FORMAT; + +public class ParseUnpair extends Parser { + private final String commandDescription; + private final ClientList clientList; + private final PropertyList propertyList; + private final PairingList pairingList; + + public ParseUnpair(String unpairCommandDescription, ClientList clientList, + PropertyList propertyList, PairingList pairingList) { + this.commandDescription = unpairCommandDescription; + this.clientList = clientList; + this.propertyList = propertyList; + this.pairingList = pairingList; + } + + @Override + public Command parseCommand() throws InvalidIndexException, NoExistingPairException, MissingFlagException, + IncorrectFlagOrderException, NotIntegerException, EmptyDescriptionException { + try { + checkForEmptyDescription(commandDescription); + ArrayList unpairDetailsString = processCommandDetails(commandDescription); + ArrayList unpairDetailsInt = convertProcessedCommandDetailsToInteger(unpairDetailsString); + + validateUnpairDetails(unpairDetailsInt); + return new CommandUnpair(unpairDetailsInt); + } catch (InvalidIndexException e) { + throw new InvalidIndexException(MESSAGE_INVALID_INDEX); + } catch (NoExistingPairException e) { + throw new NoExistingPairException(MESSAGE_NO_EXISTING_PAIR); + } catch (MissingFlagException e) { + throw new MissingFlagException(MESSAGE_UNPAIR_WRONG_FORMAT); + } catch (IncorrectFlagOrderException e) { + throw new IncorrectFlagOrderException(MESSAGE_UNPAIR_WRONG_FORMAT); + } catch (NotIntegerException e) { + throw new NotIntegerException(MESSAGE_NOT_INTEGER); + } + } + + private void checkForEmptyDescription(String commandDetail) throws EmptyDescriptionException { + boolean isEmptyDescription = isEmptyString(commandDetail); + if (isEmptyDescription) { + throw new EmptyDescriptionException(MESSAGE_EMPTY_DESCRIPTION); + } + } + + private boolean isEmptyString(String commandDetail) { + return commandDetail.trim().isEmpty(); + } + + private ArrayList processCommandDetails(String rawCommandDetail) + throws MissingFlagException, IncorrectFlagOrderException { + + String[] flags = UNPAIR_FLAGS; + int[] flagIndexPositions = getFlagIndexPositions(rawCommandDetail, flags); + checkForMissingFlags(flagIndexPositions); + checkFlagsOrder(flagIndexPositions); + return extractCommandDetails(rawCommandDetail, flags, flagIndexPositions); + } + + private ArrayList convertProcessedCommandDetailsToInteger(ArrayList processedCommandDetails) + throws NotIntegerException { + ArrayList integerDetails = new ArrayList<>(); + for (String detail : processedCommandDetails) { + int integer; + try { + integer = Integer.parseInt(detail); + } catch (NumberFormatException e) { + throw new NotIntegerException(EXCEPTION); + } + integerDetails.add(integer - 1); // Convert to 0-index + } + return integerDetails; + } + + private void validateUnpairDetails(ArrayList unpairDetails) throws InvalidIndexException, + NoExistingPairException { + int propertyIndex = unpairDetails.get(0); + int clientIndex = unpairDetails.get(1); + + checkForClientListIndexOutOfBounds(clientIndex); + checkForPropertyListIndexOutOfBounds(propertyIndex); + + Client client = clientList.getClientList().get(clientIndex); + Property property = propertyList.getPropertyList().get(propertyIndex); + + if (!pairingList.isAlreadyPaired(client, property)) { + throw new NoExistingPairException(EXCEPTION); + } + } + + private int[] getFlagIndexPositions(String commandDetail, String[] flags) { + int[] flagIndexPositions = new int[flags.length]; + + for (int i = 0; i < flags.length; i++) { + flagIndexPositions[i] = commandDetail.indexOf(flags[i]); + } + return flagIndexPositions; + } + + private void checkForMissingFlags(int[] flagIndexPositions) throws MissingFlagException { + for (int flagIndex : flagIndexPositions) { + if (!isFlagPresent(flagIndex)) { + throw new MissingFlagException(EXCEPTION); + } + } + } + + private void checkFlagsOrder(int[] flagIndexPositions) throws IncorrectFlagOrderException { + for (int i = 0; i < flagIndexPositions.length - 1; i++) { + checkForCorrectFlagOrder(flagIndexPositions[i], flagIndexPositions[i + 1]); + } + } + + private ArrayList extractCommandDetails(String rawCommandDetail, String[] flags, + int[] flagIndexPositions) { + ArrayList extractedCommandDetails = new ArrayList<>(); + for (int i = 0; i < flags.length; i++) { + String extractedDetail; + if (i == flags.length - 1) { + /* The extracted detail for the last flag starts from the char after the flag, to the end of + rawCommandDetails */ + extractedDetail = extractDetail(rawCommandDetail, flagIndexPositions[i] + flags[i].length()); + } else { + // The extracted detail for non-last starts from the char after the flag, to index before the next flag + extractedDetail = extractDetail( + rawCommandDetail, + flagIndexPositions[i] + flags[i].length(), + flagIndexPositions[i + 1]); + } + extractedCommandDetails.add(extractedDetail.trim()); + } + return extractedCommandDetails; + } + + private void checkForClientListIndexOutOfBounds(int clientIndex) throws InvalidIndexException { + if (clientIndex < 0 || clientIndex > clientList.getCurrentListSize() - 1) { + throw new InvalidIndexException(EXCEPTION); + } + } + + private void checkForPropertyListIndexOutOfBounds(int propertyIndex) throws InvalidIndexException { + if (propertyIndex < 0 || propertyIndex > propertyList.getCurrentListSize() - 1) { + throw new InvalidIndexException(EXCEPTION); + } + } + + private boolean isFlagPresent(int flagIndexPosition) { + return (flagIndexPosition != -1); + } + + private void checkForCorrectFlagOrder(int flagPosition, int nextFlagPosition) throws IncorrectFlagOrderException { + boolean hasCorrectOrder = (flagPosition < nextFlagPosition); + if (!hasCorrectOrder) { + throw new IncorrectFlagOrderException(EXCEPTION); + } + } + + private static String extractDetail(String rawDetail, int beginIndex) { + return rawDetail.substring(beginIndex).trim(); + } + + private static String extractDetail(String rawDetail, int beginIndex, int endIndex) { + return rawDetail.substring(beginIndex, endIndex).trim(); + } + + +} diff --git a/src/main/java/seedu/duke/parsermanager/Parser.java b/src/main/java/seedu/duke/parsermanager/Parser.java new file mode 100644 index 000000000..8b46e858c --- /dev/null +++ b/src/main/java/seedu/duke/parsermanager/Parser.java @@ -0,0 +1,26 @@ +package seedu.duke.parsermanager; + +import seedu.duke.command.Command; +import seedu.duke.exception.ClientAlreadyPairedException; +import seedu.duke.exception.EmptyDescriptionException; +import seedu.duke.exception.EmptyDetailException; +import seedu.duke.exception.ExistingPairException; +import seedu.duke.exception.ExtraParametersException; +import seedu.duke.exception.IncorrectFlagOrderException; +import seedu.duke.exception.InvalidBudgetFormatException; +import seedu.duke.exception.InvalidContactNumberException; +import seedu.duke.exception.InvalidEmailException; +import seedu.duke.exception.InvalidIndexException; +import seedu.duke.exception.InvalidPriceFormatException; +import seedu.duke.exception.InvalidSingaporeAddressException; +import seedu.duke.exception.MissingFlagException; +import seedu.duke.exception.NoExistingPairException; +import seedu.duke.exception.NotIntegerException; + +public abstract class Parser { + public abstract Command parseCommand() throws EmptyDescriptionException, InvalidSingaporeAddressException, + MissingFlagException, IncorrectFlagOrderException, InvalidPriceFormatException, EmptyDetailException, + InvalidContactNumberException, InvalidEmailException, InvalidBudgetFormatException, InvalidIndexException, + NotIntegerException, ClientAlreadyPairedException, ExistingPairException, NoExistingPairException, + ExtraParametersException; +} diff --git a/src/main/java/seedu/duke/parsermanager/ParserManager.java b/src/main/java/seedu/duke/parsermanager/ParserManager.java new file mode 100644 index 000000000..eccc745bc --- /dev/null +++ b/src/main/java/seedu/duke/parsermanager/ParserManager.java @@ -0,0 +1,129 @@ +package seedu.duke.parsermanager; + +import seedu.duke.ClientList; +import seedu.duke.PairingList; +import seedu.duke.PropertyList; +import seedu.duke.exception.ClientAlreadyPairedException; +import seedu.duke.exception.DukeParseException; +import seedu.duke.exception.ExistingPairException; +import seedu.duke.exception.NoExistingPairException; +import seedu.duke.exception.UndefinedSubCommandTypeException; + +import java.util.ArrayList; + +import static seedu.duke.CommandStructure.COMMAND_ADD; +import static seedu.duke.CommandStructure.COMMAND_CHECK; +import static seedu.duke.CommandStructure.COMMAND_DELETE; +import static seedu.duke.CommandStructure.COMMAND_EXIT; +import static seedu.duke.CommandStructure.COMMAND_LIST; +import static seedu.duke.CommandStructure.COMMAND_PAIR; +import static seedu.duke.CommandStructure.COMMAND_UNPAIR; +import static seedu.duke.Messages.MESSAGE_INCORRECT_LIST_DETAILS; +import static seedu.duke.Messages.MESSAGE_MISSING_SUB_COMMAND_TYPE; + +public class ParserManager { + private static ClientList clientList; + private static PropertyList propertyList; + private static PairingList pairingList; + + private static final String EMPTY_SPACE = " "; + private static final String EMPTY_STRING = ""; + private static final int MAX_LENGTH = 2; + private static final int COMMAND_TYPE_INDEX = 0; + private static final int SUB_COMMAND_INDEX = 0; + private static final int COMMAND_FLAG_INDEX = 1; + private static final int COMMAND_DESCRIPTION_INDEX = 1; + private static final String PROPERTY_FLAG = "-property"; + private static final String CLIENT_FLAG = "-client"; + + public ParserManager(ClientList clientL, PropertyList propertyL, PairingList pairingL) { + clientList = clientL; + propertyList = propertyL; + pairingList = pairingL; + } + + public Parser parseCommand(String input) throws DukeParseException, ExistingPairException, + ClientAlreadyPairedException, NoExistingPairException { + + ArrayList processedCommandDetails = splitCommandAndCommandType(input); + String commandType = processedCommandDetails.get(COMMAND_TYPE_INDEX); + String commandDetail = processedCommandDetails.get(COMMAND_FLAG_INDEX); + + switch (commandType) { + case COMMAND_ADD: + ArrayList processedAddCommandDetails = splitCommandAndCommandType(commandDetail); + String subAddCommandType = processedAddCommandDetails.get(SUB_COMMAND_INDEX); + String addCommandDescription = processedAddCommandDetails.get(COMMAND_DESCRIPTION_INDEX); + + boolean isAddProperty = subAddCommandType.equals(PROPERTY_FLAG); + boolean isAddClient = subAddCommandType.equals(CLIENT_FLAG); + + if (isAddProperty) { + return new ParseAddProperty(addCommandDescription); + } else if (isAddClient) { + return new ParseAddClient(addCommandDescription); + } else { + throw new UndefinedSubCommandTypeException(MESSAGE_MISSING_SUB_COMMAND_TYPE); + } + case COMMAND_DELETE: + ArrayList processedDeleteCommandDetails = splitCommandAndCommandType(commandDetail); + String subDeleteCommandType = processedDeleteCommandDetails.get(SUB_COMMAND_INDEX); + String deleteCommandDescription = processedDeleteCommandDetails.get(COMMAND_DESCRIPTION_INDEX); + + boolean isDeleteProperty = subDeleteCommandType.equals(PROPERTY_FLAG); + boolean isDeleteClient = subDeleteCommandType.equals(CLIENT_FLAG); + + if (isDeleteProperty) { + return new ParseDeleteProperty(deleteCommandDescription, propertyList); + } else if (isDeleteClient) { + return new ParseDeleteClient(deleteCommandDescription, clientList); + } else { + throw new UndefinedSubCommandTypeException(MESSAGE_MISSING_SUB_COMMAND_TYPE); + } + case COMMAND_PAIR: + return new ParsePair(commandDetail, clientList, propertyList, pairingList); + case COMMAND_UNPAIR: + return new ParseUnpair(commandDetail, clientList, propertyList, pairingList); + case COMMAND_CHECK: + ArrayList processedCheckCommandDetail = splitCommandAndCommandType(commandDetail); + String subCheckCommandType = processedCheckCommandDetail.get(SUB_COMMAND_INDEX); + + boolean isProperty = subCheckCommandType.equals(subCheckCommandType); + + if (isProperty) { + return new ParseCheckProperty(commandDetail, propertyList); + } else { + throw new UndefinedSubCommandTypeException(MESSAGE_MISSING_SUB_COMMAND_TYPE); + } + case COMMAND_LIST: + boolean isListProperty = commandDetail.trim().equals(PROPERTY_FLAG); + boolean isListClient = commandDetail.trim().equals(CLIENT_FLAG); + + if (isListProperty) { + return new ParseListProperty(commandDetail); + } else if (isListClient) { + return new ParseListClient(commandDetail); + } else { + throw new UndefinedSubCommandTypeException(MESSAGE_INCORRECT_LIST_DETAILS); + } + case COMMAND_EXIT: + return new ParseExit(commandDetail); + default: + return new ParseUndefined(); + } + } + + private ArrayList splitCommandAndCommandType(String fullCommandDetail) { + String[] inputDetails = fullCommandDetail.split(EMPTY_SPACE, MAX_LENGTH); + + String commandType = inputDetails[COMMAND_TYPE_INDEX]; + String commandFlag = fullCommandDetail.replaceFirst(commandType, EMPTY_STRING).trim(); + + ArrayList processedCommandDetails = new ArrayList<>(); + processedCommandDetails.add(commandType); + processedCommandDetails.add(commandFlag); + + return processedCommandDetails; + } + +} From 60d2cede86816fdf6e8c2bda71badc4c62966f1e Mon Sep 17 00:00:00 2001 From: "MSI\\User" Date: Tue, 18 Oct 2022 07:49:37 +0800 Subject: [PATCH 084/325] Enable assertion in build.gradle --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index b0c5528fb..91fffd027 100644 --- a/build.gradle +++ b/build.gradle @@ -43,4 +43,5 @@ checkstyle { run{ standardInput = System.in + enableAssertions = true } From 045721daae3ddd7316f8673c5f239ed8e01086c0 Mon Sep 17 00:00:00 2001 From: "MSI\\User" Date: Tue, 18 Oct 2022 17:20:14 +0800 Subject: [PATCH 085/325] Fix spelling mistake on variable in Storage.java --- src/main/java/seedu/duke/Storage.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/duke/Storage.java b/src/main/java/seedu/duke/Storage.java index 2a9f6aac8..1e94a4936 100644 --- a/src/main/java/seedu/duke/Storage.java +++ b/src/main/java/seedu/duke/Storage.java @@ -207,14 +207,14 @@ public void loadPair(PairingList pairingList, File pairFile) { while (scanner.hasNext()) { String[] pairingParameters = scanner.nextLine().split("\\s\\:\\s"); - String[] clientParamters = pairingParameters[0].split("\\s\\|\\s"); + String[] clientParameters = pairingParameters[0].split("\\s\\|\\s"); String[] propertyParameters = pairingParameters[1].split("\\s\\|\\s"); //Client Information - String clientName = clientParamters[0].replace(OPEN_BRACKET, EMPTY_STRING); - String clientContactNumber = clientParamters[1]; - String clientEmail = clientParamters[2]; - String clientBudget = clientParamters[3].replace(CLOSE_BRACKET, EMPTY_STRING); + String clientName = clientParameters[0].replace(OPEN_BRACKET, EMPTY_STRING); + String clientContactNumber = clientParameters[1]; + String clientEmail = clientParameters[2]; + String clientBudget = clientParameters[3].replace(CLOSE_BRACKET, EMPTY_STRING); //Property Information String landLordName = propertyParameters[0].replace(OPEN_BRACKET,EMPTY_STRING); From c27bed995826a1f82ef15e2e1b522f145f2ddfc4 Mon Sep 17 00:00:00 2001 From: ngdeqi Date: Tue, 18 Oct 2022 20:09:27 +0800 Subject: [PATCH 086/325] Move client and property subcommand flags to CommandStructure --- src/main/java/seedu/duke/CommandStructure.java | 3 +++ src/main/java/seedu/duke/parsermanager/ParserManager.java | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/duke/CommandStructure.java b/src/main/java/seedu/duke/CommandStructure.java index fc5997dd3..eca5b0b78 100644 --- a/src/main/java/seedu/duke/CommandStructure.java +++ b/src/main/java/seedu/duke/CommandStructure.java @@ -10,6 +10,9 @@ public class CommandStructure { public static final String COMMAND_CHECK = "check"; public static final String COMMAND_EXIT = "quit"; + public static final String PROPERTY_FLAG = "-property"; + public static final String CLIENT_FLAG = "-client"; + public static final String[] ADD_PROPERTY_FLAGS = {"n/", "a/", "p/", "t/"}; public static final String[] ADD_CLIENT_FLAGS = {"n/", "c/", "e/", "b/"}; diff --git a/src/main/java/seedu/duke/parsermanager/ParserManager.java b/src/main/java/seedu/duke/parsermanager/ParserManager.java index eccc745bc..b74d4416d 100644 --- a/src/main/java/seedu/duke/parsermanager/ParserManager.java +++ b/src/main/java/seedu/duke/parsermanager/ParserManager.java @@ -11,6 +11,7 @@ import java.util.ArrayList; +import static seedu.duke.CommandStructure.CLIENT_FLAG; import static seedu.duke.CommandStructure.COMMAND_ADD; import static seedu.duke.CommandStructure.COMMAND_CHECK; import static seedu.duke.CommandStructure.COMMAND_DELETE; @@ -18,6 +19,7 @@ import static seedu.duke.CommandStructure.COMMAND_LIST; import static seedu.duke.CommandStructure.COMMAND_PAIR; import static seedu.duke.CommandStructure.COMMAND_UNPAIR; +import static seedu.duke.CommandStructure.PROPERTY_FLAG; import static seedu.duke.Messages.MESSAGE_INCORRECT_LIST_DETAILS; import static seedu.duke.Messages.MESSAGE_MISSING_SUB_COMMAND_TYPE; @@ -33,8 +35,6 @@ public class ParserManager { private static final int SUB_COMMAND_INDEX = 0; private static final int COMMAND_FLAG_INDEX = 1; private static final int COMMAND_DESCRIPTION_INDEX = 1; - private static final String PROPERTY_FLAG = "-property"; - private static final String CLIENT_FLAG = "-client"; public ParserManager(ClientList clientL, PropertyList propertyL, PairingList pairingL) { clientList = clientL; From cfdf4ab30012d6f10291806524406206dc0deea0 Mon Sep 17 00:00:00 2001 From: ngdeqi Date: Tue, 18 Oct 2022 20:10:50 +0800 Subject: [PATCH 087/325] Revert "Move client and property subcommand flags to CommandStructure" This reverts commit c27bed995826a1f82ef15e2e1b522f145f2ddfc4. --- src/main/java/seedu/duke/CommandStructure.java | 3 --- src/main/java/seedu/duke/parsermanager/ParserManager.java | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/duke/CommandStructure.java b/src/main/java/seedu/duke/CommandStructure.java index eca5b0b78..fc5997dd3 100644 --- a/src/main/java/seedu/duke/CommandStructure.java +++ b/src/main/java/seedu/duke/CommandStructure.java @@ -10,9 +10,6 @@ public class CommandStructure { public static final String COMMAND_CHECK = "check"; public static final String COMMAND_EXIT = "quit"; - public static final String PROPERTY_FLAG = "-property"; - public static final String CLIENT_FLAG = "-client"; - public static final String[] ADD_PROPERTY_FLAGS = {"n/", "a/", "p/", "t/"}; public static final String[] ADD_CLIENT_FLAGS = {"n/", "c/", "e/", "b/"}; diff --git a/src/main/java/seedu/duke/parsermanager/ParserManager.java b/src/main/java/seedu/duke/parsermanager/ParserManager.java index b74d4416d..eccc745bc 100644 --- a/src/main/java/seedu/duke/parsermanager/ParserManager.java +++ b/src/main/java/seedu/duke/parsermanager/ParserManager.java @@ -11,7 +11,6 @@ import java.util.ArrayList; -import static seedu.duke.CommandStructure.CLIENT_FLAG; import static seedu.duke.CommandStructure.COMMAND_ADD; import static seedu.duke.CommandStructure.COMMAND_CHECK; import static seedu.duke.CommandStructure.COMMAND_DELETE; @@ -19,7 +18,6 @@ import static seedu.duke.CommandStructure.COMMAND_LIST; import static seedu.duke.CommandStructure.COMMAND_PAIR; import static seedu.duke.CommandStructure.COMMAND_UNPAIR; -import static seedu.duke.CommandStructure.PROPERTY_FLAG; import static seedu.duke.Messages.MESSAGE_INCORRECT_LIST_DETAILS; import static seedu.duke.Messages.MESSAGE_MISSING_SUB_COMMAND_TYPE; @@ -35,6 +33,8 @@ public class ParserManager { private static final int SUB_COMMAND_INDEX = 0; private static final int COMMAND_FLAG_INDEX = 1; private static final int COMMAND_DESCRIPTION_INDEX = 1; + private static final String PROPERTY_FLAG = "-property"; + private static final String CLIENT_FLAG = "-client"; public ParserManager(ClientList clientL, PropertyList propertyL, PairingList pairingL) { clientList = clientL; From 662c302d394836bf809dfcb3c71d90b1161b2b27 Mon Sep 17 00:00:00 2001 From: ngdeqi Date: Tue, 18 Oct 2022 20:13:21 +0800 Subject: [PATCH 088/325] Move client and property subcommand flags to CommandStructure class --- src/main/java/seedu/duke/CommandStructure.java | 2 ++ src/main/java/seedu/duke/parsermanager/ParserManager.java | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/duke/CommandStructure.java b/src/main/java/seedu/duke/CommandStructure.java index fc5997dd3..685acbf38 100644 --- a/src/main/java/seedu/duke/CommandStructure.java +++ b/src/main/java/seedu/duke/CommandStructure.java @@ -10,6 +10,8 @@ public class CommandStructure { public static final String COMMAND_CHECK = "check"; public static final String COMMAND_EXIT = "quit"; + public static final String PROPERTY_FLAG = "-property"; + public static final String CLIENT_FLAG = "-client"; public static final String[] ADD_PROPERTY_FLAGS = {"n/", "a/", "p/", "t/"}; public static final String[] ADD_CLIENT_FLAGS = {"n/", "c/", "e/", "b/"}; diff --git a/src/main/java/seedu/duke/parsermanager/ParserManager.java b/src/main/java/seedu/duke/parsermanager/ParserManager.java index eccc745bc..af0adf762 100644 --- a/src/main/java/seedu/duke/parsermanager/ParserManager.java +++ b/src/main/java/seedu/duke/parsermanager/ParserManager.java @@ -11,6 +11,7 @@ import java.util.ArrayList; +import static seedu.duke.CommandStructure.CLIENT_FLAG; import static seedu.duke.CommandStructure.COMMAND_ADD; import static seedu.duke.CommandStructure.COMMAND_CHECK; import static seedu.duke.CommandStructure.COMMAND_DELETE; @@ -18,6 +19,7 @@ import static seedu.duke.CommandStructure.COMMAND_LIST; import static seedu.duke.CommandStructure.COMMAND_PAIR; import static seedu.duke.CommandStructure.COMMAND_UNPAIR; +import static seedu.duke.CommandStructure.PROPERTY_FLAG; import static seedu.duke.Messages.MESSAGE_INCORRECT_LIST_DETAILS; import static seedu.duke.Messages.MESSAGE_MISSING_SUB_COMMAND_TYPE; @@ -33,8 +35,7 @@ public class ParserManager { private static final int SUB_COMMAND_INDEX = 0; private static final int COMMAND_FLAG_INDEX = 1; private static final int COMMAND_DESCRIPTION_INDEX = 1; - private static final String PROPERTY_FLAG = "-property"; - private static final String CLIENT_FLAG = "-client"; + public ParserManager(ClientList clientL, PropertyList propertyL, PairingList pairingL) { clientList = clientL; From 8b832a77bfa65b1b004725c62cf8f92192cd4740 Mon Sep 17 00:00:00 2001 From: ngdeqi Date: Tue, 18 Oct 2022 20:35:44 +0800 Subject: [PATCH 089/325] Add budget checker for Pairing feature --- src/main/java/seedu/duke/Messages.java | 4 ++++ src/main/java/seedu/duke/PairingList.java | 15 +++++++++++++++ .../duke/exception/BudgetExceededException.java | 15 +++++++++++++++ .../java/seedu/duke/parsermanager/ParsePair.java | 14 +++++++++++--- .../java/seedu/duke/parsermanager/Parser.java | 7 ++----- 5 files changed, 47 insertions(+), 8 deletions(-) create mode 100644 src/main/java/seedu/duke/exception/BudgetExceededException.java diff --git a/src/main/java/seedu/duke/Messages.java b/src/main/java/seedu/duke/Messages.java index 7782e46e1..046c24d21 100644 --- a/src/main/java/seedu/duke/Messages.java +++ b/src/main/java/seedu/duke/Messages.java @@ -113,10 +113,14 @@ public class Messages { public static final String MESSAGE_EXISTING_PAIR = "OOPS!! This client and this property are already paired " + "together. You don't need to pair them again."; + public static final String MESSAGE_BUDGET_EXCEEDED = "OOPS!! The rental price exceeds the client's budget. " + + "Pair unsuccessful."; + public static final String MESSAGE_NO_EXISTING_PAIR = "OOPS!! This property is not being rented by the tenant. " + "Unpair unsuccessful."; + /* Check property/client related Error Messages */ public static final String MESSAGE_CHECK_PROPERTY_RESULT = "Here are the tenants renting this property:"; diff --git a/src/main/java/seedu/duke/PairingList.java b/src/main/java/seedu/duke/PairingList.java index c7b580f40..fbff43bb2 100644 --- a/src/main/java/seedu/duke/PairingList.java +++ b/src/main/java/seedu/duke/PairingList.java @@ -120,6 +120,21 @@ public boolean isAlreadyPaired(Client client, Property property) { return false; } + /** + * Returns true if the rental price of the property exceeds the client's budget. + * + * @param client Client to be paired with the property. + * @param property Property to be paired with the client. + * @return True is rental price exceeds client's budget; false if rental price is equal to or lower than clien's + * budget. + */ + + public boolean hasPriceExceededBudget(Client client, Property property) { + int clientBudget = Integer.parseInt(client.getClientBudgetPerMonth()); + int rentalPrice = Integer.parseInt(property.getRentingPrice()); + return rentalPrice > clientBudget; + } + /** * Fetches a list of tenants that is renting the property. diff --git a/src/main/java/seedu/duke/exception/BudgetExceededException.java b/src/main/java/seedu/duke/exception/BudgetExceededException.java new file mode 100644 index 000000000..8a2388acd --- /dev/null +++ b/src/main/java/seedu/duke/exception/BudgetExceededException.java @@ -0,0 +1,15 @@ +package seedu.duke.exception; + +public class BudgetExceededException extends DukeCommandException { + + private final String message; + + public BudgetExceededException(String message) { + this.message = message; + } + + @Override + public String toString() { + return message; + } +} diff --git a/src/main/java/seedu/duke/parsermanager/ParsePair.java b/src/main/java/seedu/duke/parsermanager/ParsePair.java index 0ae81ca26..702f48d61 100644 --- a/src/main/java/seedu/duke/parsermanager/ParsePair.java +++ b/src/main/java/seedu/duke/parsermanager/ParsePair.java @@ -7,7 +7,9 @@ import seedu.duke.PropertyList; import seedu.duke.command.Command; import seedu.duke.command.CommandPair; +import seedu.duke.exception.BudgetExceededException; import seedu.duke.exception.ClientAlreadyPairedException; +import seedu.duke.exception.DukeException; import seedu.duke.exception.EmptyDescriptionException; import seedu.duke.exception.ExistingPairException; import seedu.duke.exception.IncorrectFlagOrderException; @@ -19,6 +21,7 @@ import static seedu.duke.CommandStructure.PAIR_FLAGS; import static seedu.duke.Messages.EXCEPTION; +import static seedu.duke.Messages.MESSAGE_BUDGET_EXCEEDED; import static seedu.duke.Messages.MESSAGE_CLIENT_ALREADY_PAIRED; import static seedu.duke.Messages.MESSAGE_EMPTY_DESCRIPTION; import static seedu.duke.Messages.MESSAGE_EXISTING_PAIR; @@ -41,8 +44,7 @@ public ParsePair(String pairCommandDescription, ClientList clientL, } @Override - public Command parseCommand() throws InvalidIndexException, ClientAlreadyPairedException, MissingFlagException, - IncorrectFlagOrderException, NotIntegerException, ExistingPairException, EmptyDescriptionException { + public Command parseCommand() throws DukeException { try { checkForEmptyDescription(commandDescription); @@ -63,6 +65,8 @@ public Command parseCommand() throws InvalidIndexException, ClientAlreadyPairedE throw new NotIntegerException(MESSAGE_NOT_INTEGER); } catch (ExistingPairException e) { throw new ExistingPairException(MESSAGE_EXISTING_PAIR); + } catch (BudgetExceededException e) { + throw new BudgetExceededException(MESSAGE_BUDGET_EXCEEDED); } } @@ -104,7 +108,7 @@ private ArrayList convertProcessedCommandDetailsToInteger(ArrayList pairDetails) throws InvalidIndexException, - ClientAlreadyPairedException, ExistingPairException { + ClientAlreadyPairedException, ExistingPairException, BudgetExceededException { int propertyIndex = pairDetails.get(0); int clientIndex = pairDetails.get(1); checkForClientListIndexOutOfBounds(clientIndex); @@ -120,6 +124,10 @@ private void validatePairDetails(ArrayList pairDetails) throws InvalidI if (pairingList.isClientPairedWithProperty(client)) { throw new ClientAlreadyPairedException(EXCEPTION); } + + if (pairingList.hasPriceExceededBudget(client, property)) { + throw new BudgetExceededException(EXCEPTION); + } } private int[] getFlagIndexPositions(String commandDetail, String[] flags) { diff --git a/src/main/java/seedu/duke/parsermanager/Parser.java b/src/main/java/seedu/duke/parsermanager/Parser.java index 8b46e858c..404728738 100644 --- a/src/main/java/seedu/duke/parsermanager/Parser.java +++ b/src/main/java/seedu/duke/parsermanager/Parser.java @@ -2,6 +2,7 @@ import seedu.duke.command.Command; import seedu.duke.exception.ClientAlreadyPairedException; +import seedu.duke.exception.DukeException; import seedu.duke.exception.EmptyDescriptionException; import seedu.duke.exception.EmptyDetailException; import seedu.duke.exception.ExistingPairException; @@ -18,9 +19,5 @@ import seedu.duke.exception.NotIntegerException; public abstract class Parser { - public abstract Command parseCommand() throws EmptyDescriptionException, InvalidSingaporeAddressException, - MissingFlagException, IncorrectFlagOrderException, InvalidPriceFormatException, EmptyDetailException, - InvalidContactNumberException, InvalidEmailException, InvalidBudgetFormatException, InvalidIndexException, - NotIntegerException, ClientAlreadyPairedException, ExistingPairException, NoExistingPairException, - ExtraParametersException; + public abstract Command parseCommand() throws DukeException; } From b9b4a63b4892c50036130750fb34ae5d6bc95d7d Mon Sep 17 00:00:00 2001 From: ngdeqi Date: Tue, 18 Oct 2022 20:49:01 +0800 Subject: [PATCH 090/325] Add budget checker tests for pairingList --- src/test/java/seedu/duke/PairingListTest.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/test/java/seedu/duke/PairingListTest.java b/src/test/java/seedu/duke/PairingListTest.java index 93fb8cbaf..669cfff90 100644 --- a/src/test/java/seedu/duke/PairingListTest.java +++ b/src/test/java/seedu/duke/PairingListTest.java @@ -18,6 +18,14 @@ class PairingListTest { public static final Client ABSENT_CLIENT = new Client("Doja Cat", "93437878", "doja88@example.com", "100000"); + + public static final Client BUDGET_CHECKER_CLIENT_RICH = new Client("Jojo Rabbit", + "97632911", "jojorabbit@example.com", "1000"); + + public static final Client BUDGET_CHECKER_CLIENT_POOR = new Client("Olivia Rodrigo", + "90234911", "oliviaaaR@example.com", "350"); + + public static final Property PRESENT_PROPERTY = new Property("Mary Tan Bee Bee", "107 North Bridge Rd, Singapore 179105", "1000", "HDB 3 Room"); @@ -100,6 +108,13 @@ void isAlreadyPaired_presentAndAbsentPropertyAndClients_success() { } } + @Test void hasPriceExceededBudget_differentBudgetClients_success() { + PairingList pairingList = pairingListInit(); + assertTrue(pairingList.hasPriceExceededBudget(BUDGET_CHECKER_CLIENT_POOR, PRESENT_PROPERTY)); + assertFalse(pairingList.hasPriceExceededBudget(PRESENT_CLIENT, PRESENT_PROPERTY)); + assertFalse(pairingList.hasPriceExceededBudget(BUDGET_CHECKER_CLIENT_RICH, PRESENT_PROPERTY)); + } + @Test void getPropertyTenants_propertyRentedByOnlyPresentClient_success() { PairingList pairingList = pairingListInit(); From dba50f85fb14dc2282d52e5f058d1fa4d80d88a6 Mon Sep 17 00:00:00 2001 From: "ZORAN\\syedo" Date: Tue, 18 Oct 2022 22:32:02 +0800 Subject: [PATCH 091/325] Add List with Tags feature. Add bye message. --- src/main/java/seedu/duke/Client.java | 7 ++ .../java/seedu/duke/CommandStructure.java | 8 ++- src/main/java/seedu/duke/Messages.java | 20 +++++- src/main/java/seedu/duke/Ui.java | 49 +++++++++++++ .../java/seedu/duke/command/CommandBye.java | 3 +- .../duke/command/CommandListClients.java | 2 + .../command/CommandListClientsWithTags.java | 70 ++++++++++++++++++ .../duke/command/CommandListEverything.java | 25 +++++++ .../duke/command/CommandListProperties.java | 4 +- .../CommandListPropertiesWithTags.java | 71 +++++++++++++++++++ .../IncorrectListFlagsException.java | 17 +++++ .../duke/parsermanager/ParseListClient.java | 41 ++++++----- .../parsermanager/ParseListEverything.java | 12 ++++ .../duke/parsermanager/ParseListProperty.java | 40 +++++++---- .../java/seedu/duke/parsermanager/Parser.java | 3 +- .../duke/parsermanager/ParserManager.java | 25 +++++-- 16 files changed, 354 insertions(+), 43 deletions(-) create mode 100644 src/main/java/seedu/duke/command/CommandListClientsWithTags.java create mode 100644 src/main/java/seedu/duke/command/CommandListEverything.java create mode 100644 src/main/java/seedu/duke/command/CommandListPropertiesWithTags.java create mode 100644 src/main/java/seedu/duke/exception/IncorrectListFlagsException.java create mode 100644 src/main/java/seedu/duke/parsermanager/ParseListEverything.java diff --git a/src/main/java/seedu/duke/Client.java b/src/main/java/seedu/duke/Client.java index a7824b95d..757a741f6 100644 --- a/src/main/java/seedu/duke/Client.java +++ b/src/main/java/seedu/duke/Client.java @@ -42,6 +42,13 @@ public String getClientEmail() { return clientEmail; } + public String getClientEmailForList() { + if (clientEmail.isEmpty()) { + return "This client has not provided an e-mail"; + } + return clientEmail; + } + public String getClientBudgetPerMonth() { return clientBudgetPerMonth; } diff --git a/src/main/java/seedu/duke/CommandStructure.java b/src/main/java/seedu/duke/CommandStructure.java index fc5997dd3..617146969 100644 --- a/src/main/java/seedu/duke/CommandStructure.java +++ b/src/main/java/seedu/duke/CommandStructure.java @@ -9,7 +9,13 @@ public class CommandStructure { public static final String COMMAND_UNPAIR = "unpair"; public static final String COMMAND_CHECK = "check"; public static final String COMMAND_EXIT = "quit"; - + public static final String NAME_FLAG = "n/"; + public static final String CONTACT_NUMBER_FLAG = "c/"; + public static final String ADDRESS_FLAG = "a/"; + public static final String TYPE_FLAG = "t/"; + public static final String PRICE_FLAG = "p/"; + public static final String EMAIL_FLAG = "e/"; + public static final String BUDGET_FLAG = "b/"; public static final String[] ADD_PROPERTY_FLAGS = {"n/", "a/", "p/", "t/"}; public static final String[] ADD_CLIENT_FLAGS = {"n/", "c/", "e/", "b/"}; diff --git a/src/main/java/seedu/duke/Messages.java b/src/main/java/seedu/duke/Messages.java index 7782e46e1..5173e9a04 100644 --- a/src/main/java/seedu/duke/Messages.java +++ b/src/main/java/seedu/duke/Messages.java @@ -132,12 +132,28 @@ public class Messages { /* List related Error Messages */ - public static final String MESSAGE_INCORRECT_LIST_DETAILS = "OOPS!!! Please enter either -client or -property to" - + " list clients and properties respectively"; + public static final String MESSAGE_INCORRECT_LIST_DETAILS = "OOPS!!! Please enter -client" + + " to list clients, -property to list properties, and -everything to list" + + " everything"; public static final String LINE_BREAK = "----------------------------------------------------------------------" + "----------"; public static final String MESSAGE_BYE_PARAMETERS_PRESENT = "Please type bye without any parameters" + " if you would like to quit"; + + public static final String MESSAGE_INCORRECT_PROPERTY_LIST_FLAG = "Please type the following " + + "after list -property to display - " + + "\na/ for property address" + + "\nt/ for property type" + + "\nn/ for property owner name" + + "\nt/ for property type"; + + public static final String MESSAGE_INCORRECT_CLIENT_LIST_FLAG = "Please type the following " + + "after list -client to display - " + + "\nn/ for client name" + + "\nc/ for client contact number" + + "\ne/ for client email" + + "\nb/ for client budget"; + public static final String MESSAGE_BYE = "Goodbye :). See you soon!"; } diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index 808eedd5a..e1d4d4ba0 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -102,12 +102,61 @@ public void displayOneClient(Client client, int i) { System.out.println(LINE_BREAK); } + public void displayOneClientName(Client client, int i) { + System.out.println(i + "."); + System.out.println(client.getClientName()); + System.out.println(LINE_BREAK); + } + + public void displayOneClientContact(Client client, int i) { + System.out.println(i + "."); + System.out.println(client.getClientContactNumber()); + System.out.println(LINE_BREAK); + } + + public void displayOneClientEmail(Client client, int i) { + System.out.println(i + "."); + System.out.println(client.getClientEmailForList()); + System.out.println(LINE_BREAK); + } + + public void displayOneClientBudget(Client client, int i) { + System.out.println(i + "."); + System.out.println(client.getClientBudgetPerMonth()); + System.out.println(LINE_BREAK); + } + public void displayOneProperty(Property property, int i) { System.out.println(i + "."); System.out.println(property.toString()); System.out.println(LINE_BREAK); } + public void displayOnePropertyAddress(Property property, int i) { + System.out.println(i + "."); + System.out.println(property.getPropertyAddress()); + System.out.println(LINE_BREAK); + } + + public void displayOnePropertyLandlordName(Property property, int i) { + System.out.println(i + "."); + System.out.println(property.getLandlordName()); + System.out.println(LINE_BREAK); + } + + public void displayOnePropertyRentingPrice(Property property, int i) { + System.out.println(i + "."); + System.out.println(property.getRentingPrice()); + System.out.println(LINE_BREAK); + } + + public void displayOnePropertyUnitType(Property property, int i) { + System.out.println(i + "."); + System.out.println(property.getUnitType()); + System.out.println(LINE_BREAK); + } + + public void showCheckProperty(ArrayList tenants) { showToUser(MESSAGE_CHECK_PROPERTY_RESULT); int count = 0; diff --git a/src/main/java/seedu/duke/command/CommandBye.java b/src/main/java/seedu/duke/command/CommandBye.java index 5ea43c4f9..c3bfa1152 100644 --- a/src/main/java/seedu/duke/command/CommandBye.java +++ b/src/main/java/seedu/duke/command/CommandBye.java @@ -6,12 +6,13 @@ import seedu.duke.PropertyList; import seedu.duke.Storage; import seedu.duke.Ui; +import static seedu.duke.Messages.MESSAGE_BYE; public class CommandBye extends Command { @Override public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, PairingList pairingList) { - //print bye message + System.out.println(MESSAGE_BYE); } } diff --git a/src/main/java/seedu/duke/command/CommandListClients.java b/src/main/java/seedu/duke/command/CommandListClients.java index 086afaf4b..2cf802569 100644 --- a/src/main/java/seedu/duke/command/CommandListClients.java +++ b/src/main/java/seedu/duke/command/CommandListClients.java @@ -12,6 +12,8 @@ public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientLis for (int i = 0; i < clientList.getCurrentListSize(); i++) { ui.displayOneClient(clientList.getClientList().get(i), i + 1); } + System.out.println("There are " + clientList.getCurrentListSize() + + " clients in this list"); } } diff --git a/src/main/java/seedu/duke/command/CommandListClientsWithTags.java b/src/main/java/seedu/duke/command/CommandListClientsWithTags.java new file mode 100644 index 000000000..586c908ea --- /dev/null +++ b/src/main/java/seedu/duke/command/CommandListClientsWithTags.java @@ -0,0 +1,70 @@ +package seedu.duke.command; + +import seedu.duke.ClientList; +import seedu.duke.PairingList; +import seedu.duke.PropertyList; +import seedu.duke.Storage; +import seedu.duke.Ui; +import seedu.duke.CommandStructure; + +public class CommandListClientsWithTags extends Command { + private final String commandFlag; + + public CommandListClientsWithTags(String commandFlag) { + this.commandFlag = commandFlag; + } + + @Override + public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, + PairingList pairingList) { + switch (commandFlag) { + case CommandStructure.CONTACT_NUMBER_FLAG: + displayClientContacts(clientList, ui); + break; + case CommandStructure.NAME_FLAG: + displayClientNames(clientList, ui); + break; + case CommandStructure.EMAIL_FLAG: + displayClientEmails(clientList, ui); + break; + case CommandStructure.BUDGET_FLAG: + displayClientBudget(clientList, ui); + break; + default: + break; + } + } + + private void displayClientContacts(ClientList clientList, Ui ui) { + for (int i = 0; i < clientList.getCurrentListSize(); i++) { + ui.displayOneClientContact(clientList.getClientList().get(i), i + 1); + } + System.out.println("There are " + clientList.getCurrentListSize() + + " clients in this list"); + } + + private void displayClientNames(ClientList clientList, Ui ui) { + for (int i = 0; i < clientList.getCurrentListSize(); i++) { + ui.displayOneClientName(clientList.getClientList().get(i), i + 1); + } + System.out.println("There are " + clientList.getCurrentListSize() + + " clients in this list"); + } + + private void displayClientEmails(ClientList clientList, Ui ui) { + for (int i = 0; i < clientList.getCurrentListSize(); i++) { + ui.displayOneClientEmail(clientList.getClientList().get(i), i + 1); + } + System.out.println("There are " + clientList.getCurrentListSize() + + " clients in this list"); + } + + private void displayClientBudget(ClientList clientList, Ui ui) { + for (int i = 0; i < clientList.getCurrentListSize(); i++) { + ui.displayOneClientBudget(clientList.getClientList().get(i), i + 1); + } + System.out.println("There are " + clientList.getCurrentListSize() + + " clients in this list"); + } +} + diff --git a/src/main/java/seedu/duke/command/CommandListEverything.java b/src/main/java/seedu/duke/command/CommandListEverything.java new file mode 100644 index 000000000..38ee37f14 --- /dev/null +++ b/src/main/java/seedu/duke/command/CommandListEverything.java @@ -0,0 +1,25 @@ +package seedu.duke.command; + +import seedu.duke.ClientList; +import seedu.duke.PairingList; +import seedu.duke.PropertyList; +import seedu.duke.Storage; +import seedu.duke.Ui; +import seedu.duke.Messages; + +public class CommandListEverything extends Command { + public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, + PairingList pairingList) { + for (int i = 0; i < propertyList.getCurrentListSize(); i++) { + ui.displayOneProperty(propertyList.getPropertyList().get(i), i + 1); + } + System.out.println("There are " + propertyList.getCurrentListSize() + + " properties in this list"); + System.out.println(Messages.LINE_BREAK); + for (int i = 0; i < clientList.getCurrentListSize(); i++) { + ui.displayOneClient(clientList.getClientList().get(i), i + 1); + } + System.out.println("There are " + clientList.getCurrentListSize() + + " clients in this list"); + } +} diff --git a/src/main/java/seedu/duke/command/CommandListProperties.java b/src/main/java/seedu/duke/command/CommandListProperties.java index 557adaf9a..73aab2118 100644 --- a/src/main/java/seedu/duke/command/CommandListProperties.java +++ b/src/main/java/seedu/duke/command/CommandListProperties.java @@ -12,5 +12,7 @@ public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientLis for (int i = 0; i < propertyList.getCurrentListSize(); i++) { ui.displayOneProperty(propertyList.getPropertyList().get(i), i + 1); } + System.out.println("There are " + propertyList.getCurrentListSize() + + " properties in this list"); } -} \ No newline at end of file +} diff --git a/src/main/java/seedu/duke/command/CommandListPropertiesWithTags.java b/src/main/java/seedu/duke/command/CommandListPropertiesWithTags.java new file mode 100644 index 000000000..c296a6caf --- /dev/null +++ b/src/main/java/seedu/duke/command/CommandListPropertiesWithTags.java @@ -0,0 +1,71 @@ +package seedu.duke.command; + +import seedu.duke.ClientList; +import seedu.duke.PairingList; +import seedu.duke.PropertyList; +import seedu.duke.Storage; +import seedu.duke.Ui; + +import seedu.duke.CommandStructure; + +public class CommandListPropertiesWithTags extends Command { + private final String commandFlag; + + public CommandListPropertiesWithTags(String commandFlag) { + this.commandFlag = commandFlag; + } + + @Override + public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, + PairingList pairingList) { + switch (commandFlag) { + case CommandStructure.ADDRESS_FLAG: + displayPropertyAddresses(propertyList, ui); + break; + case CommandStructure.NAME_FLAG: + displayPropertyLandlordNames(propertyList, ui); + break; + case CommandStructure.PRICE_FLAG: + displayPropertyPrices(propertyList, ui); + break; + case CommandStructure.TYPE_FLAG: + displayPropertyTypes(propertyList, ui); + break; + default: + break; + } + } + + private void displayPropertyAddresses(PropertyList propertyList, Ui ui) { + for (int i = 0; i < propertyList.getCurrentListSize(); i++) { + ui.displayOnePropertyAddress(propertyList.getPropertyList().get(i), i + 1); + } + System.out.println("There are " + propertyList.getCurrentListSize() + + " properties in this list"); + } + + private void displayPropertyLandlordNames(PropertyList propertyList, Ui ui) { + for (int i = 0; i < propertyList.getCurrentListSize(); i++) { + ui.displayOnePropertyLandlordName(propertyList.getPropertyList().get(i), i + 1); + } + System.out.println("There are " + propertyList.getCurrentListSize() + + " properties in this list"); + } + + private void displayPropertyPrices(PropertyList propertyList, Ui ui) { + for (int i = 0; i < propertyList.getCurrentListSize(); i++) { + ui.displayOnePropertyRentingPrice(propertyList.getPropertyList().get(i), i + 1); + } + System.out.println("There are " + propertyList.getCurrentListSize() + + " properties in this list"); + } + + private void displayPropertyTypes(PropertyList propertyList, Ui ui) { + for (int i = 0; i < propertyList.getCurrentListSize(); i++) { + ui.displayOnePropertyUnitType(propertyList.getPropertyList().get(i), i + 1); + } + System.out.println("There are " + propertyList.getCurrentListSize() + + " properties in this list"); + } +} + diff --git a/src/main/java/seedu/duke/exception/IncorrectListFlagsException.java b/src/main/java/seedu/duke/exception/IncorrectListFlagsException.java new file mode 100644 index 000000000..1f5d6990c --- /dev/null +++ b/src/main/java/seedu/duke/exception/IncorrectListFlagsException.java @@ -0,0 +1,17 @@ +package seedu.duke.exception; + +public class IncorrectListFlagsException extends DukeCommandException { + private final String message; + + public IncorrectListFlagsException(String message) { + this.message = message; + } + + @Override + public String toString() { + return message; + } + + + +} diff --git a/src/main/java/seedu/duke/parsermanager/ParseListClient.java b/src/main/java/seedu/duke/parsermanager/ParseListClient.java index c0894df0c..a10011c85 100644 --- a/src/main/java/seedu/duke/parsermanager/ParseListClient.java +++ b/src/main/java/seedu/duke/parsermanager/ParseListClient.java @@ -2,33 +2,40 @@ import seedu.duke.command.Command; import seedu.duke.command.CommandListClients; -import seedu.duke.exception.EmptyDescriptionException; +import seedu.duke.command.CommandListClientsWithTags; +import seedu.duke.exception.IncorrectListFlagsException; +import seedu.duke.CommandStructure; -import static seedu.duke.Messages.MESSAGE_EMPTY_DESCRIPTION; +import static seedu.duke.Messages.MESSAGE_INCORRECT_CLIENT_LIST_FLAG; public class ParseListClient extends Parser { - private final String commandDetail; + + private final String commandFlags; public ParseListClient(String listClientCommandDescription) { - this.commandDetail = listClientCommandDescription; + this.commandFlags = listClientCommandDescription; } @Override - public Command parseCommand() throws EmptyDescriptionException { - checkForEmptyDescription(commandDetail); - return new CommandListClients(); - } - - private void checkForEmptyDescription(String commandDetail) throws EmptyDescriptionException { - boolean isEmptyDescription = isEmptyString(commandDetail); - if (isEmptyDescription) { - throw new EmptyDescriptionException(MESSAGE_EMPTY_DESCRIPTION); + public Command parseCommand() throws IncorrectListFlagsException { + if (commandFlags.isEmpty()) { + return new CommandListClients(); + } else if (isValidTag(commandFlags)) { + return new CommandListClientsWithTags(commandFlags); + } else { + throw new IncorrectListFlagsException(MESSAGE_INCORRECT_CLIENT_LIST_FLAG); } } - private boolean isEmptyString(String commandDetail) { - return commandDetail.trim().isEmpty(); + boolean isValidTag(String commandFlags) { + switch (commandFlags) { + case CommandStructure.NAME_FLAG://deliberate fall through till BUDGET_FLAG + case CommandStructure.CONTACT_NUMBER_FLAG: + case CommandStructure.EMAIL_FLAG: + case CommandStructure.BUDGET_FLAG: + return true;//break not needed as we are returning + default: + return false; + } } - - } diff --git a/src/main/java/seedu/duke/parsermanager/ParseListEverything.java b/src/main/java/seedu/duke/parsermanager/ParseListEverything.java new file mode 100644 index 000000000..a10360afa --- /dev/null +++ b/src/main/java/seedu/duke/parsermanager/ParseListEverything.java @@ -0,0 +1,12 @@ +package seedu.duke.parsermanager; + +import seedu.duke.command.Command; +import seedu.duke.command.CommandListEverything; + +public class ParseListEverything extends Parser { + @Override + public Command parseCommand() { + return new CommandListEverything(); + } +} + diff --git a/src/main/java/seedu/duke/parsermanager/ParseListProperty.java b/src/main/java/seedu/duke/parsermanager/ParseListProperty.java index ec11f9b09..9aeedef10 100644 --- a/src/main/java/seedu/duke/parsermanager/ParseListProperty.java +++ b/src/main/java/seedu/duke/parsermanager/ParseListProperty.java @@ -2,32 +2,42 @@ import seedu.duke.command.Command; import seedu.duke.command.CommandListProperties; -import seedu.duke.exception.EmptyDescriptionException; +import seedu.duke.command.CommandListPropertiesWithTags; +import seedu.duke.CommandStructure; -import static seedu.duke.Messages.MESSAGE_EMPTY_DESCRIPTION; +import seedu.duke.exception.IncorrectListFlagsException; + +import static seedu.duke.Messages.MESSAGE_INCORRECT_PROPERTY_LIST_FLAG; public class ParseListProperty extends Parser { - private final String commandDetail; + private final String commandFlags; public ParseListProperty(String listPropertyCommandDescription) { - this.commandDetail = listPropertyCommandDescription; + this.commandFlags = listPropertyCommandDescription; } @Override - public Command parseCommand() throws EmptyDescriptionException { - checkForEmptyDescription(commandDetail); - return new CommandListProperties(); - } - - private void checkForEmptyDescription(String commandDetail) throws EmptyDescriptionException { - boolean isEmptyDescription = isEmptyString(commandDetail); - if (isEmptyDescription) { - throw new EmptyDescriptionException(MESSAGE_EMPTY_DESCRIPTION); + public Command parseCommand() throws IncorrectListFlagsException { + if (commandFlags.isEmpty()) { + return new CommandListProperties(); + } else if (isValidTag(commandFlags)) { + return new CommandListPropertiesWithTags(commandFlags); + } else { + throw new IncorrectListFlagsException(MESSAGE_INCORRECT_PROPERTY_LIST_FLAG); } } - private boolean isEmptyString(String commandDetail) { - return commandDetail.trim().isEmpty(); + boolean isValidTag(String commandFlags) { + switch (commandFlags) { + case CommandStructure.NAME_FLAG: //deliberate fall through till /t + case CommandStructure.ADDRESS_FLAG: + case CommandStructure.PRICE_FLAG: + case CommandStructure.TYPE_FLAG: + return true;//break not needed as we are returning + default: + return false; + } } } + diff --git a/src/main/java/seedu/duke/parsermanager/Parser.java b/src/main/java/seedu/duke/parsermanager/Parser.java index 8b46e858c..28314c255 100644 --- a/src/main/java/seedu/duke/parsermanager/Parser.java +++ b/src/main/java/seedu/duke/parsermanager/Parser.java @@ -7,6 +7,7 @@ import seedu.duke.exception.ExistingPairException; import seedu.duke.exception.ExtraParametersException; import seedu.duke.exception.IncorrectFlagOrderException; +import seedu.duke.exception.IncorrectListFlagsException; import seedu.duke.exception.InvalidBudgetFormatException; import seedu.duke.exception.InvalidContactNumberException; import seedu.duke.exception.InvalidEmailException; @@ -22,5 +23,5 @@ public abstract Command parseCommand() throws EmptyDescriptionException, Invalid MissingFlagException, IncorrectFlagOrderException, InvalidPriceFormatException, EmptyDetailException, InvalidContactNumberException, InvalidEmailException, InvalidBudgetFormatException, InvalidIndexException, NotIntegerException, ClientAlreadyPairedException, ExistingPairException, NoExistingPairException, - ExtraParametersException; + ExtraParametersException, IncorrectListFlagsException; } diff --git a/src/main/java/seedu/duke/parsermanager/ParserManager.java b/src/main/java/seedu/duke/parsermanager/ParserManager.java index eccc745bc..db7cdad06 100644 --- a/src/main/java/seedu/duke/parsermanager/ParserManager.java +++ b/src/main/java/seedu/duke/parsermanager/ParserManager.java @@ -35,6 +35,7 @@ public class ParserManager { private static final int COMMAND_DESCRIPTION_INDEX = 1; private static final String PROPERTY_FLAG = "-property"; private static final String CLIENT_FLAG = "-client"; + private static final String EVERYTHING_FLAG = "-everything"; public ParserManager(ClientList clientL, PropertyList propertyL, PairingList pairingL) { clientList = clientL; @@ -96,13 +97,16 @@ public Parser parseCommand(String input) throws DukeParseException, ExistingPair throw new UndefinedSubCommandTypeException(MESSAGE_MISSING_SUB_COMMAND_TYPE); } case COMMAND_LIST: - boolean isListProperty = commandDetail.trim().equals(PROPERTY_FLAG); - boolean isListClient = commandDetail.trim().equals(CLIENT_FLAG); - + ArrayList listCommandTypeAndFlags = getListCommandType(commandDetail); + boolean isListProperty = listCommandTypeAndFlags.get(0).trim().equals(PROPERTY_FLAG); + boolean isListClient = listCommandTypeAndFlags.get(0).equals(CLIENT_FLAG); + boolean isListEverything = listCommandTypeAndFlags.get(0).equals(EVERYTHING_FLAG); if (isListProperty) { - return new ParseListProperty(commandDetail); + return new ParseListProperty(listCommandTypeAndFlags.get(1)); } else if (isListClient) { - return new ParseListClient(commandDetail); + return new ParseListClient(listCommandTypeAndFlags.get(1)); + } else if (isListEverything && listCommandTypeAndFlags.get(1).isEmpty()) { + return new ParseListEverything(); } else { throw new UndefinedSubCommandTypeException(MESSAGE_INCORRECT_LIST_DETAILS); } @@ -126,4 +130,15 @@ private ArrayList splitCommandAndCommandType(String fullCommandDetail) { return processedCommandDetails; } + private ArrayList getListCommandType(String commandDetail) { + ArrayList listCommandTypeAndFlags = new ArrayList<>(); + String[] listTypeAndFlagsArray = commandDetail.split(EMPTY_SPACE, MAX_LENGTH); + listCommandTypeAndFlags.add(listTypeAndFlagsArray[0].trim()); + if (listTypeAndFlagsArray.length == 1) { + listCommandTypeAndFlags.add(""); + } else { + listCommandTypeAndFlags.add(listTypeAndFlagsArray[1].trim()); + } + return listCommandTypeAndFlags; + } } From 4bc635520b05d2977df1f856bb9059891d9a8304 Mon Sep 17 00:00:00 2001 From: "LAPTOP-S1RS66RO\\marcu" Date: Tue, 18 Oct 2022 20:55:01 +0800 Subject: [PATCH 092/325] Fix missing optional email feature for ParseAddClient and some typos --- .../duke/parsermanager/ParseAddClient.java | 108 +++++++++--------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/src/main/java/seedu/duke/parsermanager/ParseAddClient.java b/src/main/java/seedu/duke/parsermanager/ParseAddClient.java index 248ffa28d..bfdd271df 100644 --- a/src/main/java/seedu/duke/parsermanager/ParseAddClient.java +++ b/src/main/java/seedu/duke/parsermanager/ParseAddClient.java @@ -16,9 +16,9 @@ import static seedu.duke.CommandStructure.ADD_CLIENT_FLAGS; import static seedu.duke.Messages.EXCEPTION; import static seedu.duke.Messages.MESSAGE_ADD_CLIENT_WRONG_FORMAT; -import static seedu.duke.Messages.MESSAGE_INVALID_BUDGET_FORMAT; import static seedu.duke.Messages.MESSAGE_INVALID_CONTACT_NUMBER; import static seedu.duke.Messages.MESSAGE_INVALID_EMAIL; +import static seedu.duke.Messages.MESSAGE_INVALID_BUDGET_FORMAT; public class ParseAddClient extends Parser { private final String commandDescription; @@ -27,24 +27,21 @@ public ParseAddClient(String addCommandDescription) { this.commandDescription = addCommandDescription; } - public Command parseCommand() throws MissingFlagException, IncorrectFlagOrderException, EmptyDetailException, InvalidContactNumberException, InvalidEmailException, InvalidBudgetFormatException { try { checkForEmptyDetails(commandDescription); - ArrayList clientDetails = processCommandAddClientDetails(commandDescription); validateClientDetails(clientDetails); return new CommandAddClient(clientDetails); - + } catch (EmptyDetailException e) { + throw new EmptyDetailException(MESSAGE_ADD_CLIENT_WRONG_FORMAT); } catch (MissingFlagException e) { throw new MissingFlagException(MESSAGE_ADD_CLIENT_WRONG_FORMAT); } catch (IncorrectFlagOrderException e) { throw new IncorrectFlagOrderException(MESSAGE_ADD_CLIENT_WRONG_FORMAT); } catch (InvalidContactNumberException e) { throw new InvalidContactNumberException(MESSAGE_INVALID_CONTACT_NUMBER); - } catch (EmptyDetailException e) { - throw new EmptyDetailException(MESSAGE_ADD_CLIENT_WRONG_FORMAT); } catch (InvalidEmailException e) { throw new InvalidEmailException(MESSAGE_INVALID_EMAIL); } catch (InvalidBudgetFormatException e) { @@ -65,29 +62,12 @@ private boolean isEmptyString(String commandDetail) { private ArrayList processCommandAddClientDetails(String rawCommandDetail) throws MissingFlagException, IncorrectFlagOrderException { - int[] flagIndexPositions = getFlagIndexPositions(rawCommandDetail); - checkForMissingFlags(flagIndexPositions); + checkForMissingClientFlags(flagIndexPositions); checkFlagsOrder(flagIndexPositions); return extractClientDetails(rawCommandDetail, flagIndexPositions); } - private void validateClientDetails(ArrayList clientDetails) throws EmptyDetailException, - InvalidContactNumberException, InvalidEmailException, InvalidBudgetFormatException { - //Checks for Missing Client Name, Contact Number, Budget Per Month (SGD) - checkForEmptyDetails(clientDetails.get(0)); - checkForEmptyDetails(clientDetails.get(1)); - checkForEmptyDetails(clientDetails.get(3)); - - //Checks for Contact Number, Email and Budget Format - checkForValidSingaporeContactNumber(clientDetails.get(1)); - boolean hasEmail = !clientDetails.get(2).isEmpty(); - if (hasEmail) { - checkForValidEmail(clientDetails.get(2)); - } - checkForBudgetNumberFormat(clientDetails.get(3)); - } - private int[] getFlagIndexPositions(String commandDetail) { String[] flags = ADD_CLIENT_FLAGS; int[] flagIndexPositions = new int[flags.length]; @@ -98,17 +78,35 @@ private int[] getFlagIndexPositions(String commandDetail) { return flagIndexPositions; } - private void checkForMissingFlags(int[] flagIndexPositions) throws MissingFlagException { - for (int flagIndex : flagIndexPositions) { - if (!isFlagPresent(flagIndex)) { - throw new MissingFlagException(EXCEPTION); + private void checkForMissingClientFlags(int[] flagIndexPositions) throws MissingFlagException { + for (int flagIndex = 0; flagIndex < flagIndexPositions.length; flagIndex++) { + boolean isEmailIndex = (flagIndex == 2); + //Skip empty check for email as email is optional + if (!isEmailIndex && !isFlagPresent(flagIndex)) { + throw new MissingFlagException(EXCEPTION); } } } + private boolean isFlagPresent(int flagIndexPosition) { + return (flagIndexPosition != -1); + } + private void checkFlagsOrder(int[] flagIndexPositions) throws IncorrectFlagOrderException { - for (int i = 0; i < flagIndexPositions.length - 1; i++) { - checkForCorrectFlagOrder(flagIndexPositions[i], flagIndexPositions[i + 1]); + checkForCorrectFlagOrder(flagIndexPositions[0], flagIndexPositions[1]); + boolean hasEmail = (flagIndexPositions[2] != -1); + if (hasEmail) { + checkForCorrectFlagOrder(flagIndexPositions[1], flagIndexPositions[2]); + checkForCorrectFlagOrder(flagIndexPositions[2], flagIndexPositions[3]); + } else { + checkForCorrectFlagOrder(flagIndexPositions[1], flagIndexPositions[3]); + } + } + + private void checkForCorrectFlagOrder(int flagPosition, int nextFlagPosition) throws IncorrectFlagOrderException { + boolean hasCorrectOrder = (flagPosition < nextFlagPosition); + if (!hasCorrectOrder) { + throw new IncorrectFlagOrderException(EXCEPTION); } } @@ -137,6 +135,30 @@ private ArrayList extractClientDetails(String rawClientDetail, int[] add return processedClientDetails; } + private static String extractDetail(String rawDetail, int beginIndex) { + return rawDetail.substring(beginIndex).trim(); + } + + private static String extractDetail(String rawDetail, int beginIndex, int endIndex) { + return rawDetail.substring(beginIndex, endIndex).trim(); + } + + private void validateClientDetails(ArrayList clientDetails) throws EmptyDetailException, + InvalidContactNumberException, InvalidEmailException, InvalidBudgetFormatException { + //Checks for Missing Client Name, Contact Number, Budget Per Month (SGD) + checkForEmptyDetails(clientDetails.get(0)); + checkForEmptyDetails(clientDetails.get(1)); + checkForEmptyDetails(clientDetails.get(3)); + + //Checks for Contact Number, Email and Budget Format + checkForValidSingaporeContactNumber(clientDetails.get(1)); + boolean hasEmail = !clientDetails.get(2).isEmpty(); + if (hasEmail) { + checkForValidEmail(clientDetails.get(2)); + } + checkForBudgetNumberFormat(clientDetails.get(3)); + } + private void checkForValidSingaporeContactNumber(String clientContactNumber) throws InvalidContactNumberException { boolean hasValidContactNumber = checkForDetailFormat("^[689]\\d{7}$", clientContactNumber); if (!hasValidContactNumber) { @@ -151,8 +173,8 @@ private void checkForValidEmail(String clientEmail) throws InvalidEmailException + "9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-" + "9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0" + "c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])"; - boolean hasValidContactNumber = checkForDetailFormat(regex, clientEmail); - if (!hasValidContactNumber) { + boolean hasValidEmail = checkForDetailFormat(regex, clientEmail); + if (!hasValidEmail) { throw new InvalidEmailException(EXCEPTION); } } @@ -166,31 +188,9 @@ private void checkForBudgetNumberFormat(String budget) throws InvalidBudgetForma } } - private boolean isFlagPresent(int flagIndexPosition) { - return (flagIndexPosition != -1); - } - - private void checkForCorrectFlagOrder(int flagPosition, int nextFlagPosition) throws IncorrectFlagOrderException { - boolean hasCorrectOrder = (flagPosition < nextFlagPosition); - if (!hasCorrectOrder) { - throw new IncorrectFlagOrderException(EXCEPTION); - } - } - - private static String extractDetail(String rawDetail, int beginIndex) { - return rawDetail.substring(beginIndex).trim(); - } - - private static String extractDetail(String rawDetail, int beginIndex, int endIndex) { - return rawDetail.substring(beginIndex, endIndex).trim(); - } - private boolean checkForDetailFormat(String regex, String detail) { Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(detail); return matcher.matches(); } - - - } From 3ca5643fafacd358d08075b7c7798dfdf2506a55 Mon Sep 17 00:00:00 2001 From: "LAPTOP-S1RS66RO\\marcu" Date: Tue, 18 Oct 2022 21:17:06 +0800 Subject: [PATCH 093/325] Fix magic number coding standard violation for ParseAddClient --- .../duke/parsermanager/ParseAddClient.java | 67 ++++++++++++------- 1 file changed, 41 insertions(+), 26 deletions(-) diff --git a/src/main/java/seedu/duke/parsermanager/ParseAddClient.java b/src/main/java/seedu/duke/parsermanager/ParseAddClient.java index bfdd271df..03c777838 100644 --- a/src/main/java/seedu/duke/parsermanager/ParseAddClient.java +++ b/src/main/java/seedu/duke/parsermanager/ParseAddClient.java @@ -23,6 +23,15 @@ public class ParseAddClient extends Parser { private final String commandDescription; + private static final int CLIENT_NAME_INDEX = 0; + private static final int CLIENT_CONTACT_NUMBER_INDEX = 1; + private static final int CLIENT_EMAIL_INDEX = 2; + private static final int CLIENT_BUDGET_INDEX = 3; + + private static final int MISSING_FLAG_VALUE = -1; + private static final int FLAG_JUMPER_VALUE = 2; + + public ParseAddClient(String addCommandDescription) { this.commandDescription = addCommandDescription; } @@ -72,15 +81,15 @@ private int[] getFlagIndexPositions(String commandDetail) { String[] flags = ADD_CLIENT_FLAGS; int[] flagIndexPositions = new int[flags.length]; - for (int i = 0; i < flags.length; i++) { - flagIndexPositions[i] = commandDetail.indexOf(flags[i]); + for (int flagIndex = 0; flagIndex < flags.length; flagIndex++) { + flagIndexPositions[flagIndex] = commandDetail.indexOf(flags[flagIndex]); } return flagIndexPositions; } private void checkForMissingClientFlags(int[] flagIndexPositions) throws MissingFlagException { for (int flagIndex = 0; flagIndex < flagIndexPositions.length; flagIndex++) { - boolean isEmailIndex = (flagIndex == 2); + boolean isEmailIndex = (flagIndex == CLIENT_EMAIL_INDEX); //Skip empty check for email as email is optional if (!isEmailIndex && !isFlagPresent(flagIndex)) { throw new MissingFlagException(EXCEPTION); @@ -89,17 +98,20 @@ private void checkForMissingClientFlags(int[] flagIndexPositions) throws Missing } private boolean isFlagPresent(int flagIndexPosition) { - return (flagIndexPosition != -1); + return (flagIndexPosition != MISSING_FLAG_VALUE); } private void checkFlagsOrder(int[] flagIndexPositions) throws IncorrectFlagOrderException { - checkForCorrectFlagOrder(flagIndexPositions[0], flagIndexPositions[1]); - boolean hasEmail = (flagIndexPositions[2] != -1); + checkForCorrectFlagOrder(flagIndexPositions[CLIENT_NAME_INDEX], + flagIndexPositions[CLIENT_CONTACT_NUMBER_INDEX]); + boolean hasEmail = (flagIndexPositions[CLIENT_EMAIL_INDEX] != MISSING_FLAG_VALUE); if (hasEmail) { - checkForCorrectFlagOrder(flagIndexPositions[1], flagIndexPositions[2]); - checkForCorrectFlagOrder(flagIndexPositions[2], flagIndexPositions[3]); + checkForCorrectFlagOrder(flagIndexPositions[CLIENT_CONTACT_NUMBER_INDEX], + flagIndexPositions[CLIENT_EMAIL_INDEX]); + checkForCorrectFlagOrder(flagIndexPositions[CLIENT_EMAIL_INDEX], flagIndexPositions[CLIENT_BUDGET_INDEX]); } else { - checkForCorrectFlagOrder(flagIndexPositions[1], flagIndexPositions[3]); + checkForCorrectFlagOrder(flagIndexPositions[CLIENT_CONTACT_NUMBER_INDEX], + flagIndexPositions[CLIENT_BUDGET_INDEX]); } } @@ -111,21 +123,24 @@ private void checkForCorrectFlagOrder(int flagPosition, int nextFlagPosition) th } private ArrayList extractClientDetails(String rawClientDetail, int[] addClientFlagIndexPositions) { - boolean hasEmail = (addClientFlagIndexPositions[2] != -1); + boolean hasEmail = (addClientFlagIndexPositions[CLIENT_EMAIL_INDEX] != MISSING_FLAG_VALUE); String clientContactNumber; String clientEmail = ""; if (hasEmail) { - clientContactNumber = extractDetail(rawClientDetail, addClientFlagIndexPositions[1] + 2, - addClientFlagIndexPositions[2]); - clientEmail = extractDetail(rawClientDetail, addClientFlagIndexPositions[2] + 2, - addClientFlagIndexPositions[3]); + clientContactNumber = extractDetail(rawClientDetail, + addClientFlagIndexPositions[CLIENT_CONTACT_NUMBER_INDEX] + FLAG_JUMPER_VALUE, + addClientFlagIndexPositions[CLIENT_EMAIL_INDEX]); + clientEmail = extractDetail(rawClientDetail, addClientFlagIndexPositions[CLIENT_EMAIL_INDEX] + + FLAG_JUMPER_VALUE, addClientFlagIndexPositions[CLIENT_BUDGET_INDEX]); } else { - clientContactNumber = extractDetail(rawClientDetail, addClientFlagIndexPositions[1] + 2, - addClientFlagIndexPositions[3]); + clientContactNumber = extractDetail(rawClientDetail, + addClientFlagIndexPositions[CLIENT_CONTACT_NUMBER_INDEX] + FLAG_JUMPER_VALUE, + addClientFlagIndexPositions[CLIENT_BUDGET_INDEX]); } - String clientName = extractDetail(rawClientDetail, addClientFlagIndexPositions[0] + 2, - addClientFlagIndexPositions[1]); - String clientBudgetPerMonth = extractDetail(rawClientDetail, addClientFlagIndexPositions[3] + 2); + String clientName = extractDetail(rawClientDetail, addClientFlagIndexPositions[CLIENT_NAME_INDEX] + + FLAG_JUMPER_VALUE, addClientFlagIndexPositions[CLIENT_CONTACT_NUMBER_INDEX]); + String clientBudgetPerMonth = extractDetail(rawClientDetail, + addClientFlagIndexPositions[CLIENT_BUDGET_INDEX] + FLAG_JUMPER_VALUE); ArrayList processedClientDetails = new ArrayList<>(); processedClientDetails.add(clientName.trim()); @@ -146,17 +161,17 @@ private static String extractDetail(String rawDetail, int beginIndex, int endInd private void validateClientDetails(ArrayList clientDetails) throws EmptyDetailException, InvalidContactNumberException, InvalidEmailException, InvalidBudgetFormatException { //Checks for Missing Client Name, Contact Number, Budget Per Month (SGD) - checkForEmptyDetails(clientDetails.get(0)); - checkForEmptyDetails(clientDetails.get(1)); - checkForEmptyDetails(clientDetails.get(3)); + checkForEmptyDetails(clientDetails.get(CLIENT_NAME_INDEX)); + checkForEmptyDetails(clientDetails.get(CLIENT_CONTACT_NUMBER_INDEX)); + checkForEmptyDetails(clientDetails.get(CLIENT_BUDGET_INDEX)); //Checks for Contact Number, Email and Budget Format - checkForValidSingaporeContactNumber(clientDetails.get(1)); - boolean hasEmail = !clientDetails.get(2).isEmpty(); + checkForValidSingaporeContactNumber(clientDetails.get(CLIENT_CONTACT_NUMBER_INDEX)); + boolean hasEmail = !clientDetails.get(CLIENT_EMAIL_INDEX).isEmpty(); if (hasEmail) { - checkForValidEmail(clientDetails.get(2)); + checkForValidEmail(clientDetails.get(CLIENT_EMAIL_INDEX)); } - checkForBudgetNumberFormat(clientDetails.get(3)); + checkForBudgetNumberFormat(clientDetails.get(CLIENT_BUDGET_INDEX)); } private void checkForValidSingaporeContactNumber(String clientContactNumber) throws InvalidContactNumberException { From 83b72d782f47e7968b4bd33e874859220b66a0bf Mon Sep 17 00:00:00 2001 From: "LAPTOP-S1RS66RO\\marcu" Date: Tue, 18 Oct 2022 23:04:45 +0800 Subject: [PATCH 094/325] Fix discrepancies between ParseAddProperty and ParseAddClient --- src/main/java/seedu/duke/Duke.java | 2 - .../duke/parsermanager/ParseAddClient.java | 22 +-- .../duke/parsermanager/ParseAddProperty.java | 160 ++++++++---------- 3 files changed, 78 insertions(+), 106 deletions(-) diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 36c4b4261..9ee09219a 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -36,8 +36,6 @@ public void run() { try { //System.exit(0); //to pass CI String userInputText = ui.readCommand(); - - parser = parserManager.parseCommand(userInputText); command = parser.parseCommand(); command.execute(ui, storage, propertyList, clientList, pairingList); diff --git a/src/main/java/seedu/duke/parsermanager/ParseAddClient.java b/src/main/java/seedu/duke/parsermanager/ParseAddClient.java index 03c777838..4ba38bfdb 100644 --- a/src/main/java/seedu/duke/parsermanager/ParseAddClient.java +++ b/src/main/java/seedu/duke/parsermanager/ParseAddClient.java @@ -71,14 +71,14 @@ private boolean isEmptyString(String commandDetail) { private ArrayList processCommandAddClientDetails(String rawCommandDetail) throws MissingFlagException, IncorrectFlagOrderException { - int[] flagIndexPositions = getFlagIndexPositions(rawCommandDetail); + String[] flags = ADD_CLIENT_FLAGS; + int[] flagIndexPositions = getFlagIndexPositions(rawCommandDetail, flags); checkForMissingClientFlags(flagIndexPositions); - checkFlagsOrder(flagIndexPositions); + checkClientFlagsOrder(flagIndexPositions); return extractClientDetails(rawCommandDetail, flagIndexPositions); } - private int[] getFlagIndexPositions(String commandDetail) { - String[] flags = ADD_CLIENT_FLAGS; + private int[] getFlagIndexPositions(String commandDetail, String[] flags) { int[] flagIndexPositions = new int[flags.length]; for (int flagIndex = 0; flagIndex < flags.length; flagIndex++) { @@ -101,7 +101,7 @@ private boolean isFlagPresent(int flagIndexPosition) { return (flagIndexPosition != MISSING_FLAG_VALUE); } - private void checkFlagsOrder(int[] flagIndexPositions) throws IncorrectFlagOrderException { + private void checkClientFlagsOrder(int[] flagIndexPositions) throws IncorrectFlagOrderException { checkForCorrectFlagOrder(flagIndexPositions[CLIENT_NAME_INDEX], flagIndexPositions[CLIENT_CONTACT_NUMBER_INDEX]); boolean hasEmail = (flagIndexPositions[CLIENT_EMAIL_INDEX] != MISSING_FLAG_VALUE); @@ -142,12 +142,12 @@ private ArrayList extractClientDetails(String rawClientDetail, int[] add String clientBudgetPerMonth = extractDetail(rawClientDetail, addClientFlagIndexPositions[CLIENT_BUDGET_INDEX] + FLAG_JUMPER_VALUE); - ArrayList processedClientDetails = new ArrayList<>(); - processedClientDetails.add(clientName.trim()); - processedClientDetails.add(clientContactNumber.trim()); - processedClientDetails.add(clientEmail.trim()); - processedClientDetails.add(clientBudgetPerMonth.trim()); - return processedClientDetails; + ArrayList extractedClientDetails = new ArrayList<>(); + extractedClientDetails.add(clientName.trim()); + extractedClientDetails.add(clientContactNumber.trim()); + extractedClientDetails.add(clientEmail.trim()); + extractedClientDetails.add(clientBudgetPerMonth.trim()); + return extractedClientDetails; } private static String extractDetail(String rawDetail, int beginIndex) { diff --git a/src/main/java/seedu/duke/parsermanager/ParseAddProperty.java b/src/main/java/seedu/duke/parsermanager/ParseAddProperty.java index 47f841866..b3ce88e93 100644 --- a/src/main/java/seedu/duke/parsermanager/ParseAddProperty.java +++ b/src/main/java/seedu/duke/parsermanager/ParseAddProperty.java @@ -16,12 +16,12 @@ import static seedu.duke.CommandStructure.ADD_PROPERTY_FLAGS; import static seedu.duke.Messages.EXCEPTION; import static seedu.duke.Messages.MESSAGE_ADD_PROPERTY_WRONG_FORMAT; -import static seedu.duke.Messages.MESSAGE_EMPTY_DESCRIPTION; -import static seedu.duke.Messages.MESSAGE_INVALID_PRICE_FORMAT; import static seedu.duke.Messages.MESSAGE_INVALID_SINGAPORE_ADDRESS; +import static seedu.duke.Messages.MESSAGE_INVALID_PRICE_FORMAT; public class ParseAddProperty extends Parser { private final String commandDescription; + private static final int PROPERTY_FLAG_SIZE = 4; public ParseAddProperty(String addCommandDescription) { this.commandDescription = addCommandDescription; @@ -29,18 +29,11 @@ public ParseAddProperty(String addCommandDescription) { public Command parseCommand() throws EmptyDescriptionException, InvalidSingaporeAddressException, MissingFlagException, IncorrectFlagOrderException, InvalidPriceFormatException, EmptyDetailException { - - checkForEmptyDescription(commandDescription); - ArrayList propertyDetails; try { - checkForEmptyDetails(commandDescription); - - propertyDetails = processCommandDetails(commandDescription); + ArrayList propertyDetails = processCommandAddPropertyDetails(commandDescription); validatePropertyDetails(propertyDetails); - return new CommandAddProperty(propertyDetails); - } catch (InvalidSingaporeAddressException e) { throw new InvalidSingaporeAddressException(MESSAGE_INVALID_SINGAPORE_ADDRESS); } catch (MissingFlagException e) { @@ -52,21 +45,6 @@ public Command parseCommand() throws EmptyDescriptionException, InvalidSingapore } catch (EmptyDetailException e) { throw new EmptyDetailException(MESSAGE_ADD_PROPERTY_WRONG_FORMAT); } - - - } - - private void checkForEmptyDescription(String commandDetail) throws EmptyDescriptionException { - boolean isEmptyDescription = isEmptyString(commandDetail); - if (isEmptyDescription) { - throw new EmptyDescriptionException(MESSAGE_EMPTY_DESCRIPTION); - } - } - - private boolean isEmptyString(String commandDetail) { - String trimmedString = commandDetail.trim(); - - return trimmedString.isEmpty(); } private void checkForEmptyDetails(String commandDetail) throws EmptyDetailException { @@ -76,95 +54,46 @@ private void checkForEmptyDetails(String commandDetail) throws EmptyDetailExcept } } - private ArrayList processCommandDetails(String rawCommandDetail) - throws MissingFlagException, IncorrectFlagOrderException { + private boolean isEmptyString(String commandDetail) { + return commandDetail.trim().isEmpty(); + } + private ArrayList processCommandAddPropertyDetails(String rawCommandDetail) + throws MissingFlagException, IncorrectFlagOrderException { String[] flags = ADD_PROPERTY_FLAGS; int[] flagIndexPositions = getFlagIndexPositions(rawCommandDetail, flags); - checkForMissingFlags(flagIndexPositions); - checkFlagsOrder(flagIndexPositions); - return extractCommandDetails(rawCommandDetail, flags, flagIndexPositions); - } - - private void validatePropertyDetails(ArrayList propertyDetails) throws EmptyDetailException, - InvalidSingaporeAddressException, InvalidPriceFormatException { - //Checks for Missing Landlord Name, Property Address, Renting Price (SGD/month) and Unit-Type - for (String propertyDetail : propertyDetails) { - checkForEmptyDetails(propertyDetail); - } - - //Checks Format for Address (Singapore) and Renting Price - checkForValidSingaporeAddress(propertyDetails.get(1)); - checkForPriceNumberFormat(propertyDetails.get(2)); + checkForMissingPropertyFlags(flagIndexPositions); + checkPropertyFlagsOrder(flagIndexPositions); + return extractPropertyDetails(rawCommandDetail, flagIndexPositions); } private int[] getFlagIndexPositions(String commandDetail, String[] flags) { int[] flagIndexPositions = new int[flags.length]; - for (int i = 0; i < flags.length; i++) { - flagIndexPositions[i] = commandDetail.indexOf(flags[i]); + for (int flagIndex = 0; flagIndex < flags.length; flagIndex++) { + flagIndexPositions[flagIndex] = commandDetail.indexOf(flags[flagIndex]); } return flagIndexPositions; } - private void checkForMissingFlags(int[] flagIndexPositions) throws MissingFlagException { + private void checkForMissingPropertyFlags(int[] flagIndexPositions) throws MissingFlagException { for (int flagIndex : flagIndexPositions) { if (!isFlagPresent(flagIndex)) { - throw new MissingFlagException(EXCEPTION); - } - } - } - - private void checkFlagsOrder(int[] flagIndexPositions) throws IncorrectFlagOrderException { - for (int i = 0; i < flagIndexPositions.length - 1; i++) { - checkForCorrectFlagOrder(flagIndexPositions[i], flagIndexPositions[i + 1]); - } - } - - private ArrayList extractCommandDetails(String rawCommandDetail, String[] flags, - int[] flagIndexPositions) { - ArrayList extractedCommandDetails = new ArrayList<>(); - for (int i = 0; i < flags.length; i++) { - String extractedDetail; - if (i == flags.length - 1) { - /* The extracted detail for the last flag starts from the char after the flag, to the end of - rawCommandDetails */ - extractedDetail = extractDetail(rawCommandDetail, flagIndexPositions[i] + flags[i].length()); - } else { - // The extracted detail for non-last starts from the char after the flag, to index before the next flag - extractedDetail = extractDetail( - rawCommandDetail, - flagIndexPositions[i] + flags[i].length(), - flagIndexPositions[i + 1]); + throw new MissingFlagException(EXCEPTION); } - extractedCommandDetails.add(extractedDetail.trim()); } - return extractedCommandDetails; } - private void checkForValidSingaporeAddress(String address) throws InvalidSingaporeAddressException { - boolean hasValidSingaporeLandedPropertyAddress = checkForValidSingaporeLandedPropertyAddress(address); - boolean hasValidSingaporeBuildingAddress = checkForValidSingaporeBuildingAddress(address); - - boolean hasValidSingaporeAddress = hasValidSingaporeLandedPropertyAddress || hasValidSingaporeBuildingAddress; - if (!hasValidSingaporeAddress) { - throw new InvalidSingaporeAddressException(EXCEPTION); - } + private boolean isFlagPresent(int flagIndexPosition) { + return (flagIndexPosition != -1); } - private void checkForPriceNumberFormat(String budget) throws InvalidPriceFormatException { - //Accepts only positive whole number - String regex = "^[1-9]\\d*$"; - boolean hasValidPriceNumberFormat = checkForDetailFormat(regex, budget); - if (!hasValidPriceNumberFormat) { - throw new InvalidPriceFormatException(EXCEPTION); + private void checkPropertyFlagsOrder(int[] flagIndexPositions) throws IncorrectFlagOrderException { + for (int flagIndex = 0; flagIndex < flagIndexPositions.length - 1; flagIndex++) { + checkForCorrectFlagOrder(flagIndexPositions[flagIndex], flagIndexPositions[flagIndex + 1]); } } - private boolean isFlagPresent(int flagIndexPosition) { - return (flagIndexPosition != -1); - } - private void checkForCorrectFlagOrder(int flagPosition, int nextFlagPosition) throws IncorrectFlagOrderException { boolean hasCorrectOrder = (flagPosition < nextFlagPosition); if (!hasCorrectOrder) { @@ -172,6 +101,22 @@ private void checkForCorrectFlagOrder(int flagPosition, int nextFlagPosition) th } } + private ArrayList extractPropertyDetails(String rawPropertyDetail, int[] addPropertyFlagIndexPositions) { + ArrayList extractedPropertyDetails = new ArrayList<>(); + for (int flagIndex = 0; flagIndex < PROPERTY_FLAG_SIZE; flagIndex++) { + boolean isLastFlagIndex = ((flagIndex + 1) == PROPERTY_FLAG_SIZE); + if (isLastFlagIndex) { + extractedPropertyDetails.add(extractDetail(rawPropertyDetail, + addPropertyFlagIndexPositions[flagIndex] + 2).trim()); + } else { + extractedPropertyDetails.add(extractDetail(rawPropertyDetail, + addPropertyFlagIndexPositions[flagIndex] + 2, + addPropertyFlagIndexPositions[flagIndex + 1]).trim()); + } + } + return extractedPropertyDetails; + } + private static String extractDetail(String rawDetail, int beginIndex) { return rawDetail.substring(beginIndex).trim(); } @@ -180,6 +125,28 @@ private static String extractDetail(String rawDetail, int beginIndex, int endInd return rawDetail.substring(beginIndex, endIndex).trim(); } + private void validatePropertyDetails(ArrayList propertyDetails) throws EmptyDetailException, + InvalidSingaporeAddressException, InvalidPriceFormatException { + //Checks for Missing Landlord Name, Property Address, Renting Price (SGD/month) and Unit-Type + for (String propertyDetail : propertyDetails) { + checkForEmptyDetails(propertyDetail); + } + + //Checks Format for Address (Singapore) and Renting Price + checkForValidSingaporeAddress(propertyDetails.get(1)); + checkForPriceNumberFormat(propertyDetails.get(2)); + } + + private void checkForValidSingaporeAddress(String address) throws InvalidSingaporeAddressException { + boolean hasValidSingaporeLandedPropertyAddress = checkForValidSingaporeLandedPropertyAddress(address); + boolean hasValidSingaporeBuildingAddress = checkForValidSingaporeBuildingAddress(address); + + boolean hasValidSingaporeAddress = hasValidSingaporeLandedPropertyAddress || hasValidSingaporeBuildingAddress; + if (!hasValidSingaporeAddress) { + throw new InvalidSingaporeAddressException(EXCEPTION); + } + } + private boolean checkForValidSingaporeLandedPropertyAddress(String address) { String landedPropertyUnitNumberRegex = "^([0-9]{1,4})([A-Z]?) "; String streetNameRegex = "[^.!@#$%^&*()_+=<>\\s\\n?`~0-9,{}|-]([a-zA-Z\\s]+)[^.!@#$%^&*()_+=<>\\s\\n?`~0-9," @@ -228,11 +195,18 @@ private boolean checkForValidSingaporeBuildingAddress(String address) { || hasValidBuildingAddressWithBuildingName || hasValidBuildingAddressWithStreetNumberAndBuildingName; } + private void checkForPriceNumberFormat(String budget) throws InvalidPriceFormatException { + //Accepts only positive whole number + String regex = "^[1-9]\\d*$"; + boolean hasValidPriceNumberFormat = checkForDetailFormat(regex, budget); + if (!hasValidPriceNumberFormat) { + throw new InvalidPriceFormatException(EXCEPTION); + } + } + private boolean checkForDetailFormat(String regex, String detail) { Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(detail); return matcher.matches(); } - - } From 94bb6d82635a4dd03ca91bd8a84c6de5e61cd890 Mon Sep 17 00:00:00 2001 From: "LAPTOP-S1RS66RO\\marcu" Date: Tue, 18 Oct 2022 23:21:21 +0800 Subject: [PATCH 095/325] Fix magic number coding violation for ParseAddProperty --- .../duke/parsermanager/ParseAddProperty.java | 33 +++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/src/main/java/seedu/duke/parsermanager/ParseAddProperty.java b/src/main/java/seedu/duke/parsermanager/ParseAddProperty.java index b3ce88e93..f25650cd0 100644 --- a/src/main/java/seedu/duke/parsermanager/ParseAddProperty.java +++ b/src/main/java/seedu/duke/parsermanager/ParseAddProperty.java @@ -21,7 +21,14 @@ public class ParseAddProperty extends Parser { private final String commandDescription; + private static final int PROPERTY_FLAG_SIZE = 4; + private static final int PROPERTY_ADDRESS_INDEX = 1; + private static final int PROPERTY_PRICE_INDEX = 2; + + private static final int MISSING_FLAG_VALUE = -1; + private static final int FLAG_JUMPER_VALUE = 2; + private static final int UNIT_VALUE = 1; public ParseAddProperty(String addCommandDescription) { this.commandDescription = addCommandDescription; @@ -34,16 +41,16 @@ public Command parseCommand() throws EmptyDescriptionException, InvalidSingapore ArrayList propertyDetails = processCommandAddPropertyDetails(commandDescription); validatePropertyDetails(propertyDetails); return new CommandAddProperty(propertyDetails); - } catch (InvalidSingaporeAddressException e) { - throw new InvalidSingaporeAddressException(MESSAGE_INVALID_SINGAPORE_ADDRESS); + } catch (EmptyDetailException e) { + throw new EmptyDetailException(MESSAGE_ADD_PROPERTY_WRONG_FORMAT); } catch (MissingFlagException e) { throw new MissingFlagException(MESSAGE_ADD_PROPERTY_WRONG_FORMAT); } catch (IncorrectFlagOrderException e) { throw new IncorrectFlagOrderException(MESSAGE_ADD_PROPERTY_WRONG_FORMAT); + } catch (InvalidSingaporeAddressException e) { + throw new InvalidSingaporeAddressException(MESSAGE_INVALID_SINGAPORE_ADDRESS); } catch (InvalidPriceFormatException e) { throw new InvalidPriceFormatException(MESSAGE_INVALID_PRICE_FORMAT); - } catch (EmptyDetailException e) { - throw new EmptyDetailException(MESSAGE_ADD_PROPERTY_WRONG_FORMAT); } } @@ -85,12 +92,12 @@ private void checkForMissingPropertyFlags(int[] flagIndexPositions) throws Missi } private boolean isFlagPresent(int flagIndexPosition) { - return (flagIndexPosition != -1); + return (flagIndexPosition != MISSING_FLAG_VALUE); } private void checkPropertyFlagsOrder(int[] flagIndexPositions) throws IncorrectFlagOrderException { - for (int flagIndex = 0; flagIndex < flagIndexPositions.length - 1; flagIndex++) { - checkForCorrectFlagOrder(flagIndexPositions[flagIndex], flagIndexPositions[flagIndex + 1]); + for (int flagIndex = 0; flagIndex < PROPERTY_FLAG_SIZE - UNIT_VALUE; flagIndex++) { + checkForCorrectFlagOrder(flagIndexPositions[flagIndex], flagIndexPositions[flagIndex + UNIT_VALUE]); } } @@ -104,14 +111,14 @@ private void checkForCorrectFlagOrder(int flagPosition, int nextFlagPosition) th private ArrayList extractPropertyDetails(String rawPropertyDetail, int[] addPropertyFlagIndexPositions) { ArrayList extractedPropertyDetails = new ArrayList<>(); for (int flagIndex = 0; flagIndex < PROPERTY_FLAG_SIZE; flagIndex++) { - boolean isLastFlagIndex = ((flagIndex + 1) == PROPERTY_FLAG_SIZE); + boolean isLastFlagIndex = ((flagIndex + UNIT_VALUE) == PROPERTY_FLAG_SIZE); if (isLastFlagIndex) { extractedPropertyDetails.add(extractDetail(rawPropertyDetail, - addPropertyFlagIndexPositions[flagIndex] + 2).trim()); + addPropertyFlagIndexPositions[flagIndex] + FLAG_JUMPER_VALUE).trim()); } else { extractedPropertyDetails.add(extractDetail(rawPropertyDetail, - addPropertyFlagIndexPositions[flagIndex] + 2, - addPropertyFlagIndexPositions[flagIndex + 1]).trim()); + addPropertyFlagIndexPositions[flagIndex] + FLAG_JUMPER_VALUE, + addPropertyFlagIndexPositions[flagIndex + UNIT_VALUE]).trim()); } } return extractedPropertyDetails; @@ -133,8 +140,8 @@ private void validatePropertyDetails(ArrayList propertyDetails) throws E } //Checks Format for Address (Singapore) and Renting Price - checkForValidSingaporeAddress(propertyDetails.get(1)); - checkForPriceNumberFormat(propertyDetails.get(2)); + checkForValidSingaporeAddress(propertyDetails.get(PROPERTY_ADDRESS_INDEX)); + checkForPriceNumberFormat(propertyDetails.get(PROPERTY_PRICE_INDEX)); } private void checkForValidSingaporeAddress(String address) throws InvalidSingaporeAddressException { From 92077f1bcf3e8cc817aeccdb93ad21efa3c9d686 Mon Sep 17 00:00:00 2001 From: "LAPTOP-S1RS66RO\\marcu" Date: Tue, 18 Oct 2022 23:36:03 +0800 Subject: [PATCH 096/325] Extract validation regex as String constants for ParseAddClient --- .../duke/parsermanager/ParseAddClient.java | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/main/java/seedu/duke/parsermanager/ParseAddClient.java b/src/main/java/seedu/duke/parsermanager/ParseAddClient.java index 4ba38bfdb..3e1d03739 100644 --- a/src/main/java/seedu/duke/parsermanager/ParseAddClient.java +++ b/src/main/java/seedu/duke/parsermanager/ParseAddClient.java @@ -31,6 +31,16 @@ public class ParseAddClient extends Parser { private static final int MISSING_FLAG_VALUE = -1; private static final int FLAG_JUMPER_VALUE = 2; + /* Add Client Regex for Validation */ + private static final String VALID_SINGAPORE_CONTACT_NUMBER_REGEX = "^[689]\\d{7}$"; + //General Email Regex (RFC 5322 Official Standard) + private static final String VALID_EMAIL_REGEX = "(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)" + + "*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x" + + "7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2" + + "[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01" + + "-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])"; + //Accepts only positive whole number for budget + private static final String VALID_BUDGET_REGEX = "^[1-9]\\d*$"; public ParseAddClient(String addCommandDescription) { this.commandDescription = addCommandDescription; @@ -175,29 +185,21 @@ private void validateClientDetails(ArrayList clientDetails) throws Empty } private void checkForValidSingaporeContactNumber(String clientContactNumber) throws InvalidContactNumberException { - boolean hasValidContactNumber = checkForDetailFormat("^[689]\\d{7}$", clientContactNumber); + boolean hasValidContactNumber = checkForDetailFormat(VALID_SINGAPORE_CONTACT_NUMBER_REGEX, clientContactNumber); if (!hasValidContactNumber) { throw new InvalidContactNumberException(EXCEPTION); } } private void checkForValidEmail(String clientEmail) throws InvalidEmailException { - //General Email Regex (RFC 5322 Official Standard) - String regex = "(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\" - + "x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-" - + "9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-" - + "9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0" - + "c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])"; - boolean hasValidEmail = checkForDetailFormat(regex, clientEmail); + boolean hasValidEmail = checkForDetailFormat(VALID_EMAIL_REGEX, clientEmail); if (!hasValidEmail) { throw new InvalidEmailException(EXCEPTION); } } private void checkForBudgetNumberFormat(String budget) throws InvalidBudgetFormatException { - //Accepts only positive whole number - String regex = "^[1-9]\\d*$"; - boolean hasValidBudgetNumberFormat = checkForDetailFormat(regex, budget); + boolean hasValidBudgetNumberFormat = checkForDetailFormat(VALID_BUDGET_REGEX, budget); if (!hasValidBudgetNumberFormat) { throw new InvalidBudgetFormatException(EXCEPTION); } From ec812f68eebb692816b7bff8389605278ee98f09 Mon Sep 17 00:00:00 2001 From: "LAPTOP-S1RS66RO\\marcu" Date: Wed, 19 Oct 2022 00:01:21 +0800 Subject: [PATCH 097/325] Extract validation regex as String constants for ParseAddProperty --- .../duke/parsermanager/ParseAddProperty.java | 78 ++++++++++--------- 1 file changed, 40 insertions(+), 38 deletions(-) diff --git a/src/main/java/seedu/duke/parsermanager/ParseAddProperty.java b/src/main/java/seedu/duke/parsermanager/ParseAddProperty.java index f25650cd0..8415d84e4 100644 --- a/src/main/java/seedu/duke/parsermanager/ParseAddProperty.java +++ b/src/main/java/seedu/duke/parsermanager/ParseAddProperty.java @@ -30,6 +30,39 @@ public class ParseAddProperty extends Parser { private static final int FLAG_JUMPER_VALUE = 2; private static final int UNIT_VALUE = 1; + /* Add Property Regex for Validation */ + //Singapore Address Related Regex + private static final String LANDED_PROPERTY_UNIT_NUMBER_REGEX = "^([0-9]{1,4})([A-Z]?) "; + private static final String BUILDING_BLOCK_NUMBER_REGEX = "^([0-9]{1,4})([A-Z]?) "; + private static final String STREET_NAME_REGEX = "[^.!@#$%^&*()_+=<>\\s\\n?`~0-9,{}|-]([a-zA-Z\\s]+)[^.!@#$%^&*()_+" + + "=<>\\s\\n?`~0-9,{}|-]"; + private static final String STREET_NUMBER_REGEX = " ([1-9]{1}[0-9]{0,3})"; + private static final String BUILDING_UNIT_FLOOR_AND_NUMBER_REGEX = " #(([0]{1}[1-9]{1})|([1-9]{1}[0-9]{1,2}))-(([0]" + + "{1}[1-9]{1})|([1-9]{1}[0-9]{1,3}))([A-Z]?)"; + private static final String BUILDING_NAME_REGEX = " [^.!@#$%^&*()_+=<>\\s\\n?`~0-9,{}|-]([a-zA-Z\\s]+)[^.!@#$%^&*()" + + "_+=<>\\s\\n?`~0-9,{}|-]"; + private static final String POSTAL_CODE_REGEX = ", (Singapore [0-9]{6})$"; + + //Singapore Landed Property Regex + private static final String LANDED_PROPERTY_ADDRESS_REGEX = LANDED_PROPERTY_UNIT_NUMBER_REGEX + STREET_NAME_REGEX + + POSTAL_CODE_REGEX; + private static final String LANDED_PROPERTY_ADDRESS_WITH_STREET_NUMBER_REGEX = LANDED_PROPERTY_UNIT_NUMBER_REGEX + + STREET_NAME_REGEX + STREET_NUMBER_REGEX + POSTAL_CODE_REGEX; + + //Singapore Building Regex + private static final String BUILDING_ADDRESS_REGEX = BUILDING_BLOCK_NUMBER_REGEX + STREET_NAME_REGEX + + BUILDING_UNIT_FLOOR_AND_NUMBER_REGEX + POSTAL_CODE_REGEX; + private static final String BUILDING_ADDRESS_WITH_STREET_NUMBER_REGEX = BUILDING_BLOCK_NUMBER_REGEX + + STREET_NAME_REGEX + STREET_NUMBER_REGEX + BUILDING_UNIT_FLOOR_AND_NUMBER_REGEX + POSTAL_CODE_REGEX; + private static final String BUILDING_ADDRESS_WITH_BUILDING_NAME_REGEX = BUILDING_BLOCK_NUMBER_REGEX + + STREET_NAME_REGEX + BUILDING_UNIT_FLOOR_AND_NUMBER_REGEX + BUILDING_NAME_REGEX + POSTAL_CODE_REGEX; + private static final String BUILDING_ADDRESS_WITH_STREET_NUMBER_AND_BUILDING_NAME_REGEX + = BUILDING_BLOCK_NUMBER_REGEX + STREET_NAME_REGEX + STREET_NUMBER_REGEX + + BUILDING_UNIT_FLOOR_AND_NUMBER_REGEX + BUILDING_NAME_REGEX + POSTAL_CODE_REGEX; + + //Accepts only positive whole number for price + private static final String VALID_PRICE_REGEX = "^[1-9]\\d*$"; + public ParseAddProperty(String addCommandDescription) { this.commandDescription = addCommandDescription; } @@ -155,57 +188,26 @@ private void checkForValidSingaporeAddress(String address) throws InvalidSingapo } private boolean checkForValidSingaporeLandedPropertyAddress(String address) { - String landedPropertyUnitNumberRegex = "^([0-9]{1,4})([A-Z]?) "; - String streetNameRegex = "[^.!@#$%^&*()_+=<>\\s\\n?`~0-9,{}|-]([a-zA-Z\\s]+)[^.!@#$%^&*()_+=<>\\s\\n?`~0-9," - + "{}|-]"; - String streetNumberRegex = " ([1-9]{1}[0-9]{0,3})"; - String postalCodeRegex = ", (Singapore [0-9]{6})$"; - - String landedPropertyAddressRegex = landedPropertyUnitNumberRegex + streetNameRegex + postalCodeRegex; - String landedPropertyAddressWithStreetNumberRegex = landedPropertyUnitNumberRegex + streetNameRegex - + streetNumberRegex + postalCodeRegex; - - boolean hasValidLandedPropertyAddress = checkForDetailFormat(landedPropertyAddressRegex, address); + boolean hasValidLandedPropertyAddress = checkForDetailFormat(LANDED_PROPERTY_ADDRESS_REGEX, address); boolean hasValidLandedPropertyAddressWithStreetNumber - = checkForDetailFormat(landedPropertyAddressWithStreetNumberRegex, address); + = checkForDetailFormat(LANDED_PROPERTY_ADDRESS_WITH_STREET_NUMBER_REGEX, address); return hasValidLandedPropertyAddress || hasValidLandedPropertyAddressWithStreetNumber; } private boolean checkForValidSingaporeBuildingAddress(String address) { - String buildingBlockNumberRegex = "^([0-9]{1,4})([A-Z]?) "; - String streetNameRegex = "[^.!@#$%^&*()_+=<>\\s\\n?`~0-9,{}|-]([a-zA-Z\\s]+)[^.!@#$%^&*()_+=<>\\s\\n?`~0-9," - + "{}|-]"; - String streetNumberRegex = " ([1-9]{1}[0-9]{0,3})"; - String buildingUnitFloorAndNumberRegex = " #(([0]{1}[1-9]{1})|([1-9]{1}[0-9]{1,2}))-(([0]{1}[1-9]{1})|([1-9]" - + "{1}[0-9]{1,3}))([A-Z]?)"; - String buildingNameRegex = " [^.!@#$%^&*()_+=<>\\s\\n?`~0-9,{}|-]([a-zA-Z\\s]+)[^.!@#$%^&*()_+=<>\\s\\n?`~0-9" - + ",{}|-]"; - String postalCodeRegex = ", (Singapore [0-9]{6})$"; - - String buildingAddressRegex = buildingBlockNumberRegex + streetNameRegex + buildingUnitFloorAndNumberRegex - + postalCodeRegex; - String buildingAddressWithStreetNumberRegex = buildingBlockNumberRegex + streetNameRegex + streetNumberRegex - + buildingUnitFloorAndNumberRegex + postalCodeRegex; - String buildingAddressWithBuildingNameRegex = buildingBlockNumberRegex + streetNameRegex - + buildingUnitFloorAndNumberRegex + buildingNameRegex + postalCodeRegex; - String buildingAddressWithStreetNumberAndBuildingNameRegex = buildingBlockNumberRegex + streetNameRegex - + streetNumberRegex + buildingUnitFloorAndNumberRegex + buildingNameRegex + postalCodeRegex; - - boolean hasValidBuildingAddress = checkForDetailFormat(buildingAddressRegex, address); + boolean hasValidBuildingAddress = checkForDetailFormat(BUILDING_ADDRESS_REGEX, address); boolean hasValidBuildingAddressWithStreetNumber - = checkForDetailFormat(buildingAddressWithStreetNumberRegex, address); + = checkForDetailFormat(BUILDING_ADDRESS_WITH_STREET_NUMBER_REGEX, address); boolean hasValidBuildingAddressWithBuildingName - = checkForDetailFormat(buildingAddressWithBuildingNameRegex, address); + = checkForDetailFormat(BUILDING_ADDRESS_WITH_BUILDING_NAME_REGEX, address); boolean hasValidBuildingAddressWithStreetNumberAndBuildingName - = checkForDetailFormat(buildingAddressWithStreetNumberAndBuildingNameRegex, address); + = checkForDetailFormat(BUILDING_ADDRESS_WITH_STREET_NUMBER_AND_BUILDING_NAME_REGEX, address); return hasValidBuildingAddress || hasValidBuildingAddressWithStreetNumber || hasValidBuildingAddressWithBuildingName || hasValidBuildingAddressWithStreetNumberAndBuildingName; } private void checkForPriceNumberFormat(String budget) throws InvalidPriceFormatException { - //Accepts only positive whole number - String regex = "^[1-9]\\d*$"; - boolean hasValidPriceNumberFormat = checkForDetailFormat(regex, budget); + boolean hasValidPriceNumberFormat = checkForDetailFormat(VALID_PRICE_REGEX, budget); if (!hasValidPriceNumberFormat) { throw new InvalidPriceFormatException(EXCEPTION); } From 2cc2c86fbd708d1e87bf487f21bbfabc864268b4 Mon Sep 17 00:00:00 2001 From: "LAPTOP-S1RS66RO\\marcu" Date: Wed, 19 Oct 2022 10:21:58 +0800 Subject: [PATCH 098/325] Extract common methods from ParseAddProperty and ParseAddClient into new superclass ParseAdd (ParserAdd Parent Class is Parser) --- .../seedu/duke/parsermanager/ParseAdd.java | 58 ++++++++++++++++++ .../duke/parsermanager/ParseAddClient.java | 57 ++---------------- .../duke/parsermanager/ParseAddProperty.java | 60 ++----------------- 3 files changed, 67 insertions(+), 108 deletions(-) create mode 100644 src/main/java/seedu/duke/parsermanager/ParseAdd.java diff --git a/src/main/java/seedu/duke/parsermanager/ParseAdd.java b/src/main/java/seedu/duke/parsermanager/ParseAdd.java new file mode 100644 index 000000000..fa8c3e408 --- /dev/null +++ b/src/main/java/seedu/duke/parsermanager/ParseAdd.java @@ -0,0 +1,58 @@ +package seedu.duke.parsermanager; + +import seedu.duke.exception.EmptyDetailException; +import seedu.duke.exception.IncorrectFlagOrderException; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static seedu.duke.Messages.EXCEPTION; + +public abstract class ParseAdd extends Parser { + protected static final int MISSING_FLAG_VALUE = -1; + + protected void checkForEmptyDetails(String commandDetail) throws EmptyDetailException { + boolean isEmptyDetail = isEmptyString(commandDetail); + if (isEmptyDetail) { + throw new EmptyDetailException(EXCEPTION); + } + } + + private boolean isEmptyString(String commandDetail) { + return commandDetail.trim().isEmpty(); + } + + protected int[] getFlagIndexPositions(String commandDetail, String[] flags) { + int[] flagIndexPositions = new int[flags.length]; + + for (int flagIndex = 0; flagIndex < flags.length; flagIndex++) { + flagIndexPositions[flagIndex] = commandDetail.indexOf(flags[flagIndex]); + } + return flagIndexPositions; + } + + protected boolean checkForFlagPresence(int flagIndexPosition) { + return (flagIndexPosition != MISSING_FLAG_VALUE); + } + + protected void checkForCorrectFlagOrder(int flagPosition, int nextFlagPosition) throws IncorrectFlagOrderException { + boolean hasCorrectOrder = (flagPosition < nextFlagPosition); + if (!hasCorrectOrder) { + throw new IncorrectFlagOrderException(EXCEPTION); + } + } + + protected String extractDetail(String rawDetail, int beginIndex) { + return rawDetail.substring(beginIndex).trim(); + } + + protected String extractDetail(String rawDetail, int beginIndex, int endIndex) { + return rawDetail.substring(beginIndex, endIndex).trim(); + } + + protected boolean checkForDetailFormat(String regex, String detail) { + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(detail); + return matcher.matches(); + } +} diff --git a/src/main/java/seedu/duke/parsermanager/ParseAddClient.java b/src/main/java/seedu/duke/parsermanager/ParseAddClient.java index 3e1d03739..c02f2af13 100644 --- a/src/main/java/seedu/duke/parsermanager/ParseAddClient.java +++ b/src/main/java/seedu/duke/parsermanager/ParseAddClient.java @@ -10,8 +10,6 @@ import seedu.duke.exception.MissingFlagException; import java.util.ArrayList; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import static seedu.duke.CommandStructure.ADD_CLIENT_FLAGS; import static seedu.duke.Messages.EXCEPTION; @@ -20,7 +18,7 @@ import static seedu.duke.Messages.MESSAGE_INVALID_EMAIL; import static seedu.duke.Messages.MESSAGE_INVALID_BUDGET_FORMAT; -public class ParseAddClient extends Parser { +public class ParseAddClient extends ParseAdd { private final String commandDescription; private static final int CLIENT_NAME_INDEX = 0; @@ -28,7 +26,6 @@ public class ParseAddClient extends Parser { private static final int CLIENT_EMAIL_INDEX = 2; private static final int CLIENT_BUDGET_INDEX = 3; - private static final int MISSING_FLAG_VALUE = -1; private static final int FLAG_JUMPER_VALUE = 2; /* Add Client Regex for Validation */ @@ -46,7 +43,7 @@ public ParseAddClient(String addCommandDescription) { this.commandDescription = addCommandDescription; } - public Command parseCommand() throws MissingFlagException, IncorrectFlagOrderException, EmptyDetailException, + public Command parseCommand() throws EmptyDetailException, MissingFlagException, IncorrectFlagOrderException, InvalidContactNumberException, InvalidEmailException, InvalidBudgetFormatException { try { checkForEmptyDetails(commandDescription); @@ -68,49 +65,24 @@ public Command parseCommand() throws MissingFlagException, IncorrectFlagOrderExc } } - private void checkForEmptyDetails(String commandDetail) throws EmptyDetailException { - boolean isEmptyDetail = isEmptyString(commandDetail); - if (isEmptyDetail) { - throw new EmptyDetailException(EXCEPTION); - } - } - - private boolean isEmptyString(String commandDetail) { - return commandDetail.trim().isEmpty(); - } - private ArrayList processCommandAddClientDetails(String rawCommandDetail) throws MissingFlagException, IncorrectFlagOrderException { - String[] flags = ADD_CLIENT_FLAGS; - int[] flagIndexPositions = getFlagIndexPositions(rawCommandDetail, flags); + int[] flagIndexPositions = getFlagIndexPositions(rawCommandDetail, ADD_CLIENT_FLAGS); checkForMissingClientFlags(flagIndexPositions); checkClientFlagsOrder(flagIndexPositions); return extractClientDetails(rawCommandDetail, flagIndexPositions); } - private int[] getFlagIndexPositions(String commandDetail, String[] flags) { - int[] flagIndexPositions = new int[flags.length]; - - for (int flagIndex = 0; flagIndex < flags.length; flagIndex++) { - flagIndexPositions[flagIndex] = commandDetail.indexOf(flags[flagIndex]); - } - return flagIndexPositions; - } - private void checkForMissingClientFlags(int[] flagIndexPositions) throws MissingFlagException { for (int flagIndex = 0; flagIndex < flagIndexPositions.length; flagIndex++) { boolean isEmailIndex = (flagIndex == CLIENT_EMAIL_INDEX); //Skip empty check for email as email is optional - if (!isEmailIndex && !isFlagPresent(flagIndex)) { + if (!isEmailIndex && !checkForFlagPresence(flagIndex)) { throw new MissingFlagException(EXCEPTION); } } } - private boolean isFlagPresent(int flagIndexPosition) { - return (flagIndexPosition != MISSING_FLAG_VALUE); - } - private void checkClientFlagsOrder(int[] flagIndexPositions) throws IncorrectFlagOrderException { checkForCorrectFlagOrder(flagIndexPositions[CLIENT_NAME_INDEX], flagIndexPositions[CLIENT_CONTACT_NUMBER_INDEX]); @@ -125,13 +97,6 @@ private void checkClientFlagsOrder(int[] flagIndexPositions) throws IncorrectFla } } - private void checkForCorrectFlagOrder(int flagPosition, int nextFlagPosition) throws IncorrectFlagOrderException { - boolean hasCorrectOrder = (flagPosition < nextFlagPosition); - if (!hasCorrectOrder) { - throw new IncorrectFlagOrderException(EXCEPTION); - } - } - private ArrayList extractClientDetails(String rawClientDetail, int[] addClientFlagIndexPositions) { boolean hasEmail = (addClientFlagIndexPositions[CLIENT_EMAIL_INDEX] != MISSING_FLAG_VALUE); String clientContactNumber; @@ -160,14 +125,6 @@ private ArrayList extractClientDetails(String rawClientDetail, int[] add return extractedClientDetails; } - private static String extractDetail(String rawDetail, int beginIndex) { - return rawDetail.substring(beginIndex).trim(); - } - - private static String extractDetail(String rawDetail, int beginIndex, int endIndex) { - return rawDetail.substring(beginIndex, endIndex).trim(); - } - private void validateClientDetails(ArrayList clientDetails) throws EmptyDetailException, InvalidContactNumberException, InvalidEmailException, InvalidBudgetFormatException { //Checks for Missing Client Name, Contact Number, Budget Per Month (SGD) @@ -204,10 +161,4 @@ private void checkForBudgetNumberFormat(String budget) throws InvalidBudgetForma throw new InvalidBudgetFormatException(EXCEPTION); } } - - private boolean checkForDetailFormat(String regex, String detail) { - Pattern pattern = Pattern.compile(regex); - Matcher matcher = pattern.matcher(detail); - return matcher.matches(); - } } diff --git a/src/main/java/seedu/duke/parsermanager/ParseAddProperty.java b/src/main/java/seedu/duke/parsermanager/ParseAddProperty.java index 8415d84e4..ef6ad3f4c 100644 --- a/src/main/java/seedu/duke/parsermanager/ParseAddProperty.java +++ b/src/main/java/seedu/duke/parsermanager/ParseAddProperty.java @@ -2,7 +2,6 @@ import seedu.duke.command.Command; import seedu.duke.command.CommandAddProperty; -import seedu.duke.exception.EmptyDescriptionException; import seedu.duke.exception.EmptyDetailException; import seedu.duke.exception.IncorrectFlagOrderException; import seedu.duke.exception.InvalidPriceFormatException; @@ -10,8 +9,6 @@ import seedu.duke.exception.MissingFlagException; import java.util.ArrayList; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import static seedu.duke.CommandStructure.ADD_PROPERTY_FLAGS; import static seedu.duke.Messages.EXCEPTION; @@ -19,14 +16,13 @@ import static seedu.duke.Messages.MESSAGE_INVALID_SINGAPORE_ADDRESS; import static seedu.duke.Messages.MESSAGE_INVALID_PRICE_FORMAT; -public class ParseAddProperty extends Parser { +public class ParseAddProperty extends ParseAdd { private final String commandDescription; private static final int PROPERTY_FLAG_SIZE = 4; private static final int PROPERTY_ADDRESS_INDEX = 1; private static final int PROPERTY_PRICE_INDEX = 2; - private static final int MISSING_FLAG_VALUE = -1; private static final int FLAG_JUMPER_VALUE = 2; private static final int UNIT_VALUE = 1; @@ -67,8 +63,8 @@ public ParseAddProperty(String addCommandDescription) { this.commandDescription = addCommandDescription; } - public Command parseCommand() throws EmptyDescriptionException, InvalidSingaporeAddressException, - MissingFlagException, IncorrectFlagOrderException, InvalidPriceFormatException, EmptyDetailException { + public Command parseCommand() throws EmptyDetailException, MissingFlagException, IncorrectFlagOrderException, + InvalidSingaporeAddressException, InvalidPriceFormatException { try { checkForEmptyDetails(commandDescription); ArrayList propertyDetails = processCommandAddPropertyDetails(commandDescription); @@ -87,60 +83,28 @@ public Command parseCommand() throws EmptyDescriptionException, InvalidSingapore } } - private void checkForEmptyDetails(String commandDetail) throws EmptyDetailException { - boolean isEmptyDetail = isEmptyString(commandDetail); - if (isEmptyDetail) { - throw new EmptyDetailException(EXCEPTION); - } - } - - private boolean isEmptyString(String commandDetail) { - return commandDetail.trim().isEmpty(); - } - private ArrayList processCommandAddPropertyDetails(String rawCommandDetail) throws MissingFlagException, IncorrectFlagOrderException { - String[] flags = ADD_PROPERTY_FLAGS; - int[] flagIndexPositions = getFlagIndexPositions(rawCommandDetail, flags); + int[] flagIndexPositions = getFlagIndexPositions(rawCommandDetail, ADD_PROPERTY_FLAGS); checkForMissingPropertyFlags(flagIndexPositions); checkPropertyFlagsOrder(flagIndexPositions); return extractPropertyDetails(rawCommandDetail, flagIndexPositions); } - private int[] getFlagIndexPositions(String commandDetail, String[] flags) { - int[] flagIndexPositions = new int[flags.length]; - - for (int flagIndex = 0; flagIndex < flags.length; flagIndex++) { - flagIndexPositions[flagIndex] = commandDetail.indexOf(flags[flagIndex]); - } - return flagIndexPositions; - } - private void checkForMissingPropertyFlags(int[] flagIndexPositions) throws MissingFlagException { for (int flagIndex : flagIndexPositions) { - if (!isFlagPresent(flagIndex)) { + if (!checkForFlagPresence(flagIndex)) { throw new MissingFlagException(EXCEPTION); } } } - private boolean isFlagPresent(int flagIndexPosition) { - return (flagIndexPosition != MISSING_FLAG_VALUE); - } - private void checkPropertyFlagsOrder(int[] flagIndexPositions) throws IncorrectFlagOrderException { for (int flagIndex = 0; flagIndex < PROPERTY_FLAG_SIZE - UNIT_VALUE; flagIndex++) { checkForCorrectFlagOrder(flagIndexPositions[flagIndex], flagIndexPositions[flagIndex + UNIT_VALUE]); } } - private void checkForCorrectFlagOrder(int flagPosition, int nextFlagPosition) throws IncorrectFlagOrderException { - boolean hasCorrectOrder = (flagPosition < nextFlagPosition); - if (!hasCorrectOrder) { - throw new IncorrectFlagOrderException(EXCEPTION); - } - } - private ArrayList extractPropertyDetails(String rawPropertyDetail, int[] addPropertyFlagIndexPositions) { ArrayList extractedPropertyDetails = new ArrayList<>(); for (int flagIndex = 0; flagIndex < PROPERTY_FLAG_SIZE; flagIndex++) { @@ -157,14 +121,6 @@ private ArrayList extractPropertyDetails(String rawPropertyDetail, int[] return extractedPropertyDetails; } - private static String extractDetail(String rawDetail, int beginIndex) { - return rawDetail.substring(beginIndex).trim(); - } - - private static String extractDetail(String rawDetail, int beginIndex, int endIndex) { - return rawDetail.substring(beginIndex, endIndex).trim(); - } - private void validatePropertyDetails(ArrayList propertyDetails) throws EmptyDetailException, InvalidSingaporeAddressException, InvalidPriceFormatException { //Checks for Missing Landlord Name, Property Address, Renting Price (SGD/month) and Unit-Type @@ -212,10 +168,4 @@ private void checkForPriceNumberFormat(String budget) throws InvalidPriceFormatE throw new InvalidPriceFormatException(EXCEPTION); } } - - private boolean checkForDetailFormat(String regex, String detail) { - Pattern pattern = Pattern.compile(regex); - Matcher matcher = pattern.matcher(detail); - return matcher.matches(); - } } From 0b486406a250952009d18920da732f066aa81d97 Mon Sep 17 00:00:00 2001 From: "LAPTOP-S1RS66RO\\marcu" Date: Wed, 19 Oct 2022 10:29:58 +0800 Subject: [PATCH 099/325] Add basic JavaDoc for Classes ParseAdd, ParseAddProperty and ParseAddClient --- src/main/java/seedu/duke/parsermanager/ParseAdd.java | 3 +++ src/main/java/seedu/duke/parsermanager/ParseAddClient.java | 3 +++ src/main/java/seedu/duke/parsermanager/ParseAddProperty.java | 3 +++ 3 files changed, 9 insertions(+) diff --git a/src/main/java/seedu/duke/parsermanager/ParseAdd.java b/src/main/java/seedu/duke/parsermanager/ParseAdd.java index fa8c3e408..9c691e300 100644 --- a/src/main/java/seedu/duke/parsermanager/ParseAdd.java +++ b/src/main/java/seedu/duke/parsermanager/ParseAdd.java @@ -8,6 +8,9 @@ import static seedu.duke.Messages.EXCEPTION; +/** + * Parses input for add-type command. + */ public abstract class ParseAdd extends Parser { protected static final int MISSING_FLAG_VALUE = -1; diff --git a/src/main/java/seedu/duke/parsermanager/ParseAddClient.java b/src/main/java/seedu/duke/parsermanager/ParseAddClient.java index c02f2af13..a599a4800 100644 --- a/src/main/java/seedu/duke/parsermanager/ParseAddClient.java +++ b/src/main/java/seedu/duke/parsermanager/ParseAddClient.java @@ -18,6 +18,9 @@ import static seedu.duke.Messages.MESSAGE_INVALID_EMAIL; import static seedu.duke.Messages.MESSAGE_INVALID_BUDGET_FORMAT; +/** + * Parses input for add client command. + */ public class ParseAddClient extends ParseAdd { private final String commandDescription; diff --git a/src/main/java/seedu/duke/parsermanager/ParseAddProperty.java b/src/main/java/seedu/duke/parsermanager/ParseAddProperty.java index ef6ad3f4c..812cd7399 100644 --- a/src/main/java/seedu/duke/parsermanager/ParseAddProperty.java +++ b/src/main/java/seedu/duke/parsermanager/ParseAddProperty.java @@ -16,6 +16,9 @@ import static seedu.duke.Messages.MESSAGE_INVALID_SINGAPORE_ADDRESS; import static seedu.duke.Messages.MESSAGE_INVALID_PRICE_FORMAT; +/** + * Parses input for add property command. + */ public class ParseAddProperty extends ParseAdd { private final String commandDescription; From 401bd3653c4edb9bba13cc9f4357cfd36b3228fe Mon Sep 17 00:00:00 2001 From: FeliciaBeatrice Date: Wed, 19 Oct 2022 12:53:25 +0800 Subject: [PATCH 100/325] Show deleted pairs when deleting --- src/main/java/seedu/duke/Messages.java | 6 ++++ src/main/java/seedu/duke/Ui.java | 29 +++++++++++++++++++ .../duke/command/CommandDeleteClient.java | 5 +--- .../duke/command/CommandDeleteProperty.java | 11 ++----- 4 files changed, 38 insertions(+), 13 deletions(-) diff --git a/src/main/java/seedu/duke/Messages.java b/src/main/java/seedu/duke/Messages.java index 7782e46e1..3d0ab8436 100644 --- a/src/main/java/seedu/duke/Messages.java +++ b/src/main/java/seedu/duke/Messages.java @@ -28,6 +28,12 @@ public class Messages { public static final String MESSAGE_UNPAIRED = "Unpairing the following client and property: "; + public static final String MESSAGE_PAIRED_PROPERTIES_DELETED = "\nThe pairing this client has with " + + "the following property will be deleted:"; + + public static final String MESSAGE_PAIRED_CLIENTS_DELETED = "\nThe pairing(s) this property has with " + + "the following client(s) will be deleted:"; + /* General Error Messages */ diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index 808eedd5a..7d4531951 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -3,6 +3,8 @@ import seedu.duke.exception.DukeException; import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; import java.util.Scanner; import static seedu.duke.Messages.LINE_BREAK; @@ -12,6 +14,8 @@ import static seedu.duke.Messages.MESSAGE_COMMAND_UNDEFINED; import static seedu.duke.Messages.MESSAGE_NUMBER_OF_LIST_RESULTS; import static seedu.duke.Messages.MESSAGE_PAIRED; +import static seedu.duke.Messages.MESSAGE_PAIRED_CLIENTS_DELETED; +import static seedu.duke.Messages.MESSAGE_PAIRED_PROPERTIES_DELETED; import static seedu.duke.Messages.MESSAGE_PROPERTY_ADDED; import static seedu.duke.Messages.MESSAGE_PROPERTY_DELETED; import static seedu.duke.Messages.MESSAGE_UNPAIRED; @@ -80,6 +84,31 @@ public void showClientDeletedConfirmationMessage(Client deletedClient) { showToUser(" " + deletedClient); } + public void showPairedPropertiesDeletedConfirmationMessage(Client deletedClient, PairingList pairingList) { + HashMap clientPropertyPairs = pairingList.getClientPropertyPairs(); + if (clientPropertyPairs.containsKey(deletedClient)) { + Property pairedProperty = clientPropertyPairs.get(deletedClient); + showToUser(MESSAGE_PAIRED_PROPERTIES_DELETED); + showToUser(" " + pairedProperty.getPropertyAddress()); + } + } + + public void showPairedClientsDeletedConfirmationMessage(Property deletedProperty, PairingList pairingList) { + HashMap clientPropertyPairs = pairingList.getClientPropertyPairs(); + int currentIndex = 1; + + for (Map.Entry entry : clientPropertyPairs.entrySet()) { + if (entry.getValue().equals(deletedProperty)) { + if (currentIndex == 1) { + showToUser(MESSAGE_PAIRED_CLIENTS_DELETED); + } + Client pairedClient = entry.getKey(); + showToUser(" " + currentIndex + ". " + pairedClient.getClientName()); + currentIndex++; + } + } + } + /* Pair/Unpair-Command-related showMessage methods. */ diff --git a/src/main/java/seedu/duke/command/CommandDeleteClient.java b/src/main/java/seedu/duke/command/CommandDeleteClient.java index 44acc3eeb..2a855c398 100644 --- a/src/main/java/seedu/duke/command/CommandDeleteClient.java +++ b/src/main/java/seedu/duke/command/CommandDeleteClient.java @@ -23,14 +23,11 @@ public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, PairingList pairingList) { Client deletedClient = clientList.deleteClient(clientIndex); ui.showClientDeletedConfirmationMessage(deletedClient); + ui.showPairedPropertiesDeletedConfirmationMessage(deletedClient, pairingList); pairingList.deletePairing(deletedClient); //Update Storage storage.updateClient(clientList); - - for (Client i : pairingList.getClientPropertyPairs().keySet()) { - System.out.println("Key: " + i + "Value: " + pairingList.getClientPropertyPairs().get(i)); - } storage.updatePair(pairingList); } } diff --git a/src/main/java/seedu/duke/command/CommandDeleteProperty.java b/src/main/java/seedu/duke/command/CommandDeleteProperty.java index 8d016b718..d82186a72 100644 --- a/src/main/java/seedu/duke/command/CommandDeleteProperty.java +++ b/src/main/java/seedu/duke/command/CommandDeleteProperty.java @@ -21,20 +21,13 @@ public CommandDeleteProperty(int propertyIndex) { @Override public void execute(Ui ui, Storage storage, PropertyList propertyList, ClientList clientList, PairingList pairingList) { - Property deletedProperty = propertyList.deleteProperty(propertyIndex); - ui.showPropertyDeletedConfirmationMessage(deletedProperty); - + ui.showPairedClientsDeletedConfirmationMessage(deletedProperty, pairingList); pairingList.deletePairing(deletedProperty); + //Update Storage storage.updateProperty(propertyList); - - - for (Client i : pairingList.getClientPropertyPairs().keySet()) { - System.out.println("Key: " + i + "Value: " + pairingList.getClientPropertyPairs().get(i)); - } - storage.updatePair(pairingList); } From 5f4213746959f897f81afe848abc3ea014e72b84 Mon Sep 17 00:00:00 2001 From: zoranabc201 <80355198+zoranabc201@users.noreply.github.com> Date: Wed, 19 Oct 2022 15:44:52 +0800 Subject: [PATCH 101/325] Update CommandStructure.java --- src/main/java/seedu/duke/CommandStructure.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/duke/CommandStructure.java b/src/main/java/seedu/duke/CommandStructure.java index 823b9d04c..25ddea0f7 100644 --- a/src/main/java/seedu/duke/CommandStructure.java +++ b/src/main/java/seedu/duke/CommandStructure.java @@ -19,7 +19,7 @@ public class CommandStructure { public static final String PROPERTY_FLAG = "-property"; public static final String CLIENT_FLAG = "-client"; - private static final String EVERYTHING_FLAG = "-everything"; + public static final String EVERYTHING_FLAG = "-everything"; public static final String[] ADD_PROPERTY_FLAGS = {"n/", "a/", "p/", "t/"}; public static final String[] ADD_CLIENT_FLAGS = {"n/", "c/", "e/", "b/"}; From d49a6e29b8b22469a639d891b19b4539270ffa3d Mon Sep 17 00:00:00 2001 From: "MSI\\User" Date: Thu, 20 Oct 2022 09:53:22 +0800 Subject: [PATCH 102/325] Update Design and Implementation portion for Storage --- docs/DeveloperGuide.md | 76 ++++++++++++++++++ docs/diagrams/LoadFileFlowChart.jpg | Bin 0 -> 60244 bytes .../StorageAddClientSequenceDiagram.jpg | Bin 0 -> 51091 bytes .../StorageAddPairSequenceDiagram.jpg | Bin 0 -> 47426 bytes .../StorageAddPropertySequenceDiagram.jpg | Bin 0 -> 52312 bytes docs/diagrams/StorageDesignDiagram.jpg | Bin 0 -> 41564 bytes docs/diagrams/StorageUpdateClientSD.jpg | Bin 0 -> 53906 bytes docs/diagrams/StorageUpdatePairSD.jpg | Bin 0 -> 31516 bytes docs/diagrams/StorageUpdatePropertySD.jpg | Bin 0 -> 31951 bytes 9 files changed, 76 insertions(+) create mode 100644 docs/diagrams/LoadFileFlowChart.jpg create mode 100644 docs/diagrams/StorageAddClientSequenceDiagram.jpg create mode 100644 docs/diagrams/StorageAddPairSequenceDiagram.jpg create mode 100644 docs/diagrams/StorageAddPropertySequenceDiagram.jpg create mode 100644 docs/diagrams/StorageDesignDiagram.jpg create mode 100644 docs/diagrams/StorageUpdateClientSD.jpg create mode 100644 docs/diagrams/StorageUpdatePairSD.jpg create mode 100644 docs/diagrams/StorageUpdatePropertySD.jpg diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 32a0c03ec..07f2b1d4e 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -56,9 +56,85 @@ ___ ### Property Component ### Model Component ### Storage Component +For `Storage` feature: + +![Storage Design Diagram](diagrams/StorageDesignDiagram.jpg) + +The Storage class is a superclass itself that is not inherit from other class. This class is responsible for managing +three different text file: +- `client.txt` - Stores the client that is in the Client ArrayList. +- `property.txt` - Stores the property that is in the Property ArrayList. +- `pairing.txt` - Stores the relationship between a client and property which is stored in the Pairing hashmap. + + +It has an association with other class which includes: +- CommandAddProperty +- CommandAddClient +- CommandDeleteProperty +- CommandDeleteClient +- CommandPair +- CommandUnpair + +Since the arraylist changes by **adding** and **deleting** operations while hashmap changes by **pair** and **unpair** +operations, the text files will be updated when `add`, `delete`, `pair` or `unpair` is invoked. + ### Common Classes ___ ## Implementation +This section describes the implementation details of the features within Property Rental Manager. + +### Storage +The implementation of Storage class requires consists of different level of operations: + +- Load Files +- Append to File +- Update to File + +#### Load Files: +![Load File Flowchart](diagrams/LoadFileFlowChart.jpg) +At the file loading level, it comprises checks to verify the directory is created. This is done by invoking a method: +`loadFiles(hasDirectory, hasPropertyFile, hasClientFile, hasPairingFile, clientList, propertyList, pairingList)`. +This method would conduct the following operations: +- Create a `data` directory if not already exist. (`hasDirectory` is `false`) +- Load Clients into Client ArrayList if `hasClientFile` is `true`. +- Load Properties into Property ArrayList if `hasPropertyFile` is `true`. +- Load Pairings into Pairing HashMap if `hasPairingFile` is `true`. + +An empty file would not be loaded into the ArrayList and PropertyList as the code is designed to read for `next()`. +An empty file would invoke a `false` in `hasNext()`, thus adding operation would not continue. The overall operation can +be visualised in the flowchart above. + +#### Append To File +When file is appended into the text file, it's being stored in different formats as shown below: + +- Client: `NAME | CONTACT_NUMBER | EMAIL | BUDGET` +- Property: `NAME | ADDRESS | RENTAL_PRICE | UNIT_TYPE` +- Pairing: `[CLIENT_FORMAT] : [PROPERTY_FORMAT]` + +The text file of which Client, Property and Pairing is being stored is `client.txt`, `property.txt` and `pairing.txt` +respectively. + +![Add Client to Storage Diagram](diagrams/StorageAddClientSequenceDiagram.jpg) +![Add Property to Storage Diagram](diagrams/StorageAddPropertySequenceDiagram.jpg) +![Add Pair to Storage Diagram](diagrams/StorageAddPairSequenceDiagram.jpg) + +The three sequence diagram above shows the sequence of which the append operation is being invoked. All three +operations are similar in operations but are invoked with different `parameter` and `path`. + +### Update To File +The update operation happens when entries in ClientList and PropertyList is being deleted and entries the hash map of +PairingList is being removed. + +The sequence diagram of `updateClient`, `updateProperty` and `updatePair` can be seen below: +![Update Client Sequence Diagram](diagrams/StorageUpdateClientSD.jpg) +![Update Property Sequence Diagram](diagrams/StorageUpdatePropertySD.jpg) +![Update Pairing Sequence Diagram](diagrams/StorageUpdatePairSD.jpg) + +Note that when delete operation is being invoked on client and property, the `updatePair` method will also be invoked to +prevent entries retaining within pairingList after it has been deleted from clientList or propertyList. + + + ___ ## Documentation, logging, testing, configuration and dev-ops ___ diff --git a/docs/diagrams/LoadFileFlowChart.jpg b/docs/diagrams/LoadFileFlowChart.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3202b1947add73965aad7bd86545fa9c39eaa4de GIT binary patch literal 60244 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
P>HbkFg?(vL{+)XB_iAlbGC3Vnlo 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 ADF6Tf literal 0 HcmV?d00001 diff --git a/docs/diagrams/StorageAddPairSequenceDiagram.jpg b/docs/diagrams/StorageAddPairSequenceDiagram.jpg new file mode 100644 index 0000000000000000000000000000000000000000..199d801a142a707e413cdebfeb4366a916f5ccb9 GIT binary patch literal 47426 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