From b011c5897b3ad5d2e16a80f1d6e5f59a0c91c031 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sat, 25 Sep 2021 14:33:10 +0800 Subject: [PATCH 001/756] Set theme jekyll-theme-slate --- docs/_config.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/_config.yml diff --git a/docs/_config.yml b/docs/_config.yml new file mode 100644 index 0000000000..c741881743 --- /dev/null +++ b/docs/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-slate \ No newline at end of file From b9c46336d495a89d00c9a1d68173ab1b15e105b9 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 30 Sep 2021 09:31:34 +0800 Subject: [PATCH 002/756] Update AboutUs.md with personal details --- docs/AboutUs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 0f072953ea..3eab3a7ef2 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) | Marcus Ong | [Github](https://github.com/marcusbory) | [Portfolio](marcusbory.github.io/) ![](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 9f3f29f66388f64274b8225b958ecd99f285d820 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Thu, 30 Sep 2021 09:33:32 +0800 Subject: [PATCH 003/756] Update AboutUs --- docs/AboutUs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 0f072953ea..feb3a0c1da 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -3,7 +3,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) | Don Joe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Andre | [Github](https://github.com/ng-andre) | [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 a427970ce489fba8a12c6129780cebaec2e435e3 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Thu, 30 Sep 2021 09:33:41 +0800 Subject: [PATCH 004/756] Add details for Ashraf in AboutUs.md --- docs/AboutUs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 0f072953ea..3493d814fa 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -6,4 +6,4 @@ Display | Name | Github Profile | Portfolio ![](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) +![Ashraf](https://via.placeholder.com/100.png?text=Photo) | Ashraf| [Github](https://github.com/ashrafjfr) | [Portfolio](docs/team/johndoe.md) From 999da03711bb64a0fe05d9f80bc853450168ad55 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Thu, 30 Sep 2021 09:35:51 +0800 Subject: [PATCH 005/756] Update AboutUs --- docs/AboutUs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 0f072953ea..b02b2ca346 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -5,5 +5,5 @@ 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) | 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) | Mayank Panjiyara | [Github](https://github.com/mayankp291) | [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 2bf5fe9ca10989e22cf418d547016b53d2dcb44f Mon Sep 17 00:00:00 2001 From: lezong Date: Thu, 30 Sep 2021 09:36:07 +0800 Subject: [PATCH 006/756] Add details to docs/AboutUs.md --- docs/AboutUs.md | 2 +- src/main/java/seedu/duke/Duke.class | Bin 0 -> 1234 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 src/main/java/seedu/duke/Duke.class diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 0f072953ea..8a117c03ed 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -4,6 +4,6 @@ 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) | 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) | Mun Le Zong | [Github](https://github.com/lezongmun) | [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) diff --git a/src/main/java/seedu/duke/Duke.class b/src/main/java/seedu/duke/Duke.class new file mode 100644 index 0000000000000000000000000000000000000000..db6bd33b650dae70e17766b13dca23169359d65c GIT binary patch literal 1234 zcmaJ=>rN9v6#k}Mwp~|><&J_20+x%c;03jKqlQ3I)TBgWByNUwgoW*H)14(Y>4W$h z@&gh~d;lNHc&1xz8yaV_XU=}-GUqnGeqa6su!apC*D)N&NCKl6OA$7qV-mOHFf~jm za9W3kJBrMtz%Zd-gU=w(nU+#ha9t~+rnyd5wx!pUZ_C`b?IoK;`!;cQP1le%FpmX>{te%k zfvoWIj*v%wF-Z1eF^(kz_pq$NGH@R&45_^%E=?yetCWiA@sfDSaHF1WC>__z7r5t% zih)%;P2=kEs1y z+$*{wn28KCR|9H6+6;HAWzj*s^+iOz&a`IPaFOM%n|GwhXn4&qdnLb4u`x{kUk_6- z=;f;wqgPFDjcC7m{&X@rdloLhz7s=}Otd!wkw6Lq#4FX$=%Nj*ree7>bS++@8#qS~ z@u^-qe?a?qhWG^%I|MDAL%+nex<=FQIC%zi@{^?9j}h`eO*gDykg!3L#V~~DbsdHb UUSb_%7^nX}lH8<7Zq@1RAL&atpa1{> literal 0 HcmV?d00001 From 346fd2f4d55c37b1eb8ee283a0c1c13df542d792 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Tue, 5 Oct 2021 22:58:20 +0800 Subject: [PATCH 007/756] Replace Duke logo with ConTech logo --- src/main/java/seedu/duke/Duke.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 5c74e68d59..5e4d1e7500 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -7,11 +7,14 @@ public class Duke { * Main entry-point for the java.duke.Duke application. */ public static void main(String[] args) { - String logo = " ____ _ \n" - + "| _ \\ _ _| | _____ \n" - + "| | | | | | | |/ / _ \\\n" - + "| |_| | |_| | < __/\n" - + "|____/ \\__,_|_|\\_\\___|\n"; + String logo = " _____ _______ _ \n" + + " / ____| |__ __| | | \n" + + " | | ___ _ __ | | ___ ___| |__ \n" + + " | | / _ \\| '_ \\| |/ _ \\/ __| '_ \\ \n" + + " | |___| (_) | | | | | __/ (__| | | |\n" + + " \\_____\\___/|_| |_|_|\\___|\\___|_| |_|\n" + + " \n" + + " "; System.out.println("Hello from\n" + logo); System.out.println("What is your name?"); From 14cf9976b1a214ff6f0a87b9211624eef2520d9f Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Tue, 5 Oct 2021 23:49:30 +0800 Subject: [PATCH 008/756] Implement TextUi class to take over initial message printing --- src/main/java/seedu/duke/Duke.java | 22 +++++++++------------- src/main/java/seedu/ui/TextUi.java | 30 ++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 13 deletions(-) create mode 100644 src/main/java/seedu/ui/TextUi.java diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 5e4d1e7500..75556c1b5f 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -1,24 +1,20 @@ package seedu.duke; +import seedu.ui.TextUi; + import java.util.Scanner; public class Duke { + private TextUi textUi; + + public Duke() { + this.textUi = new TextUi(); + } + /** * Main entry-point for the java.duke.Duke application. */ public static void main(String[] args) { - String logo = " _____ _______ _ \n" + - " / ____| |__ __| | | \n" + - " | | ___ _ __ | | ___ ___| |__ \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(); } } diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java new file mode 100644 index 0000000000..3b4aef3094 --- /dev/null +++ b/src/main/java/seedu/ui/TextUi.java @@ -0,0 +1,30 @@ +package seedu.ui; + +import java.util.Scanner; + +public class TextUi { + private static final String LOGO = + " _____ _______ _ \n" + + " / ____| |__ __| | | \n" + + " | | ___ _ __ | | ___ ___| |__ \n" + + " | | / _ \\| '_ \\| |/ _ \\/ __| '_ \\ \n" + + " | |___| (_) | | | | | __/ (__| | | |\n" + + " \\_____\\___/|_| |_|_|\\___|\\___|_| |_|\n" + + " \n"; + + private static final String LINE = + "____________________________________________________________\n"; + + private final Scanner scanner; + + public TextUi() { + scanner = new Scanner(System.in); + initMessage(); + } + + private static void initMessage() { + System.out.println(LINE + LOGO + LINE); + System.out.println("Welcome to ConTech, your personal contact tracker.\n" + LINE); + } + +} From f82af9974aa56e037dd6b1546ea75dc59bba9851 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 00:12:54 +0800 Subject: [PATCH 009/756] Create FileErrorException for Storage related exceptions --- src/main/java/seedu/exception/FileErrorException.java | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/main/java/seedu/exception/FileErrorException.java diff --git a/src/main/java/seedu/exception/FileErrorException.java b/src/main/java/seedu/exception/FileErrorException.java new file mode 100644 index 0000000000..b2dce59bb6 --- /dev/null +++ b/src/main/java/seedu/exception/FileErrorException.java @@ -0,0 +1,4 @@ +package seedu.exception; + +public class FileErrorException extends Exception { +} From e90158cf8027a4575f0e3827e5851ca4084874d6 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 00:13:31 +0800 Subject: [PATCH 010/756] Create two types of message templates, one with single line (bottom), one with double line --- src/main/java/seedu/ui/TextUi.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 3b4aef3094..e4c6bb06d8 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -22,6 +22,18 @@ public TextUi() { initMessage(); } + private static void printDoubleLineMessage(String message) { + System.out.println( + LINE + message + "\n" + LINE + ); + } + + private static void printBottomLineMessage(String message) { + System.out.println( + message + "\n" + LINE + ); + } + private static void initMessage() { System.out.println(LINE + LOGO + LINE); System.out.println("Welcome to ConTech, your personal contact tracker.\n" + LINE); From a68d70d2df1129dfb0d61d2483a89eb48ef771e7 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 01:00:06 +0800 Subject: [PATCH 011/756] Introduce DetailType to enumerate indexes for contact details --- src/main/java/seedu/contact/DetailType.java | 26 +++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 src/main/java/seedu/contact/DetailType.java diff --git a/src/main/java/seedu/contact/DetailType.java b/src/main/java/seedu/contact/DetailType.java new file mode 100644 index 0000000000..87e0c5a858 --- /dev/null +++ b/src/main/java/seedu/contact/DetailType.java @@ -0,0 +1,26 @@ +package seedu.contact; + +/** + * Enumeration for Contact Detail Type. + * This is used for decoding contacts from CSV. The indexes of CSV file lines + * upon splitting will be stored here. + * Eg. ANDRE, ng-andre => upon splitting becomes ["ANDRE", "ng-andre"] + */ +public enum DetailType { + NAME (0), + GITHUB (1), + LINKEDIN (2), + TELEGRAM (3), + TWITTER (4), + EMAIL (5); + + private int index; + + private DetailType(int index) { + this.index = index; + } + + public int getIndex() { + return index; + } +} From 831cea74183d6ef71b7ee7a69bffc85546ad6c3f Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 01:00:42 +0800 Subject: [PATCH 012/756] Create basic Contact and ContactList for first iteration/foundation --- src/main/java/seedu/contact/Contact.java | 27 ++++++++++++++++++++ src/main/java/seedu/contact/ContactList.java | 15 +++++++++++ 2 files changed, 42 insertions(+) create mode 100644 src/main/java/seedu/contact/Contact.java create mode 100644 src/main/java/seedu/contact/ContactList.java diff --git a/src/main/java/seedu/contact/Contact.java b/src/main/java/seedu/contact/Contact.java new file mode 100644 index 0000000000..072f1920b2 --- /dev/null +++ b/src/main/java/seedu/contact/Contact.java @@ -0,0 +1,27 @@ +package seedu.contact; + +public class Contact { + private String name; + private String github; + + public Contact(String name, String github) { + this.name = name; + this.github = github; + } + + public String getName() { + return name; + } + + public String getGithub() { + return github; + } + + public void setName(String name) { + this.name = name; + } + + public void setGithub(String github) { + this.github = github; + } +} diff --git a/src/main/java/seedu/contact/ContactList.java b/src/main/java/seedu/contact/ContactList.java new file mode 100644 index 0000000000..3b7d9e5a35 --- /dev/null +++ b/src/main/java/seedu/contact/ContactList.java @@ -0,0 +1,15 @@ +package seedu.contact; + +import java.util.ArrayList; + +public class ContactList { + private ArrayList contacts; + + public ContactList() { + this.contacts = new ArrayList<>(); + } + + public void addContact(Contact contact) { + contacts.add(contact); + } +} From 272aeae3d5ac036fbc2b114ac3e79823eff9a587 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 01:05:58 +0800 Subject: [PATCH 013/756] Update initMessage in TextUi --- src/main/java/seedu/ui/TextUi.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index e4c6bb06d8..3c48b3ee78 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -35,7 +35,7 @@ private static void printBottomLineMessage(String message) { } private static void initMessage() { - System.out.println(LINE + LOGO + LINE); + printDoubleLineMessage(LOGO); System.out.println("Welcome to ConTech, your personal contact tracker.\n" + LINE); } From 3a2f5d7bea3c90ab7538a46664ca86d251c8ff34 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 01:06:25 +0800 Subject: [PATCH 014/756] Implement messages for creation of new save files and file error messages --- src/main/java/seedu/ui/TextUi.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 3c48b3ee78..f51148f11f 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -39,4 +39,16 @@ private static void initMessage() { System.out.println("Welcome to ConTech, your personal contact tracker.\n" + LINE); } + public static void createNewContactFileMessage(String contactFilePath) { + String message = "As ConTech is unable to find your saved data, \n" + + " it has created a new one for you at: \n" + contactFilePath; + printBottomLineMessage(message); + } + + public static void fileErrorMessage(String contactFilePath) { + String message = "ConTech is unfortunately unable to create a file for your\n" + + " save file at " + contactFilePath + ".\n" + + "Please relocate the file and try again."; + printBottomLineMessage(message); + } } From 5dd52de38d4e4db44f75c413bddca4803451b473 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 01:07:37 +0800 Subject: [PATCH 015/756] Implement basic local storage feature --- src/main/java/seedu/storage/Storage.java | 41 ++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 src/main/java/seedu/storage/Storage.java diff --git a/src/main/java/seedu/storage/Storage.java b/src/main/java/seedu/storage/Storage.java new file mode 100644 index 0000000000..f194550baf --- /dev/null +++ b/src/main/java/seedu/storage/Storage.java @@ -0,0 +1,41 @@ +package seedu.storage; + +import seedu.contact.ContactList; +import seedu.exception.FileErrorException; +import seedu.ui.TextUi; + +import java.io.File; +import java.io.IOException; + +public class Storage { + private final String contactFilePath; + private final File contactFile; + public static final String SEPARATOR = ","; + + public Storage(String contactFilePath) { + this.contactFilePath = contactFilePath; + this.contactFile = new File(contactFilePath); + } + + private boolean hasExistingContactFile() throws FileErrorException { + try { + if (!contactFile.exists()) { + contactFile.getParentFile().mkdirs(); + } + if (contactFile.createNewFile()) { + TextUi.createNewContactFileMessage(contactFilePath); + return false; + } + } catch (IOException e) { + throw new FileErrorException(); + } + return true; + } + + public ContactList loadExistingContacts() throws FileErrorException { + if (!hasExistingContactFile()) { + return new ContactList(); + } + return ContactsDecoder.readContacts(contactFile); + } +} From e5e038da8c220dd25276173ad9f64733330562cd Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 01:08:11 +0800 Subject: [PATCH 016/756] Implement method calls to test Storage unit --- src/main/java/seedu/duke/Duke.java | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 75556c1b5f..30fe9acc75 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -1,20 +1,31 @@ package seedu.duke; +import seedu.contact.ContactList; +import seedu.exception.FileErrorException; +import seedu.storage.Storage; import seedu.ui.TextUi; -import java.util.Scanner; - public class Duke { private TextUi textUi; + private String contactFilePath; + private Storage storage; + private ContactList contactList; - public Duke() { + public Duke(String contactFilePath) { this.textUi = new TextUi(); + this.contactFilePath = contactFilePath; + this.storage = new Storage(contactFilePath); + try { + this.contactList = storage.loadExistingContacts(); + } catch (FileErrorException e) { + TextUi.fileErrorMessage(this.contactFilePath); + } } /** * Main entry-point for the java.duke.Duke application. */ public static void main(String[] args) { - new Duke(); + new Duke("data/contacts.txt"); } } From 4d77838737c64c46e510f8bbede7a60db1befff3 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 01:12:19 +0800 Subject: [PATCH 017/756] Implement ContactDecoder to decode contacts from CSV txt, not yet tested --- .../java/seedu/storage/ContactsDecoder.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 src/main/java/seedu/storage/ContactsDecoder.java diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java new file mode 100644 index 0000000000..dcb692ac91 --- /dev/null +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -0,0 +1,35 @@ +package seedu.storage; + +import seedu.contact.Contact; +import seedu.contact.ContactList; +import seedu.contact.DetailType; +import seedu.exception.FileErrorException; +import static seedu.storage.Storage.SEPARATOR; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.Scanner; + +public class ContactsDecoder { + public static ContactList readContacts(File contactFile) throws FileErrorException { + ContactList updatedContactList = new ContactList(); + try { + Scanner fileScanner = new Scanner(contactFile); + while (fileScanner.hasNext()) { + String contactText = fileScanner.nextLine(); + decodeContacts(updatedContactList, contactText); + } + } catch (FileNotFoundException e) { + throw new FileErrorException(); + } + return updatedContactList; + } + + private static void decodeContacts(ContactList contactList, String contactText) { + String[] destructuredInputs = contactText.split(SEPARATOR); + String contactName = destructuredInputs[DetailType.NAME.getIndex()]; + String contactGithub = destructuredInputs[DetailType.GITHUB.getIndex()]; + // Add more later + contactList.addContact(new Contact(contactName, contactGithub)); + } +} From 4e210fa0f303f3fd670e6bf1ff40eb74cae87091 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 01:31:48 +0800 Subject: [PATCH 018/756] Implement getListSize for ContactList class --- src/main/java/seedu/contact/ContactList.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/seedu/contact/ContactList.java b/src/main/java/seedu/contact/ContactList.java index 3b7d9e5a35..bc6718980e 100644 --- a/src/main/java/seedu/contact/ContactList.java +++ b/src/main/java/seedu/contact/ContactList.java @@ -12,4 +12,8 @@ public ContactList() { public void addContact(Contact contact) { contacts.add(contact); } + + public int getListSize() { + return contacts.size(); + } } From db3522395d3fa1ec33a64b29e539b57d80439f62 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 01:32:14 +0800 Subject: [PATCH 019/756] Add comments specifying usage of single vs double line message templates --- src/main/java/seedu/ui/TextUi.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index f51148f11f..a42d87770b 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -22,12 +22,14 @@ public TextUi() { initMessage(); } + // Used for print messages after user inputs private static void printDoubleLineMessage(String message) { System.out.println( LINE + message + "\n" + LINE ); } + // Used for system messages without user inputs private static void printBottomLineMessage(String message) { System.out.println( message + "\n" + LINE From d3e0784fb6959c8da0a1defc43854e718c488d80 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 01:32:29 +0800 Subject: [PATCH 020/756] Add exit and add contact messages --- src/main/java/seedu/ui/TextUi.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index a42d87770b..d9b3398de1 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -53,4 +53,16 @@ public static void fileErrorMessage(String contactFilePath) { "Please relocate the file and try again."; printBottomLineMessage(message); } + + public static void addContactMessage(String contactName, int listSize) { + String message = "ConTech has added the specified contact: " + contactName + "\n" + + "You now have " + listSize + " contact(s)."; + printDoubleLineMessage(message); + } + + public static void exitMessage() { + String message = "ConTech will now shutdown.\n" + + "We hope you have enjoyed using it."; + printDoubleLineMessage(message); + } } From 016ed7983a4801865ee10c3c4f8c9626d1d85778 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 01:32:44 +0800 Subject: [PATCH 021/756] Implement abstract Command class for command creation --- src/main/java/seedu/command/Command.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/main/java/seedu/command/Command.java diff --git a/src/main/java/seedu/command/Command.java b/src/main/java/seedu/command/Command.java new file mode 100644 index 0000000000..c9c6808d4b --- /dev/null +++ b/src/main/java/seedu/command/Command.java @@ -0,0 +1,17 @@ +package seedu.command; + +import seedu.contact.ContactList; + +public abstract class Command { + protected ContactList contactList; + + public void setContactList(ContactList contactList) { + this.contactList = contactList; + } + + public abstract void execute(); + + public boolean isExit() { + return this instanceof ExitCommand; + } +} From 1ef76ddaeed92357e3f3dc12410e2313cdf46f01 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 01:32:54 +0800 Subject: [PATCH 022/756] Implement exit command for app --- src/main/java/seedu/command/ExitCommand.java | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/main/java/seedu/command/ExitCommand.java diff --git a/src/main/java/seedu/command/ExitCommand.java b/src/main/java/seedu/command/ExitCommand.java new file mode 100644 index 0000000000..dfa532b433 --- /dev/null +++ b/src/main/java/seedu/command/ExitCommand.java @@ -0,0 +1,9 @@ +package seedu.command; + +import seedu.ui.TextUi; + +public class ExitCommand extends Command { + public void execute() { + TextUi.exitMessage(); + } +} From 0cf1a91e030089536910ab4d72e68f560da937b6 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 01:33:40 +0800 Subject: [PATCH 023/756] Implement Add command for adding contacts --- .../java/seedu/command/AddContactCommand.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/main/java/seedu/command/AddContactCommand.java diff --git a/src/main/java/seedu/command/AddContactCommand.java b/src/main/java/seedu/command/AddContactCommand.java new file mode 100644 index 0000000000..593dc6262e --- /dev/null +++ b/src/main/java/seedu/command/AddContactCommand.java @@ -0,0 +1,20 @@ +package seedu.command; + +import seedu.contact.Contact; +import seedu.ui.TextUi; + +public class AddContactCommand extends Command { + private final String name; + private final String github; + + public AddContactCommand(String name, String github) { + this.name = name; + this.github = github; + } + + public void execute() { + Contact addedContact = new Contact(name, github); + contactList.addContact(addedContact); + TextUi.addContactMessage(name, contactList.getListSize()); + } +} From a1394cb84c352d30f1b02374d9a964f9f38dbb99 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 01:41:22 +0800 Subject: [PATCH 024/756] Remove redundant access modifier from Enum Constructor --- src/main/java/seedu/contact/DetailType.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/contact/DetailType.java b/src/main/java/seedu/contact/DetailType.java index 87e0c5a858..8d82c53b34 100644 --- a/src/main/java/seedu/contact/DetailType.java +++ b/src/main/java/seedu/contact/DetailType.java @@ -16,7 +16,7 @@ public enum DetailType { private int index; - private DetailType(int index) { + DetailType(int index) { this.index = index; } From 965bcd1c09b9fdcef92bb1af3e799a688592c011 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 02:42:57 +0800 Subject: [PATCH 025/756] Implement FailedCommand and FailedCommandType (enum) --- .../java/seedu/command/FailedCommand.java | 22 +++++++++++++++++++ .../java/seedu/parser/FailedCommandType.java | 5 +++++ 2 files changed, 27 insertions(+) create mode 100644 src/main/java/seedu/command/FailedCommand.java create mode 100644 src/main/java/seedu/parser/FailedCommandType.java diff --git a/src/main/java/seedu/command/FailedCommand.java b/src/main/java/seedu/command/FailedCommand.java new file mode 100644 index 0000000000..9e0bc7a97f --- /dev/null +++ b/src/main/java/seedu/command/FailedCommand.java @@ -0,0 +1,22 @@ +package seedu.command; + +import seedu.parser.FailedCommandType; +import seedu.ui.TextUi; + +public class FailedCommand extends Command { + private FailedCommandType type; + + public FailedCommand(FailedCommandType type) { + this.type = type; + } + + public void execute() { + switch (type) { + case GENERAL: + TextUi.invalidCommandMessage(); + break; + default: + return; + } + } +} diff --git a/src/main/java/seedu/parser/FailedCommandType.java b/src/main/java/seedu/parser/FailedCommandType.java new file mode 100644 index 0000000000..4de6809d26 --- /dev/null +++ b/src/main/java/seedu/parser/FailedCommandType.java @@ -0,0 +1,5 @@ +package seedu.parser; + +public enum FailedCommandType { + GENERAL +} From f4d6cd049916fc8a522493615d21f44b31045c37 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 02:44:28 +0800 Subject: [PATCH 026/756] Update gitignore to ignore data files --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index f69985ef1f..9c01cdedb7 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,5 @@ bin/ /text-ui-test/ACTUAL.txt text-ui-test/EXPECTED-UNIX.TXT + +/data From f31c654b0d869c187220ecde8e9382f54f2e38fd Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 02:45:00 +0800 Subject: [PATCH 027/756] Implement method for getting contact at an index --- src/main/java/seedu/contact/ContactList.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/seedu/contact/ContactList.java b/src/main/java/seedu/contact/ContactList.java index bc6718980e..6226227743 100644 --- a/src/main/java/seedu/contact/ContactList.java +++ b/src/main/java/seedu/contact/ContactList.java @@ -13,6 +13,10 @@ public void addContact(Contact contact) { contacts.add(contact); } + public Contact getContactAtIndex(int index) { + return contacts.get(index); + } + public int getListSize() { return contacts.size(); } From b378983d58d0740956a7e410b2dfc8bf1536f6c8 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 02:45:39 +0800 Subject: [PATCH 028/756] Implement contacts encoder for saving --- .../java/seedu/storage/ContactsEncoder.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/main/java/seedu/storage/ContactsEncoder.java diff --git a/src/main/java/seedu/storage/ContactsEncoder.java b/src/main/java/seedu/storage/ContactsEncoder.java new file mode 100644 index 0000000000..8aae5d52a6 --- /dev/null +++ b/src/main/java/seedu/storage/ContactsEncoder.java @@ -0,0 +1,31 @@ +package seedu.storage; + +import seedu.contact.Contact; +import seedu.contact.ContactList; +import seedu.exception.FileErrorException; + +import java.io.FileWriter; +import java.io.IOException; + +import static seedu.storage.Storage.SEPARATOR; + +public class ContactsEncoder { + public static void saveContacts(String contactFilePath, ContactList contactList) throws FileErrorException { + try { + FileWriter fileWriter = new FileWriter(contactFilePath); + for (int i = 0; i < contactList.getListSize(); i++) { + Contact currentContact = contactList.getContactAtIndex(i); + String encodedContact = encodeContact(currentContact); + fileWriter.write(encodedContact); + } + fileWriter.close(); + } catch (IOException e) { + throw new FileErrorException(); + } + } + + private static String encodeContact(Contact contact) { + String stringifiedContact = contact.getName() + SEPARATOR + contact.getGithub(); + return stringifiedContact; + } +} From 3106e96409bb00bd63abde6a4612558ea56b40fd Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 02:45:55 +0800 Subject: [PATCH 029/756] Implement parser to parse input into commands --- src/main/java/seedu/parser/Parser.java | 54 ++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 src/main/java/seedu/parser/Parser.java diff --git a/src/main/java/seedu/parser/Parser.java b/src/main/java/seedu/parser/Parser.java new file mode 100644 index 0000000000..cef802744f --- /dev/null +++ b/src/main/java/seedu/parser/Parser.java @@ -0,0 +1,54 @@ +package seedu.parser; + +import seedu.command.AddContactCommand; +import seedu.command.Command; +import seedu.command.ExitCommand; +import seedu.command.FailedCommand; + +public class Parser { + private final String ADD_TASK_COMMAND = "add"; + private final String EXIT_COMMAND = "exit"; + + private final int COMMAND_WORD_INDEX = 0; + private final int ISOLATE_COMMAND_WORD = 2; + private final int CONTACT_PARAMS = 1; + + private final String NAME_TAG = " n/"; + private final String GITHUB_TAG = " g/"; + + public Command parseCommand(String userInput) { + String commandType = getCommandWord(userInput); + Command command; + switch (commandType) { + case ADD_TASK_COMMAND: + command = parseAddContact(userInput); + break; + case EXIT_COMMAND: + command = new ExitCommand(); + break; + default: + command = new FailedCommand(FailedCommandType.GENERAL); + } + return command; + } + + public String getCommandWord(String userInput) { + String[] destructuredInputs = userInput.split(" ", ISOLATE_COMMAND_WORD); + return destructuredInputs[COMMAND_WORD_INDEX]; + } + + // Scuffed version + private Command parseAddContact(String userInput) { + String[] destructuredInputs = userInput.split(" ", ISOLATE_COMMAND_WORD); + String contact = destructuredInputs[1]; + String name = contact.substring(contact.indexOf(NAME_TAG) + 3, contact.indexOf(GITHUB_TAG)); + String github = contact.substring(contact.indexOf(GITHUB_TAG) + 3); + return new AddContactCommand(name, github); + } + + + // Will create a function to parse details soon, hardcoding for V0.1 (7/10/21 version) +// private String parseDetail(String contactParameters, String tag) { +// +// } +} From b228b5a9cce4ed272a4dadef9ea83d6cbc2897cb Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 02:46:21 +0800 Subject: [PATCH 030/756] Implement user input from TextUi --- src/main/java/seedu/ui/TextUi.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index d9b3398de1..69ad234ff7 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -22,6 +22,10 @@ public TextUi() { initMessage(); } + public String getUserInput() { + return scanner.nextLine(); + } + // Used for print messages after user inputs private static void printDoubleLineMessage(String message) { System.out.println( From 1d86ff9b8fb2722137203b9c7fee1d3532fb28d9 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 02:47:41 +0800 Subject: [PATCH 031/756] Implement new messages for file errors and invalid commands --- src/main/java/seedu/ui/TextUi.java | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 69ad234ff7..6980e491c7 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -51,13 +51,6 @@ public static void createNewContactFileMessage(String contactFilePath) { printBottomLineMessage(message); } - public static void fileErrorMessage(String contactFilePath) { - String message = "ConTech is unfortunately unable to create a file for your\n" + - " save file at " + contactFilePath + ".\n" + - "Please relocate the file and try again."; - printBottomLineMessage(message); - } - public static void addContactMessage(String contactName, int listSize) { String message = "ConTech has added the specified contact: " + contactName + "\n" + "You now have " + listSize + " contact(s)."; @@ -69,4 +62,18 @@ public static void exitMessage() { "We hope you have enjoyed using it."; printDoubleLineMessage(message); } + + // Error Messages + public static void fileErrorMessage(String contactFilePath) { + String message = "ConTech is unfortunately unable to access / create a\n" + + " save file at " + contactFilePath + ".\n" + + "Please relocate the file and try again."; + printBottomLineMessage(message); + } + + public static void invalidCommandMessage() { + String message = "ConTech is unable to understand your request.\n" + + "Please try again with a valid command."; + printDoubleLineMessage(message); + } } From c05585e02ae94561a4f7b0e2d961a5bb76204485 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 02:48:05 +0800 Subject: [PATCH 032/756] Introduce parser into main to implement add contact --- src/main/java/seedu/duke/Duke.java | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 30fe9acc75..f154ebaea0 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -1,7 +1,10 @@ package seedu.duke; +import seedu.command.Command; import seedu.contact.ContactList; import seedu.exception.FileErrorException; +import seedu.parser.Parser; +import seedu.storage.ContactsEncoder; import seedu.storage.Storage; import seedu.ui.TextUi; @@ -9,12 +12,14 @@ public class Duke { private TextUi textUi; private String contactFilePath; private Storage storage; + private Parser parser; private ContactList contactList; public Duke(String contactFilePath) { this.textUi = new TextUi(); this.contactFilePath = contactFilePath; this.storage = new Storage(contactFilePath); + this.parser = new Parser(); try { this.contactList = storage.loadExistingContacts(); } catch (FileErrorException e) { @@ -22,10 +27,29 @@ public Duke(String contactFilePath) { } } + private void runConTech() { + Command command; + do { + String userInput = textUi.getUserInput(); + command = parser.parseCommand(userInput); + runCommandProcedure(command); + } while (!command.isExit()); + } + + private void runCommandProcedure(Command command) { + try { + command.setContactList(contactList); + command.execute(); + ContactsEncoder.saveContacts(contactFilePath, contactList); + } catch (FileErrorException e) { + TextUi.fileErrorMessage(contactFilePath); + } + } + /** * Main entry-point for the java.duke.Duke application. */ public static void main(String[] args) { - new Duke("data/contacts.txt"); + new Duke("data/contacts.txt").runConTech(); } } From 616976bf33c3331790db383ae6e39132035a4adb Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 10:48:24 +0800 Subject: [PATCH 033/756] Update gitignore to exclude data files for IO redirection tests --- .gitignore | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 9c01cdedb7..4ae120efc6 100644 --- a/.gitignore +++ b/.gitignore @@ -13,7 +13,7 @@ src/main/resources/docs/ *.iml bin/ -/text-ui-test/ACTUAL.txt -text-ui-test/EXPECTED-UNIX.TXT /data +# ensure that no existing data exists on remote, so that runtest.sh is always on fresh build +/text-ui-test/data/ From 6d3461284a837e26ed36e40ab26cfd00d1518869 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 10:48:52 +0800 Subject: [PATCH 034/756] Update IO redirection test inputs and outputs --- text-ui-test/ACTUAL.TXT | 29 ++++++++++++++++++++++++++ text-ui-test/EXPECTED-UNIX.TXT | 29 ++++++++++++++++++++++++++ text-ui-test/EXPECTED.TXT | 38 ++++++++++++++++++++++++++-------- text-ui-test/input.txt | 3 ++- 4 files changed, 89 insertions(+), 10 deletions(-) create mode 100644 text-ui-test/ACTUAL.TXT create mode 100644 text-ui-test/EXPECTED-UNIX.TXT diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT new file mode 100644 index 0000000000..4fed95bc32 --- /dev/null +++ b/text-ui-test/ACTUAL.TXT @@ -0,0 +1,29 @@ +____________________________________________________________ + _____ _______ _ + / ____| |__ __| | | + | | ___ _ __ | | ___ ___| |__ + | | / _ \| '_ \| |/ _ \/ __| '_ \ + | |___| (_) | | | | | __/ (__| | | | + \_____\___/|_| |_|_|\___|\___|_| |_| + + +____________________________________________________________ + +Welcome to ConTech, your personal contact tracker. +____________________________________________________________ + +As ConTech is unable to find your saved data, + it has created a new one for you at: +data/contacts.txt +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: andre +You now have 1 contact(s). +____________________________________________________________ + +____________________________________________________________ +ConTech will now shutdown. +We hope you have enjoyed using it. +____________________________________________________________ + diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT new file mode 100644 index 0000000000..4fed95bc32 --- /dev/null +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -0,0 +1,29 @@ +____________________________________________________________ + _____ _______ _ + / ____| |__ __| | | + | | ___ _ __ | | ___ ___| |__ + | | / _ \| '_ \| |/ _ \/ __| '_ \ + | |___| (_) | | | | | __/ (__| | | | + \_____\___/|_| |_|_|\___|\___|_| |_| + + +____________________________________________________________ + +Welcome to ConTech, your personal contact tracker. +____________________________________________________________ + +As ConTech is unable to find your saved data, + it has created a new one for you at: +data/contacts.txt +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: andre +You now have 1 contact(s). +____________________________________________________________ + +____________________________________________________________ +ConTech will now shutdown. +We hope you have enjoyed using it. +____________________________________________________________ + diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 892cb6cae7..4fed95bc32 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,9 +1,29 @@ -Hello from - ____ _ -| _ \ _ _| | _____ -| | | | | | | |/ / _ \ -| |_| | |_| | < __/ -|____/ \__,_|_|\_\___| - -What is your name? -Hello James Gosling +____________________________________________________________ + _____ _______ _ + / ____| |__ __| | | + | | ___ _ __ | | ___ ___| |__ + | | / _ \| '_ \| |/ _ \/ __| '_ \ + | |___| (_) | | | | | __/ (__| | | | + \_____\___/|_| |_|_|\___|\___|_| |_| + + +____________________________________________________________ + +Welcome to ConTech, your personal contact tracker. +____________________________________________________________ + +As ConTech is unable to find your saved data, + it has created a new one for you at: +data/contacts.txt +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: andre +You now have 1 contact(s). +____________________________________________________________ + +____________________________________________________________ +ConTech will now shutdown. +We hope you have enjoyed using it. +____________________________________________________________ + diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index f6ec2e9f95..2258b281ab 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -1 +1,2 @@ -James Gosling \ No newline at end of file +add n/andre g/ng-andre +exit \ No newline at end of file From b0c8d0049de3eb57aed0e54685824e732faf961a Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 10:54:56 +0800 Subject: [PATCH 035/756] Added line separator for encoding tasks --- src/main/java/seedu/storage/ContactsEncoder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/storage/ContactsEncoder.java b/src/main/java/seedu/storage/ContactsEncoder.java index 8aae5d52a6..1a6f76e694 100644 --- a/src/main/java/seedu/storage/ContactsEncoder.java +++ b/src/main/java/seedu/storage/ContactsEncoder.java @@ -25,7 +25,7 @@ public static void saveContacts(String contactFilePath, ContactList contactList) } private static String encodeContact(Contact contact) { - String stringifiedContact = contact.getName() + SEPARATOR + contact.getGithub(); + String stringifiedContact = contact.getName() + SEPARATOR + contact.getGithub() + "\n"; return stringifiedContact; } } From c5c7491b8952eb75e1b7f9e503f25d84b8ba8857 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 11:08:56 +0800 Subject: [PATCH 036/756] Fix CheckStyle problems to become compliant --- src/main/java/seedu/contact/DetailType.java | 12 +++---- src/main/java/seedu/parser/Parser.java | 30 ++++++++--------- src/main/java/seedu/ui/TextUi.java | 36 ++++++++++----------- 3 files changed, 39 insertions(+), 39 deletions(-) diff --git a/src/main/java/seedu/contact/DetailType.java b/src/main/java/seedu/contact/DetailType.java index 8d82c53b34..4da0277c55 100644 --- a/src/main/java/seedu/contact/DetailType.java +++ b/src/main/java/seedu/contact/DetailType.java @@ -7,12 +7,12 @@ * Eg. ANDRE, ng-andre => upon splitting becomes ["ANDRE", "ng-andre"] */ public enum DetailType { - NAME (0), - GITHUB (1), - LINKEDIN (2), - TELEGRAM (3), - TWITTER (4), - EMAIL (5); + NAME(0), + GITHUB(1), + LINKEDIN(2), + TELEGRAM(3), + TWITTER(4), + EMAIL(5); private int index; diff --git a/src/main/java/seedu/parser/Parser.java b/src/main/java/seedu/parser/Parser.java index cef802744f..a514a25954 100644 --- a/src/main/java/seedu/parser/Parser.java +++ b/src/main/java/seedu/parser/Parser.java @@ -6,24 +6,24 @@ import seedu.command.FailedCommand; public class Parser { - private final String ADD_TASK_COMMAND = "add"; - private final String EXIT_COMMAND = "exit"; + private static final String ADD_TASK_COMD = "add"; + private static final String EXIT_COMD = "exit"; - private final int COMMAND_WORD_INDEX = 0; - private final int ISOLATE_COMMAND_WORD = 2; - private final int CONTACT_PARAMS = 1; + private static final int COMD_WORD_INDEX = 0; + private static final int ISOLATE_COMD_WORD = 2; + private static final int CONTACT_PARAMS = 1; - private final String NAME_TAG = " n/"; - private final String GITHUB_TAG = " g/"; + private static final String NAME_TAG = " n/"; + private static final String GITHUB_TAG = " g/"; public Command parseCommand(String userInput) { String commandType = getCommandWord(userInput); Command command; switch (commandType) { - case ADD_TASK_COMMAND: + case ADD_TASK_COMD: command = parseAddContact(userInput); break; - case EXIT_COMMAND: + case EXIT_COMD: command = new ExitCommand(); break; default: @@ -33,13 +33,13 @@ public Command parseCommand(String userInput) { } public String getCommandWord(String userInput) { - String[] destructuredInputs = userInput.split(" ", ISOLATE_COMMAND_WORD); - return destructuredInputs[COMMAND_WORD_INDEX]; + String[] destructuredInputs = userInput.split(" ", ISOLATE_COMD_WORD); + return destructuredInputs[COMD_WORD_INDEX]; } // Scuffed version private Command parseAddContact(String userInput) { - String[] destructuredInputs = userInput.split(" ", ISOLATE_COMMAND_WORD); + String[] destructuredInputs = userInput.split(" ", ISOLATE_COMD_WORD); String contact = destructuredInputs[1]; String name = contact.substring(contact.indexOf(NAME_TAG) + 3, contact.indexOf(GITHUB_TAG)); String github = contact.substring(contact.indexOf(GITHUB_TAG) + 3); @@ -48,7 +48,7 @@ private Command parseAddContact(String userInput) { // Will create a function to parse details soon, hardcoding for V0.1 (7/10/21 version) -// private String parseDetail(String contactParameters, String tag) { -// -// } + // private String parseDetail(String contactParameters, String tag) { + // + // } } diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 6980e491c7..87eeddd175 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -4,13 +4,13 @@ public class TextUi { private static final String LOGO = - " _____ _______ _ \n" + - " / ____| |__ __| | | \n" + - " | | ___ _ __ | | ___ ___| |__ \n" + - " | | / _ \\| '_ \\| |/ _ \\/ __| '_ \\ \n" + - " | |___| (_) | | | | | __/ (__| | | |\n" + - " \\_____\\___/|_| |_|_|\\___|\\___|_| |_|\n" + - " \n"; + " _____ _______ _ \n" + + " / ____| |__ __| | | \n" + + " | | ___ _ __ | | ___ ___| |__ \n" + + " | | / _ \\| '_ \\| |/ _ \\/ __| '_ \\ \n" + + " | |___| (_) | | | | | __/ (__| | | |\n" + + " \\_____\\___/|_| |_|_|\\___|\\___|_| |_|\n" + + " \n"; private static final String LINE = "____________________________________________________________\n"; @@ -46,34 +46,34 @@ private static void initMessage() { } public static void createNewContactFileMessage(String contactFilePath) { - String message = "As ConTech is unable to find your saved data, \n" + - " it has created a new one for you at: \n" + contactFilePath; + String message = "As ConTech is unable to find your saved data, \n" + + " it has created a new one for you at: \n" + contactFilePath; printBottomLineMessage(message); } public static void addContactMessage(String contactName, int listSize) { - String message = "ConTech has added the specified contact: " + contactName + "\n" + - "You now have " + listSize + " contact(s)."; + String message = "ConTech has added the specified contact: " + contactName + "\n" + + "You now have " + listSize + " contact(s)."; printDoubleLineMessage(message); } public static void exitMessage() { - String message = "ConTech will now shutdown.\n" + - "We hope you have enjoyed using it."; + String message = "ConTech will now shutdown.\n" + + "We hope you have enjoyed using it."; printDoubleLineMessage(message); } // Error Messages public static void fileErrorMessage(String contactFilePath) { - String message = "ConTech is unfortunately unable to access / create a\n" + - " save file at " + contactFilePath + ".\n" + - "Please relocate the file and try again."; + String message = "ConTech is unfortunately unable to access / create a\n" + + " save file at " + contactFilePath + ".\n" + + "Please relocate the file and try again."; printBottomLineMessage(message); } public static void invalidCommandMessage() { - String message = "ConTech is unable to understand your request.\n" + - "Please try again with a valid command."; + String message = "ConTech is unable to understand your request.\n" + + "Please try again with a valid command."; printDoubleLineMessage(message); } } From 297cc907181da1dd89e1def57e436a997c1622f3 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 16:50:37 +0800 Subject: [PATCH 037/756] Rename Parser to MainParser --- .../parser/{Parser.java => MainParser.java} | 28 ++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) rename src/main/java/seedu/parser/{Parser.java => MainParser.java} (59%) diff --git a/src/main/java/seedu/parser/Parser.java b/src/main/java/seedu/parser/MainParser.java similarity index 59% rename from src/main/java/seedu/parser/Parser.java rename to src/main/java/seedu/parser/MainParser.java index a514a25954..b0c12ee3e6 100644 --- a/src/main/java/seedu/parser/Parser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -4,17 +4,18 @@ import seedu.command.Command; import seedu.command.ExitCommand; import seedu.command.FailedCommand; +import seedu.contact.DetailType; +import seedu.exception.InvalidFlagException; -public class Parser { +public class MainParser { private static final String ADD_TASK_COMD = "add"; private static final String EXIT_COMD = "exit"; private static final int COMD_WORD_INDEX = 0; private static final int ISOLATE_COMD_WORD = 2; - private static final int CONTACT_PARAMS = 1; - private static final String NAME_TAG = " n/"; - private static final String GITHUB_TAG = " g/"; + private ContactParser contactParser; + private AddContactParser addContactParser = new AddContactParser(); public Command parseCommand(String userInput) { String commandType = getCommandWord(userInput); @@ -37,18 +38,13 @@ public String getCommandWord(String userInput) { return destructuredInputs[COMD_WORD_INDEX]; } - // Scuffed version private Command parseAddContact(String userInput) { - String[] destructuredInputs = userInput.split(" ", ISOLATE_COMD_WORD); - String contact = destructuredInputs[1]; - String name = contact.substring(contact.indexOf(NAME_TAG) + 3, contact.indexOf(GITHUB_TAG)); - String github = contact.substring(contact.indexOf(GITHUB_TAG) + 3); - return new AddContactCommand(name, github); + contactParser = addContactParser; + try { + String[] details = contactParser.parseContactDetails(userInput); + return new AddContactCommand(details[DetailType.NAME.getIndex()], details[DetailType.GITHUB.getIndex()]); + } catch (InvalidFlagException e) { + return new FailedCommand(FailedCommandType.INVALID_FLAG); + } } - - - // Will create a function to parse details soon, hardcoding for V0.1 (7/10/21 version) - // private String parseDetail(String contactParameters, String tag) { - // - // } } From 5f0ef6ff18ddfef1a30d48cf7935e5eb14583fea Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 16:51:55 +0800 Subject: [PATCH 038/756] Implement abstract class ContactParser for AddContactParser (and EditContactParser) --- src/main/java/seedu/parser/ContactParser.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/main/java/seedu/parser/ContactParser.java diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java new file mode 100644 index 0000000000..496f05b6a0 --- /dev/null +++ b/src/main/java/seedu/parser/ContactParser.java @@ -0,0 +1,18 @@ +package seedu.parser; + +import seedu.exception.InvalidFlagException; + +public abstract class ContactParser { + public static final int CONTACT_PARAMS_START_INDEX = 1; + public static final int NUMBER_OF_DETAILS = 2; + + public static final String DETAIL_SEPARATOR = " -"; + public static final int DETAILS_TO_SPLIT = 2; + public static final int FLAG_INDEX_IN_DETAILS = 0; + public static final int DETAIL_INDEX_IN_DETAILS = 1; + + public static final String NAME_FLAG = "n"; + public static final String GITHUB_FLAG = "g"; + + public abstract String[] parseContactDetails(String userInput) throws InvalidFlagException; +} From aaf1578b059731f74eb6021c1ae3af0ffb9f7ce9 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 16:52:22 +0800 Subject: [PATCH 039/756] Implement AddContactParser to parse user input into contact details to formulate AddCommand --- .../java/seedu/parser/AddContactParser.java | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/main/java/seedu/parser/AddContactParser.java diff --git a/src/main/java/seedu/parser/AddContactParser.java b/src/main/java/seedu/parser/AddContactParser.java new file mode 100644 index 0000000000..ff9d8814f3 --- /dev/null +++ b/src/main/java/seedu/parser/AddContactParser.java @@ -0,0 +1,50 @@ +package seedu.parser; + +import seedu.contact.DetailType; +import seedu.exception.InvalidFlagException; + +public class AddContactParser extends ContactParser { + /** + * This method returns a String[] containing the user's input and the arguments specified for + * each detail flag. Each detail is parsed individually using parseDetail. + * + * Eg. userInput => add -n andre -g ng-andre + * output => ["andre", "ng-andre"] + * Note: Each index is properly identified by enumeration in contact/DetailType + * @param userInput User's complete untouched input + * @return String[] Returns an array of details + * @throws InvalidFlagException If the flag given is not recognised + */ + public String[] parseContactDetails(String userInput) throws InvalidFlagException { + String[] contactDetails = new String[NUMBER_OF_DETAILS]; + String[] destructuredInputs = userInput.split(DETAIL_SEPARATOR); + for (int i = CONTACT_PARAMS_START_INDEX; i < destructuredInputs.length; i++) { + parseDetail(contactDetails, destructuredInputs[i]); + } + return contactDetails; + } + + /** + * This method takes in the contactDetails array and populates it with contact details. + * It will sift out the flags to decide what details to populate, using the + * enumeration from DetailType. + * @param contactDetails String array containing contact details + * @param detail Unparsed detail + * @throws InvalidFlagException If the flag given is not recognised + */ + private void parseDetail(String[] contactDetails, String detail) throws InvalidFlagException { + String[] destructuredDetails = detail.split(" ", DETAILS_TO_SPLIT); + int indexToStore; + switch (destructuredDetails[FLAG_INDEX_IN_DETAILS]) { + case NAME_FLAG: + indexToStore = DetailType.NAME.getIndex(); + break; + case GITHUB_FLAG: + indexToStore = DetailType.GITHUB.getIndex(); + break; + default: + throw new InvalidFlagException(); + } + contactDetails[indexToStore] = destructuredDetails[DETAIL_INDEX_IN_DETAILS]; + } +} From 2db5f208f21ee3efe62fccab4b0db1f06e24da78 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 16:52:50 +0800 Subject: [PATCH 040/756] Update Main class to use MainParser from Parser --- src/main/java/seedu/duke/Duke.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index f154ebaea0..ee618e7770 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -3,7 +3,7 @@ import seedu.command.Command; import seedu.contact.ContactList; import seedu.exception.FileErrorException; -import seedu.parser.Parser; +import seedu.parser.MainParser; import seedu.storage.ContactsEncoder; import seedu.storage.Storage; import seedu.ui.TextUi; @@ -12,14 +12,14 @@ public class Duke { private TextUi textUi; private String contactFilePath; private Storage storage; - private Parser parser; + private MainParser parser; private ContactList contactList; public Duke(String contactFilePath) { this.textUi = new TextUi(); this.contactFilePath = contactFilePath; this.storage = new Storage(contactFilePath); - this.parser = new Parser(); + this.parser = new MainParser(); try { this.contactList = storage.loadExistingContacts(); } catch (FileErrorException e) { From 7b1f57314efbf7faf703a7bd2f2ad25df0060116 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 16:53:03 +0800 Subject: [PATCH 041/756] Implement InvalidFlagException and exception handling for it --- src/main/java/seedu/command/FailedCommand.java | 3 +++ src/main/java/seedu/exception/InvalidFlagException.java | 4 ++++ src/main/java/seedu/parser/FailedCommandType.java | 2 +- src/main/java/seedu/ui/TextUi.java | 8 ++++++++ 4 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 src/main/java/seedu/exception/InvalidFlagException.java diff --git a/src/main/java/seedu/command/FailedCommand.java b/src/main/java/seedu/command/FailedCommand.java index 9e0bc7a97f..1e0bcb2135 100644 --- a/src/main/java/seedu/command/FailedCommand.java +++ b/src/main/java/seedu/command/FailedCommand.java @@ -15,6 +15,9 @@ public void execute() { case GENERAL: TextUi.invalidCommandMessage(); break; + case INVALID_FLAG: + TextUi.invalidFlagMessage(); + break; default: return; } diff --git a/src/main/java/seedu/exception/InvalidFlagException.java b/src/main/java/seedu/exception/InvalidFlagException.java new file mode 100644 index 0000000000..db17ee92f9 --- /dev/null +++ b/src/main/java/seedu/exception/InvalidFlagException.java @@ -0,0 +1,4 @@ +package seedu.exception; + +public class InvalidFlagException extends Exception { +} diff --git a/src/main/java/seedu/parser/FailedCommandType.java b/src/main/java/seedu/parser/FailedCommandType.java index 4de6809d26..bb4485dda8 100644 --- a/src/main/java/seedu/parser/FailedCommandType.java +++ b/src/main/java/seedu/parser/FailedCommandType.java @@ -1,5 +1,5 @@ package seedu.parser; public enum FailedCommandType { - GENERAL + GENERAL, INVALID_FLAG } diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 87eeddd175..50f07d5fae 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -76,4 +76,12 @@ public static void invalidCommandMessage() { + "Please try again with a valid command."; printDoubleLineMessage(message); } + + public static void invalidFlagMessage() { + String message = "There appears to be a flag that is not recognised.\n" + + "Please try again with a valid flag.\n" + + " -n NAME\n" + + " -g GITHUB"; + printDoubleLineMessage(message); + } } From fdcf222f7a062a8fff332a0ab0e0042ec1efdee1 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 16:55:24 +0800 Subject: [PATCH 042/756] Revert "Implement InvalidFlagException and exception handling for it" This reverts commit 7b1f57314efbf7faf703a7bd2f2ad25df0060116. --- src/main/java/seedu/command/FailedCommand.java | 3 --- src/main/java/seedu/exception/InvalidFlagException.java | 4 ---- src/main/java/seedu/parser/FailedCommandType.java | 2 +- src/main/java/seedu/ui/TextUi.java | 8 -------- 4 files changed, 1 insertion(+), 16 deletions(-) delete mode 100644 src/main/java/seedu/exception/InvalidFlagException.java diff --git a/src/main/java/seedu/command/FailedCommand.java b/src/main/java/seedu/command/FailedCommand.java index 1e0bcb2135..9e0bc7a97f 100644 --- a/src/main/java/seedu/command/FailedCommand.java +++ b/src/main/java/seedu/command/FailedCommand.java @@ -15,9 +15,6 @@ public void execute() { case GENERAL: TextUi.invalidCommandMessage(); break; - case INVALID_FLAG: - TextUi.invalidFlagMessage(); - break; default: return; } diff --git a/src/main/java/seedu/exception/InvalidFlagException.java b/src/main/java/seedu/exception/InvalidFlagException.java deleted file mode 100644 index db17ee92f9..0000000000 --- a/src/main/java/seedu/exception/InvalidFlagException.java +++ /dev/null @@ -1,4 +0,0 @@ -package seedu.exception; - -public class InvalidFlagException extends Exception { -} diff --git a/src/main/java/seedu/parser/FailedCommandType.java b/src/main/java/seedu/parser/FailedCommandType.java index bb4485dda8..4de6809d26 100644 --- a/src/main/java/seedu/parser/FailedCommandType.java +++ b/src/main/java/seedu/parser/FailedCommandType.java @@ -1,5 +1,5 @@ package seedu.parser; public enum FailedCommandType { - GENERAL, INVALID_FLAG + GENERAL } diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 50f07d5fae..87eeddd175 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -76,12 +76,4 @@ public static void invalidCommandMessage() { + "Please try again with a valid command."; printDoubleLineMessage(message); } - - public static void invalidFlagMessage() { - String message = "There appears to be a flag that is not recognised.\n" - + "Please try again with a valid flag.\n" - + " -n NAME\n" - + " -g GITHUB"; - printDoubleLineMessage(message); - } } From ce6ee36d5a16cbefcc88eaf26eb7217891b55823 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 16:55:51 +0800 Subject: [PATCH 043/756] Revert "Revert "Implement InvalidFlagException and exception handling for it"" This reverts commit fdcf222f7a062a8fff332a0ab0e0042ec1efdee1. --- src/main/java/seedu/command/FailedCommand.java | 3 +++ src/main/java/seedu/exception/InvalidFlagException.java | 4 ++++ src/main/java/seedu/parser/FailedCommandType.java | 2 +- src/main/java/seedu/ui/TextUi.java | 8 ++++++++ 4 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 src/main/java/seedu/exception/InvalidFlagException.java diff --git a/src/main/java/seedu/command/FailedCommand.java b/src/main/java/seedu/command/FailedCommand.java index 9e0bc7a97f..1e0bcb2135 100644 --- a/src/main/java/seedu/command/FailedCommand.java +++ b/src/main/java/seedu/command/FailedCommand.java @@ -15,6 +15,9 @@ public void execute() { case GENERAL: TextUi.invalidCommandMessage(); break; + case INVALID_FLAG: + TextUi.invalidFlagMessage(); + break; default: return; } diff --git a/src/main/java/seedu/exception/InvalidFlagException.java b/src/main/java/seedu/exception/InvalidFlagException.java new file mode 100644 index 0000000000..db17ee92f9 --- /dev/null +++ b/src/main/java/seedu/exception/InvalidFlagException.java @@ -0,0 +1,4 @@ +package seedu.exception; + +public class InvalidFlagException extends Exception { +} diff --git a/src/main/java/seedu/parser/FailedCommandType.java b/src/main/java/seedu/parser/FailedCommandType.java index 4de6809d26..bb4485dda8 100644 --- a/src/main/java/seedu/parser/FailedCommandType.java +++ b/src/main/java/seedu/parser/FailedCommandType.java @@ -1,5 +1,5 @@ package seedu.parser; public enum FailedCommandType { - GENERAL + GENERAL, INVALID_FLAG } diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 87eeddd175..50f07d5fae 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -76,4 +76,12 @@ public static void invalidCommandMessage() { + "Please try again with a valid command."; printDoubleLineMessage(message); } + + public static void invalidFlagMessage() { + String message = "There appears to be a flag that is not recognised.\n" + + "Please try again with a valid flag.\n" + + " -n NAME\n" + + " -g GITHUB"; + printDoubleLineMessage(message); + } } From c802ed44b2d1c622ed82f78a45141489b44d5a4d Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 17:05:48 +0800 Subject: [PATCH 044/756] Update documentation to fit CheckStyle --- src/main/java/seedu/parser/AddContactParser.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/parser/AddContactParser.java b/src/main/java/seedu/parser/AddContactParser.java index ff9d8814f3..0a9dc2d801 100644 --- a/src/main/java/seedu/parser/AddContactParser.java +++ b/src/main/java/seedu/parser/AddContactParser.java @@ -5,9 +5,9 @@ public class AddContactParser extends ContactParser { /** - * This method returns a String[] containing the user's input and the arguments specified for + * Returns a String[] containing the user's input and the arguments specified for * each detail flag. Each detail is parsed individually using parseDetail. - * + *

* Eg. userInput => add -n andre -g ng-andre * output => ["andre", "ng-andre"] * Note: Each index is properly identified by enumeration in contact/DetailType From a5d091aea72b75a2e473a21583d9883e0d99d54e Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 17:09:58 +0800 Subject: [PATCH 045/756] Update IO redirection testing inputs and expected outputs --- text-ui-test/ACTUAL.TXT | 7 ++++++- text-ui-test/EXPECTED-UNIX.TXT | 7 ++++++- text-ui-test/EXPECTED.TXT | 7 ++++++- text-ui-test/input.txt | 3 ++- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index 4fed95bc32..26e883946b 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -18,10 +18,15 @@ data/contacts.txt ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: andre +ConTech has added the specified contact: ng andre You now have 1 contact(s). ____________________________________________________________ +____________________________________________________________ +ConTech has added the specified contact: lezong +You now have 2 contact(s). +____________________________________________________________ + ____________________________________________________________ ConTech will now shutdown. We hope you have enjoyed using it. diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index 4fed95bc32..26e883946b 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -18,10 +18,15 @@ data/contacts.txt ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: andre +ConTech has added the specified contact: ng andre You now have 1 contact(s). ____________________________________________________________ +____________________________________________________________ +ConTech has added the specified contact: lezong +You now have 2 contact(s). +____________________________________________________________ + ____________________________________________________________ ConTech will now shutdown. We hope you have enjoyed using it. diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 4fed95bc32..26e883946b 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -18,10 +18,15 @@ data/contacts.txt ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: andre +ConTech has added the specified contact: ng andre You now have 1 contact(s). ____________________________________________________________ +____________________________________________________________ +ConTech has added the specified contact: lezong +You now have 2 contact(s). +____________________________________________________________ + ____________________________________________________________ ConTech will now shutdown. We hope you have enjoyed using it. diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index 2258b281ab..2a8005f15d 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -1,2 +1,3 @@ -add n/andre g/ng-andre +add -n ng andre -g ng-andre +add -g lezongmun -n lezong exit \ No newline at end of file From cfc0f99cfae76c14f15e618680074fff9c438aff Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 6 Oct 2021 17:24:07 +0800 Subject: [PATCH 046/756] Change p tag wrapping in AddContactParser --- src/main/java/seedu/parser/AddContactParser.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/AddContactParser.java b/src/main/java/seedu/parser/AddContactParser.java index 0a9dc2d801..b24c6aa5a3 100644 --- a/src/main/java/seedu/parser/AddContactParser.java +++ b/src/main/java/seedu/parser/AddContactParser.java @@ -7,9 +7,10 @@ public class AddContactParser extends ContactParser { /** * Returns a String[] containing the user's input and the arguments specified for * each detail flag. Each detail is parsed individually using parseDetail. - *

+ *

* Eg. userInput => add -n andre -g ng-andre * output => ["andre", "ng-andre"] + *

* Note: Each index is properly identified by enumeration in contact/DetailType * @param userInput User's complete untouched input * @return String[] Returns an array of details From e75b69880c2c402b1506d1d90981d87d00b91042 Mon Sep 17 00:00:00 2001 From: lezong Date: Wed, 6 Oct 2021 17:51:36 +0800 Subject: [PATCH 047/756] Add basic delete feature --- text-ui-test/ACTUAL.TXT | 5 +++++ text-ui-test/EXPECTED-UNIX.TXT | 5 +++++ text-ui-test/EXPECTED.TXT | 5 +++++ text-ui-test/input.txt | 1 + 4 files changed, 16 insertions(+) diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index 4fed95bc32..dc22f35bc3 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -22,6 +22,11 @@ ConTech has added the specified contact: andre You now have 1 contact(s). ____________________________________________________________ +____________________________________________________________ +ConTech has removed the specified contact: andre +You now have 0 contact(s). +____________________________________________________________ + ____________________________________________________________ ConTech will now shutdown. We hope you have enjoyed using it. diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index 4fed95bc32..dc22f35bc3 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -22,6 +22,11 @@ ConTech has added the specified contact: andre You now have 1 contact(s). ____________________________________________________________ +____________________________________________________________ +ConTech has removed the specified contact: andre +You now have 0 contact(s). +____________________________________________________________ + ____________________________________________________________ ConTech will now shutdown. We hope you have enjoyed using it. diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 4fed95bc32..dc22f35bc3 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -22,6 +22,11 @@ ConTech has added the specified contact: andre You now have 1 contact(s). ____________________________________________________________ +____________________________________________________________ +ConTech has removed the specified contact: andre +You now have 0 contact(s). +____________________________________________________________ + ____________________________________________________________ ConTech will now shutdown. We hope you have enjoyed using it. diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index 2258b281ab..abc0401c84 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -1,2 +1,3 @@ add n/andre g/ng-andre +rm 1 exit \ No newline at end of file From 9de05ae71d4d121ab4d65d803745dedf6bffda63 Mon Sep 17 00:00:00 2001 From: lezong Date: Wed, 6 Oct 2021 18:06:27 +0800 Subject: [PATCH 048/756] Add basic delete feature --- .../seedu/command/DeleteContactCommand.java | 22 +++++++++++++++++++ src/main/java/seedu/contact/ContactList.java | 8 +++++++ src/main/java/seedu/parser/Parser.java | 12 ++++++++++ src/main/java/seedu/ui/TextUi.java | 6 +++++ .../command/DeleteContactCommandTest.java | 22 +++++++++++++++++++ 5 files changed, 70 insertions(+) create mode 100644 src/main/java/seedu/command/DeleteContactCommand.java create mode 100644 src/test/java/seedu/command/DeleteContactCommandTest.java diff --git a/src/main/java/seedu/command/DeleteContactCommand.java b/src/main/java/seedu/command/DeleteContactCommand.java new file mode 100644 index 0000000000..4ef64e92c7 --- /dev/null +++ b/src/main/java/seedu/command/DeleteContactCommand.java @@ -0,0 +1,22 @@ +package seedu.command; + +import seedu.contact.Contact; +import seedu.ui.TextUi; + +public class DeleteContactCommand extends Command { + private final int deletedIndex; + + public DeleteContactCommand(int deletedIndex) { + this.deletedIndex = deletedIndex; + } + + public int getDeletedIndex() { + return deletedIndex; + } + + public void execute() { + Contact deletedContact = contactList.getContactAtIndex(deletedIndex); + this.contactList.deleteContact(deletedIndex); + TextUi.deleteContactMessage(deletedContact.getName(), contactList.getListSize()); + } +} diff --git a/src/main/java/seedu/contact/ContactList.java b/src/main/java/seedu/contact/ContactList.java index 6226227743..76b18489e3 100644 --- a/src/main/java/seedu/contact/ContactList.java +++ b/src/main/java/seedu/contact/ContactList.java @@ -13,6 +13,14 @@ public void addContact(Contact contact) { contacts.add(contact); } + public void deleteContact(int deletedIndex) { + contacts.remove(deletedIndex); + } + + public int getIndexOfContact(Contact contact) { + return contacts.indexOf(contact); + } + public Contact getContactAtIndex(int index) { return contacts.get(index); } diff --git a/src/main/java/seedu/parser/Parser.java b/src/main/java/seedu/parser/Parser.java index a514a25954..bf61834077 100644 --- a/src/main/java/seedu/parser/Parser.java +++ b/src/main/java/seedu/parser/Parser.java @@ -1,12 +1,15 @@ package seedu.parser; + import seedu.command.AddContactCommand; +import seedu.command.DeleteContactCommand; import seedu.command.Command; import seedu.command.ExitCommand; import seedu.command.FailedCommand; public class Parser { private static final String ADD_TASK_COMD = "add"; + private static final String DELETE_TASK_COMD = "rm"; private static final String EXIT_COMD = "exit"; private static final int COMD_WORD_INDEX = 0; @@ -23,6 +26,9 @@ public Command parseCommand(String userInput) { case ADD_TASK_COMD: command = parseAddContact(userInput); break; + case DELETE_TASK_COMD: + command = parseDeleteContact(userInput); + break; case EXIT_COMD: command = new ExitCommand(); break; @@ -46,6 +52,12 @@ private Command parseAddContact(String userInput) { return new AddContactCommand(name, github); } + private Command parseDeleteContact(String userInput) { + String[] destructuredInputs = userInput.split(" ", ISOLATE_COMD_WORD); + int deletedIndex = Integer.parseInt(destructuredInputs[1]) - 1; + return new DeleteContactCommand(deletedIndex); + } + // Will create a function to parse details soon, hardcoding for V0.1 (7/10/21 version) // private String parseDetail(String contactParameters, String tag) { diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 87eeddd175..2ea5af832f 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -57,6 +57,12 @@ public static void addContactMessage(String contactName, int listSize) { printDoubleLineMessage(message); } + public static void deleteContactMessage(String contactName, int listSize) { + String message = "ConTech has removed the specified contact: " + contactName + "\n" + + "You now have " + listSize + " contact(s)."; + printDoubleLineMessage(message); + } + public static void exitMessage() { String message = "ConTech will now shutdown.\n" + "We hope you have enjoyed using it."; diff --git a/src/test/java/seedu/command/DeleteContactCommandTest.java b/src/test/java/seedu/command/DeleteContactCommandTest.java new file mode 100644 index 0000000000..3fa0fbd467 --- /dev/null +++ b/src/test/java/seedu/command/DeleteContactCommandTest.java @@ -0,0 +1,22 @@ +package seedu.command; + +import org.junit.jupiter.api.Test; +import seedu.parser.Parser; + +import static org.junit.jupiter.api.Assertions.assertEquals; + + +class DeleteContactCommandTest { + + @Test + void execute() { + Parser parser = new Parser(); + final int testIndex = 1; + final String input = "rm " + testIndex; + final Command result = parser.parseCommand(input); +// final DeleteCommand result = parseAndAssertCommandType(input, DeleteCommand.class); + int targetIndex = result.contactList.getIndexOfContact(result); + + assertEquals(result.getTargetIndex(), testIndex); + } +} \ No newline at end of file From c752454e71fcac0b19d1ba490c001db4a4b9d950 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Wed, 6 Oct 2021 19:44:16 +0800 Subject: [PATCH 049/756] Add message for editing contact --- src/main/java/seedu/ui/TextUi.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 50f07d5fae..6255a6e7f0 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -57,6 +57,11 @@ public static void addContactMessage(String contactName, int listSize) { printDoubleLineMessage(message); } + public static void editContactMessage(String contactName) { + String message = "ConTech has edited the specified contact: " + contactName + "\n"; + printDoubleLineMessage(message); + } + public static void exitMessage() { String message = "ConTech will now shutdown.\n" + "We hope you have enjoyed using it."; From 34552e6464205f4e6bee85ee341b5db6fdecaf3e Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Wed, 6 Oct 2021 19:58:24 +0800 Subject: [PATCH 050/756] Create EditContactCommand command class and implement execute method --- .../seedu/command/EditContactCommand.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/main/java/seedu/command/EditContactCommand.java diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java new file mode 100644 index 0000000000..58491a5d27 --- /dev/null +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -0,0 +1,19 @@ +package seedu.command; + +import seedu.contact.Contact; +import seedu.ui.TextUi; + +public class EditContactCommand extends Command { + String[] contactDetails; + int contactIndex; + + public EditContactCommand(String[] contactDetails, int contactIndex) { + this.contactDetails = contactDetails; + this.contactIndex = contactIndex; + } + + public void execute() { + contactList.editContact(contactDetails, contactIndex); + TextUi.editContactMessage(contactList.getContactAtIndex(contactIndex).getName()); + } +} From 0db8a5722282df7b96ef646eeba4c4a753eed8de Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Wed, 6 Oct 2021 20:10:55 +0800 Subject: [PATCH 051/756] Changed ADD_TASK_COMD to ADD_CONTACT_COMD and add edit case --- src/main/java/seedu/parser/MainParser.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index b0c12ee3e6..437f999c90 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -8,22 +8,27 @@ import seedu.exception.InvalidFlagException; public class MainParser { - private static final String ADD_TASK_COMD = "add"; + private static final String ADD_CONTACT_COMD = "add"; private static final String EXIT_COMD = "exit"; + private static final String EDIT_CONTACT_COMD = "edit"; private static final int COMD_WORD_INDEX = 0; private static final int ISOLATE_COMD_WORD = 2; private ContactParser contactParser; private AddContactParser addContactParser = new AddContactParser(); + private EditContactParser editContactParser = new EditContactParser(); public Command parseCommand(String userInput) { String commandType = getCommandWord(userInput); Command command; switch (commandType) { - case ADD_TASK_COMD: + case ADD_CONTACT_COMD: command = parseAddContact(userInput); break; + case EDIT_CONTACT_COMD: + command = parseEditContact(userInput); //todo change + break; case EXIT_COMD: command = new ExitCommand(); break; From 4e8bb835365afa1e6b3663c7f875878e7b78030f Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Wed, 6 Oct 2021 20:34:06 +0800 Subject: [PATCH 052/756] Initialise EditContactParser class with same methods as AddContactParser --- .../java/seedu/parser/EditContactParser.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 src/main/java/seedu/parser/EditContactParser.java diff --git a/src/main/java/seedu/parser/EditContactParser.java b/src/main/java/seedu/parser/EditContactParser.java new file mode 100644 index 0000000000..17f3c1a9ee --- /dev/null +++ b/src/main/java/seedu/parser/EditContactParser.java @@ -0,0 +1,35 @@ +package seedu.parser; + +import seedu.contact.DetailType; +import seedu.exception.InvalidFlagException; + +import java.util.Arrays; + +public class EditContactParser extends ContactParser { + @Override + public String[] parseContactDetails(String userInput) throws InvalidFlagException { + String[] contactDetails = new String[NUMBER_OF_DETAILS]; + Arrays.fill(contactDetails, null); + String[] destructuredInputs = userInput.split(DETAIL_SEPARATOR); + for (int i = CONTACT_PARAMS_START_INDEX; i < destructuredInputs.length; i++) { + parseDetail(contactDetails, destructuredInputs[i]); + } + return contactDetails; + } + + private void parseDetail(String[] contactDetails, String detail) throws InvalidFlagException { + String[] destructuredDetails = detail.split(" ", NUMBER_OF_EDIT_DETAILS); + int indexToStore; + switch (destructuredDetails[FLAG_INDEX_IN_DETAILS]) { + case NAME_FLAG: + indexToStore = DetailType.NAME.getIndex(); + break; + case GITHUB_FLAG: + indexToStore = DetailType.GITHUB.getIndex(); + break; + default: + throw new InvalidFlagException(); + } + contactDetails[indexToStore] = destructuredDetails[DETAIL_INDEX_IN_DETAILS]; + } +} From f4a91feeb49002b93ee7b098d3d3fcca1e7ec627 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Wed, 6 Oct 2021 20:34:35 +0800 Subject: [PATCH 053/756] Update constants in ContactParser --- src/main/java/seedu/parser/ContactParser.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index 496f05b6a0..f47a9dba45 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -5,6 +5,7 @@ public abstract class ContactParser { public static final int CONTACT_PARAMS_START_INDEX = 1; public static final int NUMBER_OF_DETAILS = 2; + public static final int NUMBER_OF_EDIT_DETAILS = 3; public static final String DETAIL_SEPARATOR = " -"; public static final int DETAILS_TO_SPLIT = 2; From af4890c016f1886793025f55261a29a80106ccc6 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Wed, 6 Oct 2021 20:35:47 +0800 Subject: [PATCH 054/756] Update imports and constants --- src/main/java/seedu/contact/ContactList.java | 18 ++++++++++++++++++ src/main/java/seedu/parser/MainParser.java | 4 ++++ 2 files changed, 22 insertions(+) diff --git a/src/main/java/seedu/contact/ContactList.java b/src/main/java/seedu/contact/ContactList.java index 6226227743..10ac322d6f 100644 --- a/src/main/java/seedu/contact/ContactList.java +++ b/src/main/java/seedu/contact/ContactList.java @@ -13,6 +13,24 @@ public void addContact(Contact contact) { contacts.add(contact); } + public void editContact(String[] contactDetails, int contactIndex) { + for (int i = 0; i < contactDetails.length; i++) { + if (contactDetails[i] != null) { + switch (i) { + case NAME_INDEX: + contacts.get(contactIndex).setName(contactDetails[i]); + break; + case GITHUB_INDEX: + contacts.get(contactIndex).setGithub(contactDetails[i]); + break; + default: + System.out.println("Index error has occurred."); + break; + } + } + } + } + public Contact getContactAtIndex(int index) { return contacts.get(index); } diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 437f999c90..f0d923576a 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -1,6 +1,7 @@ package seedu.parser; import seedu.command.AddContactCommand; +import seedu.command.EditContactCommand; import seedu.command.Command; import seedu.command.ExitCommand; import seedu.command.FailedCommand; @@ -13,7 +14,10 @@ public class MainParser { private static final String EDIT_CONTACT_COMD = "edit"; private static final int COMD_WORD_INDEX = 0; + private static final int EDIT_USER_INDEX = 1; + private static final int EDIT_INFO_INDEX = 2; private static final int ISOLATE_COMD_WORD = 2; + public static final int NUMBER_OF_EDIT_DETAILS = 3; private ContactParser contactParser; private AddContactParser addContactParser = new AddContactParser(); From 706180310a5df92c800628a973d9aacfcb1db558 Mon Sep 17 00:00:00 2001 From: lezong Date: Wed, 6 Oct 2021 20:45:35 +0800 Subject: [PATCH 055/756] Add delete contact feature,some exception handling for delete and add command --- .../java/seedu/command/FailedCommand.java | 12 ++++++ .../seedu/exception/MissingArgException.java | 4 ++ .../exception/MissingDetailException.java | 4 ++ .../java/seedu/parser/AddContactParser.java | 14 ++++++- src/main/java/seedu/parser/ContactParser.java | 5 ++- .../java/seedu/parser/FailedCommandType.java | 2 +- src/main/java/seedu/parser/MainParser.java | 23 ++++++++++-- src/main/java/seedu/ui/TextUi.java | 26 +++++++++++++ .../command/DeleteContactCommandTest.java | 22 ----------- .../java/seedu/parser/MainParserTest.java | 37 +++++++++++++++++++ text-ui-test/ACTUAL.TXT | 21 +++++++---- text-ui-test/EXPECTED-UNIX.TXT | 21 +++++++---- text-ui-test/EXPECTED.TXT | 21 +++++++---- text-ui-test/input.txt | 9 ++--- 14 files changed, 166 insertions(+), 55 deletions(-) create mode 100644 src/main/java/seedu/exception/MissingArgException.java create mode 100644 src/main/java/seedu/exception/MissingDetailException.java delete mode 100644 src/test/java/seedu/command/DeleteContactCommandTest.java create mode 100644 src/test/java/seedu/parser/MainParserTest.java diff --git a/src/main/java/seedu/command/FailedCommand.java b/src/main/java/seedu/command/FailedCommand.java index 1e0bcb2135..c59c9af14e 100644 --- a/src/main/java/seedu/command/FailedCommand.java +++ b/src/main/java/seedu/command/FailedCommand.java @@ -18,6 +18,18 @@ public void execute() { case INVALID_FLAG: TextUi.invalidFlagMessage(); break; + case MISSING_ARG: + TextUi.missingArgMessage(); + break; + case MISSING_DETAIL: + TextUi.missingDetailMessage(); + break; + case INVALID_NUM: + TextUi.invalidNumMessage(); + break; + case INVALID_FORMAT: + TextUi.invalidFormatMessage(); + break; default: return; } diff --git a/src/main/java/seedu/exception/MissingArgException.java b/src/main/java/seedu/exception/MissingArgException.java new file mode 100644 index 0000000000..a4b92a65e1 --- /dev/null +++ b/src/main/java/seedu/exception/MissingArgException.java @@ -0,0 +1,4 @@ +package seedu.exception; + +public class MissingArgException extends Exception{ +} diff --git a/src/main/java/seedu/exception/MissingDetailException.java b/src/main/java/seedu/exception/MissingDetailException.java new file mode 100644 index 0000000000..52ca852ce5 --- /dev/null +++ b/src/main/java/seedu/exception/MissingDetailException.java @@ -0,0 +1,4 @@ +package seedu.exception; + +public class MissingDetailException extends Exception { +} diff --git a/src/main/java/seedu/parser/AddContactParser.java b/src/main/java/seedu/parser/AddContactParser.java index b24c6aa5a3..965a0280d1 100644 --- a/src/main/java/seedu/parser/AddContactParser.java +++ b/src/main/java/seedu/parser/AddContactParser.java @@ -2,6 +2,8 @@ import seedu.contact.DetailType; import seedu.exception.InvalidFlagException; +import seedu.exception.MissingArgException; +import seedu.exception.MissingDetailException; public class AddContactParser extends ContactParser { /** @@ -16,9 +18,13 @@ public class AddContactParser extends ContactParser { * @return String[] Returns an array of details * @throws InvalidFlagException If the flag given is not recognised */ - public String[] parseContactDetails(String userInput) throws InvalidFlagException { + public String[] parseContactDetails(String userInput) throws InvalidFlagException, MissingArgException, + MissingDetailException { String[] contactDetails = new String[NUMBER_OF_DETAILS]; String[] destructuredInputs = userInput.split(DETAIL_SEPARATOR); + if (destructuredInputs.length == 1) { + throw new MissingArgException(); + } for (int i = CONTACT_PARAMS_START_INDEX; i < destructuredInputs.length; i++) { parseDetail(contactDetails, destructuredInputs[i]); } @@ -33,7 +39,7 @@ public String[] parseContactDetails(String userInput) throws InvalidFlagExceptio * @param detail Unparsed detail * @throws InvalidFlagException If the flag given is not recognised */ - private void parseDetail(String[] contactDetails, String detail) throws InvalidFlagException { + private void parseDetail(String[] contactDetails, String detail) throws InvalidFlagException, MissingDetailException { String[] destructuredDetails = detail.split(" ", DETAILS_TO_SPLIT); int indexToStore; switch (destructuredDetails[FLAG_INDEX_IN_DETAILS]) { @@ -46,6 +52,10 @@ private void parseDetail(String[] contactDetails, String detail) throws InvalidF default: throw new InvalidFlagException(); } + + if (destructuredDetails.length == 1 || destructuredDetails[DETAIL_INDEX_IN_DETAILS].isBlank()) { + throw new MissingDetailException(); + } contactDetails[indexToStore] = destructuredDetails[DETAIL_INDEX_IN_DETAILS]; } } diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index 496f05b6a0..7d4ead9b9c 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -1,6 +1,8 @@ package seedu.parser; import seedu.exception.InvalidFlagException; +import seedu.exception.MissingArgException; +import seedu.exception.MissingDetailException; public abstract class ContactParser { public static final int CONTACT_PARAMS_START_INDEX = 1; @@ -14,5 +16,6 @@ public abstract class ContactParser { public static final String NAME_FLAG = "n"; public static final String GITHUB_FLAG = "g"; - public abstract String[] parseContactDetails(String userInput) throws InvalidFlagException; + public abstract String[] parseContactDetails(String userInput) throws InvalidFlagException, MissingArgException, + MissingDetailException; } diff --git a/src/main/java/seedu/parser/FailedCommandType.java b/src/main/java/seedu/parser/FailedCommandType.java index bb4485dda8..4497da25cc 100644 --- a/src/main/java/seedu/parser/FailedCommandType.java +++ b/src/main/java/seedu/parser/FailedCommandType.java @@ -1,5 +1,5 @@ package seedu.parser; public enum FailedCommandType { - GENERAL, INVALID_FLAG + GENERAL, INVALID_FLAG, MISSING_ARG, MISSING_DETAIL, INVALID_NUM, INVALID_FORMAT } diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 033894bad7..1189249152 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -8,6 +8,8 @@ import seedu.command.FailedCommand; import seedu.contact.DetailType; import seedu.exception.InvalidFlagException; +import seedu.exception.MissingArgException; +import seedu.exception.MissingDetailException; public class MainParser { private static final String ADD_TASK_COMD = "add"; @@ -51,13 +53,28 @@ private Command parseAddContact(String userInput) { return new AddContactCommand(details[DetailType.NAME.getIndex()], details[DetailType.GITHUB.getIndex()]); } catch (InvalidFlagException e) { return new FailedCommand(FailedCommandType.INVALID_FLAG); + } catch (MissingArgException e) { + return new FailedCommand(FailedCommandType.MISSING_ARG); + } catch (MissingDetailException e) { + return new FailedCommand(FailedCommandType.MISSING_DETAIL); } } private Command parseDeleteContact(String userInput) { - String[] destructuredInputs = userInput.split(" ", ISOLATE_COMD_WORD); - int deletedIndex = Integer.parseInt(destructuredInputs[1]) - 1; - return new DeleteContactCommand(deletedIndex); + String[] destructuredInputs = userInput.split(" "); + if (destructuredInputs.length == 1) { + return new FailedCommand(FailedCommandType.MISSING_ARG); + } + if (destructuredInputs.length > 2) { + return new FailedCommand(FailedCommandType.INVALID_FORMAT); + } + + try { + int deletedIndex = Integer.parseInt(destructuredInputs[1]); + return new DeleteContactCommand(deletedIndex); + } catch (NumberFormatException e) { + return new FailedCommand(FailedCommandType.INVALID_NUM); + } } diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 2be83a5413..cac1b39ed4 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -22,6 +22,7 @@ public TextUi() { initMessage(); } + public String getUserInput() { return scanner.nextLine(); } @@ -90,4 +91,29 @@ public static void invalidFlagMessage() { + " -g GITHUB"; printDoubleLineMessage(message); } + + public static void missingDetailMessage() { + String message = "There are missing details.\n" + + "Please remove any flags with no details\n"; + printDoubleLineMessage(message); + } + + public static void missingArgMessage() { + String message = "There seems to be missing parameters in your request.\n" + + "Please specify your command.\n"; + printDoubleLineMessage(message); + } + + public static void invalidNumMessage() { + String message = "That does not seem to be a number.\n" + + "Please provide a number instead.\n"; + printDoubleLineMessage(message); + } + + public static void invalidFormatMessage() { + String message = "ConTech is unable to understand your request.\n" + + "The request has not been formatted correctly. Please try again.\n"; + printDoubleLineMessage(message); + } + } diff --git a/src/test/java/seedu/command/DeleteContactCommandTest.java b/src/test/java/seedu/command/DeleteContactCommandTest.java deleted file mode 100644 index 3fa0fbd467..0000000000 --- a/src/test/java/seedu/command/DeleteContactCommandTest.java +++ /dev/null @@ -1,22 +0,0 @@ -package seedu.command; - -import org.junit.jupiter.api.Test; -import seedu.parser.Parser; - -import static org.junit.jupiter.api.Assertions.assertEquals; - - -class DeleteContactCommandTest { - - @Test - void execute() { - Parser parser = new Parser(); - final int testIndex = 1; - final String input = "rm " + testIndex; - final Command result = parser.parseCommand(input); -// final DeleteCommand result = parseAndAssertCommandType(input, DeleteCommand.class); - int targetIndex = result.contactList.getIndexOfContact(result); - - assertEquals(result.getTargetIndex(), testIndex); - } -} \ No newline at end of file diff --git a/src/test/java/seedu/parser/MainParserTest.java b/src/test/java/seedu/parser/MainParserTest.java new file mode 100644 index 0000000000..02464c8b01 --- /dev/null +++ b/src/test/java/seedu/parser/MainParserTest.java @@ -0,0 +1,37 @@ +package seedu.parser; + +import org.junit.jupiter.api.BeforeEach; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; +import seedu.command.Command; +import seedu.command.DeleteContactCommand; +import seedu.parser.MainParser; + + +public class MainParserTest { + private MainParser mainParser; + + @BeforeEach + public void setUp() { + mainParser = new MainParser(); + } + + @Test + public void parseDeleteCommand() { + final int testIndex = 1; + final String testUserInput = "rm " + testIndex; + final DeleteContactCommand testResultCommand = assertParseCommand(testUserInput, DeleteContactCommand.class); + assertEquals(testIndex,testResultCommand.getDeletedIndex()); + } + + + private T assertParseCommand(String userInput, Class commandClass) { + final Command result = mainParser.parseCommand(userInput); + assertTrue(commandClass.isInstance(result)); + return (T) result; + } +} + diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index 29cf78c0b8..3d7e30421f 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -23,17 +23,24 @@ You now have 1 contact(s). ____________________________________________________________ ____________________________________________________________ -<<<<<<< HEAD -ConTech has removed the specified contact: andre -You now have 0 contact(s). -======= +There are missing details. +Please remove any flags with no details + +____________________________________________________________ + +____________________________________________________________ ConTech has added the specified contact: lezong You now have 2 contact(s). ->>>>>>> master ____________________________________________________________ ____________________________________________________________ -ConTech will now shutdown. -We hope you have enjoyed using it. +ConTech has removed the specified contact: ng andre +You now have 1 contact(s). +____________________________________________________________ + +____________________________________________________________ +That does not seem to be a number. +Please provide a number instead. + ____________________________________________________________ diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index 29cf78c0b8..3d7e30421f 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -23,17 +23,24 @@ You now have 1 contact(s). ____________________________________________________________ ____________________________________________________________ -<<<<<<< HEAD -ConTech has removed the specified contact: andre -You now have 0 contact(s). -======= +There are missing details. +Please remove any flags with no details + +____________________________________________________________ + +____________________________________________________________ ConTech has added the specified contact: lezong You now have 2 contact(s). ->>>>>>> master ____________________________________________________________ ____________________________________________________________ -ConTech will now shutdown. -We hope you have enjoyed using it. +ConTech has removed the specified contact: ng andre +You now have 1 contact(s). +____________________________________________________________ + +____________________________________________________________ +That does not seem to be a number. +Please provide a number instead. + ____________________________________________________________ diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 29cf78c0b8..3d7e30421f 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -23,17 +23,24 @@ You now have 1 contact(s). ____________________________________________________________ ____________________________________________________________ -<<<<<<< HEAD -ConTech has removed the specified contact: andre -You now have 0 contact(s). -======= +There are missing details. +Please remove any flags with no details + +____________________________________________________________ + +____________________________________________________________ ConTech has added the specified contact: lezong You now have 2 contact(s). ->>>>>>> master ____________________________________________________________ ____________________________________________________________ -ConTech will now shutdown. -We hope you have enjoyed using it. +ConTech has removed the specified contact: ng andre +You now have 1 contact(s). +____________________________________________________________ + +____________________________________________________________ +That does not seem to be a number. +Please provide a number instead. + ____________________________________________________________ diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index 968b046be5..426e4f96e1 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -1,8 +1,7 @@ -<<<<<<< HEAD -add n/andre g/ng-andre -rm 1 -======= add -n ng andre -g ng-andre +add -n bory -g add -g lezongmun -n lezong ->>>>>>> master +rm 0 +rm a +rm 1 exit \ No newline at end of file From 4d157376460a32c9e3ee4d2632c49840349b2606 Mon Sep 17 00:00:00 2001 From: lezong Date: Wed, 6 Oct 2021 21:05:35 +0800 Subject: [PATCH 056/756] Fix CheckStyle checks --- src/main/java/seedu/parser/AddContactParser.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/AddContactParser.java b/src/main/java/seedu/parser/AddContactParser.java index 965a0280d1..368a94f770 100644 --- a/src/main/java/seedu/parser/AddContactParser.java +++ b/src/main/java/seedu/parser/AddContactParser.java @@ -39,7 +39,8 @@ public String[] parseContactDetails(String userInput) throws InvalidFlagExceptio * @param detail Unparsed detail * @throws InvalidFlagException If the flag given is not recognised */ - private void parseDetail(String[] contactDetails, String detail) throws InvalidFlagException, MissingDetailException { + private void parseDetail(String[] contactDetails, String detail) + throws InvalidFlagException, MissingDetailException { String[] destructuredDetails = detail.split(" ", DETAILS_TO_SPLIT); int indexToStore; switch (destructuredDetails[FLAG_INDEX_IN_DETAILS]) { From 22bdca9f340fa5a5766f1a1185712df03f1966f2 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 6 Oct 2021 21:58:38 +0800 Subject: [PATCH 057/756] Add ListContactsCommand.java class --- src/main/java/seedu/command/ListContactsCommand.java | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/main/java/seedu/command/ListContactsCommand.java diff --git a/src/main/java/seedu/command/ListContactsCommand.java b/src/main/java/seedu/command/ListContactsCommand.java new file mode 100644 index 0000000000..9028115067 --- /dev/null +++ b/src/main/java/seedu/command/ListContactsCommand.java @@ -0,0 +1,4 @@ +package seedu.command; + +public class ListContactsCommand { +} From 402d5cd88517a80aae8018c36c3e3a0cf2a6c9ff Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 6 Oct 2021 22:44:23 +0800 Subject: [PATCH 058/756] Implement function to list all contacts with index --- .../java/seedu/command/ListContactsCommand.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/command/ListContactsCommand.java b/src/main/java/seedu/command/ListContactsCommand.java index 9028115067..6f118a7996 100644 --- a/src/main/java/seedu/command/ListContactsCommand.java +++ b/src/main/java/seedu/command/ListContactsCommand.java @@ -1,4 +1,16 @@ package seedu.command; -public class ListContactsCommand { +import seedu.ui.TextUi; + +public class ListContactsCommand extends Command { + @Override + public void execute() { + int listSize = contactList.getListSize(); + + TextUi.viewContactsListMessage(listSize); + for (int i = 0; i < listSize; i++) { + System.out.println(i + ". " + contactList.getContactAtIndex(i).getName()); + } + TextUi.printBottomLine(); + } } From c492b2c8e528c335116576a66616d97fc00ac397 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 6 Oct 2021 22:45:16 +0800 Subject: [PATCH 059/756] Add case for list command --- src/main/java/seedu/parser/MainParser.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index b0c12ee3e6..765cf5b8fc 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -4,12 +4,14 @@ import seedu.command.Command; import seedu.command.ExitCommand; import seedu.command.FailedCommand; +import seedu.command.ListContactsCommand; import seedu.contact.DetailType; import seedu.exception.InvalidFlagException; public class MainParser { private static final String ADD_TASK_COMD = "add"; private static final String EXIT_COMD = "exit"; + private static final String LIST_COMD = "list"; private static final int COMD_WORD_INDEX = 0; private static final int ISOLATE_COMD_WORD = 2; @@ -27,6 +29,9 @@ public Command parseCommand(String userInput) { case EXIT_COMD: command = new ExitCommand(); break; + case LIST_COMD: + command = new ListContactsCommand(); + break; default: command = new FailedCommand(FailedCommandType.GENERAL); } From e1f48d4fa22cf3502b69112d28639cc657259545 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Wed, 6 Oct 2021 22:46:15 +0800 Subject: [PATCH 060/756] Add UI for invalid index error --- src/main/java/seedu/command/FailedCommand.java | 3 +++ src/main/java/seedu/parser/FailedCommandType.java | 2 +- src/main/java/seedu/ui/TextUi.java | 5 +++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/command/FailedCommand.java b/src/main/java/seedu/command/FailedCommand.java index 1e0bcb2135..a4c6b4ce3e 100644 --- a/src/main/java/seedu/command/FailedCommand.java +++ b/src/main/java/seedu/command/FailedCommand.java @@ -18,6 +18,9 @@ public void execute() { case INVALID_FLAG: TextUi.invalidFlagMessage(); break; + case INVALID_INDEX: + TextUi.invalidIndexMessage(); + break; default: return; } diff --git a/src/main/java/seedu/parser/FailedCommandType.java b/src/main/java/seedu/parser/FailedCommandType.java index bb4485dda8..497d400614 100644 --- a/src/main/java/seedu/parser/FailedCommandType.java +++ b/src/main/java/seedu/parser/FailedCommandType.java @@ -1,5 +1,5 @@ package seedu.parser; public enum FailedCommandType { - GENERAL, INVALID_FLAG + GENERAL, INVALID_FLAG, INVALID_INDEX } diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 6255a6e7f0..12fb770647 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -89,4 +89,9 @@ public static void invalidFlagMessage() { + " -g GITHUB"; printDoubleLineMessage(message); } + + public static void invalidIndexMessage() { + String message = "Please enter a valid contact index."; + printDoubleLineMessage(message); + } } From 7dfd770cf2c1031ec33c505f1878e598cd36e312 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 6 Oct 2021 22:46:54 +0800 Subject: [PATCH 061/756] Add function to print line after data --- src/main/java/seedu/ui/TextUi.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 50f07d5fae..e3a60e796c 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -40,6 +40,13 @@ private static void printBottomLineMessage(String message) { ); } + // Used to print a line after displayed data + public static void printBottomLine() { + System.out.println( + "\n" + LINE + ); + } + private static void initMessage() { printDoubleLineMessage(LOGO); System.out.println("Welcome to ConTech, your personal contact tracker.\n" + LINE); From db569526925c6b5f291216e80b696ff5e7d33642 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 6 Oct 2021 22:50:02 +0800 Subject: [PATCH 062/756] Add print message for view command --- src/main/java/seedu/ui/TextUi.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index e3a60e796c..43256fed04 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -64,6 +64,11 @@ public static void addContactMessage(String contactName, int listSize) { printDoubleLineMessage(message); } + public static void viewContactsListMessage(int listSize) { + String message = "ConTech has " + listSize + " contacts stored.\n" + + "Here's the list :"; + printDoubleLineMessage(message); + } public static void exitMessage() { String message = "ConTech will now shutdown.\n" + "We hope you have enjoyed using it."; From b3991b540a90a94c0ceecf70d55bef2903eaa83a Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 6 Oct 2021 22:50:46 +0800 Subject: [PATCH 063/756] Add print message for view contacts when empty --- src/main/java/seedu/ui/TextUi.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 43256fed04..b8e80bc36d 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -69,6 +69,12 @@ public static void viewContactsListMessage(int listSize) { + "Here's the list :"; printDoubleLineMessage(message); } + + public static void viewContactsEmptyListMessage() { + String message = "You have not stored any contacts in ConTech"; + printDoubleLineMessage(message); + } + public static void exitMessage() { String message = "ConTech will now shutdown.\n" + "We hope you have enjoyed using it."; From 0b5aabfd43beb955ad3f5b5f8b72f377e3b11e5d Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Wed, 6 Oct 2021 22:56:49 +0800 Subject: [PATCH 064/756] Update more constants --- src/main/java/seedu/contact/ContactList.java | 3 +++ src/main/java/seedu/parser/MainParser.java | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/src/main/java/seedu/contact/ContactList.java b/src/main/java/seedu/contact/ContactList.java index 10ac322d6f..20b6e92654 100644 --- a/src/main/java/seedu/contact/ContactList.java +++ b/src/main/java/seedu/contact/ContactList.java @@ -3,6 +3,9 @@ import java.util.ArrayList; public class ContactList { + public static final int NAME_INDEX = 0; + public static final int GITHUB_INDEX = 1; + private ArrayList contacts; public ContactList() { diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index f0d923576a..14bdfc69ff 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -7,6 +7,9 @@ import seedu.command.FailedCommand; import seedu.contact.DetailType; import seedu.exception.InvalidFlagException; +import seedu.contact.Contact; + +import java.util.Arrays; public class MainParser { private static final String ADD_CONTACT_COMD = "add"; @@ -17,6 +20,7 @@ public class MainParser { private static final int EDIT_USER_INDEX = 1; private static final int EDIT_INFO_INDEX = 2; private static final int ISOLATE_COMD_WORD = 2; + private static final int ISOLATE_USER_INPUT = 2; public static final int NUMBER_OF_EDIT_DETAILS = 3; private ContactParser contactParser; From 0bd0076b62fce5a251270e968d6d751622ca406b Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Wed, 6 Oct 2021 22:57:36 +0800 Subject: [PATCH 065/756] Add parseEditContact method for handling user input --- src/main/java/seedu/parser/MainParser.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 14bdfc69ff..23e06af5b0 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -35,7 +35,7 @@ public Command parseCommand(String userInput) { command = parseAddContact(userInput); break; case EDIT_CONTACT_COMD: - command = parseEditContact(userInput); //todo change + command = parseEditContact(userInput); break; case EXIT_COMD: command = new ExitCommand(); @@ -60,4 +60,21 @@ private Command parseAddContact(String userInput) { return new FailedCommand(FailedCommandType.INVALID_FLAG); } } + + private Command parseEditContact(String userInput) { //userInput is raw user input + contactParser = editContactParser; + try { + //split into array of size 3 with command, index and details + String[] details = userInput.split(" ", NUMBER_OF_EDIT_DETAILS); + int userIndex = Integer.parseInt(details[EDIT_USER_INDEX]) - 1; + + String[] userDetails = editContactParser.parseContactDetails(details[ISOLATE_USER_INPUT]); + System.out.println(Arrays.toString(userDetails)); + return new EditContactCommand(userDetails, userIndex); + } catch (InvalidFlagException e) { + return new FailedCommand(FailedCommandType.INVALID_FLAG); + } catch (IndexOutOfBoundsException e) { + return new FailedCommand(FailedCommandType.INVALID_INDEX); + } + } } From 0ffb00638cfd8b022e217bda366272a0d6fd9a75 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 6 Oct 2021 22:58:45 +0800 Subject: [PATCH 066/756] Add print contact with index --- src/main/java/seedu/ui/TextUi.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index b8e80bc36d..41fa87fd9b 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -64,6 +64,10 @@ public static void addContactMessage(String contactName, int listSize) { printDoubleLineMessage(message); } + public static void printContactWithIndex(int index, String contactName) { + System.out.println(index + ". " + contactName); + } + public static void viewContactsListMessage(int listSize) { String message = "ConTech has " + listSize + " contacts stored.\n" + "Here's the list :"; From 2dd8f33447243c467947d0317eb7e2f2627b7040 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 6 Oct 2021 22:59:03 +0800 Subject: [PATCH 067/756] Refactor code --- .../java/seedu/command/ListContactsCommand.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/command/ListContactsCommand.java b/src/main/java/seedu/command/ListContactsCommand.java index 6f118a7996..43fe5951be 100644 --- a/src/main/java/seedu/command/ListContactsCommand.java +++ b/src/main/java/seedu/command/ListContactsCommand.java @@ -6,11 +6,22 @@ public class ListContactsCommand extends Command { @Override public void execute() { int listSize = contactList.getListSize(); + if (listSize == 0) { + TextUi.viewContactsEmptyListMessage(); + } else { + listAllContacts(listSize); + } + } + private void listAllContacts(int listSize) { TextUi.viewContactsListMessage(listSize); - for (int i = 0; i < listSize; i++) { - System.out.println(i + ". " + contactList.getContactAtIndex(i).getName()); + for (int index = 0; index < listSize; index++) { + TextUi.printContactWithIndex(index, getContactName(index)); } TextUi.printBottomLine(); } + + private String getContactName(int index) { + return contactList.getContactAtIndex(index).getName(); + } } From 3beb2656e00bef716a14d811aa6440cd93bbe252 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 6 Oct 2021 23:01:42 +0800 Subject: [PATCH 068/756] Rename contact print functions --- src/main/java/seedu/command/ListContactsCommand.java | 4 ++-- src/main/java/seedu/ui/TextUi.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/seedu/command/ListContactsCommand.java b/src/main/java/seedu/command/ListContactsCommand.java index 43fe5951be..49d09b98fa 100644 --- a/src/main/java/seedu/command/ListContactsCommand.java +++ b/src/main/java/seedu/command/ListContactsCommand.java @@ -7,14 +7,14 @@ public class ListContactsCommand extends Command { public void execute() { int listSize = contactList.getListSize(); if (listSize == 0) { - TextUi.viewContactsEmptyListMessage(); + TextUi.contactsEmptyListMessage(); } else { listAllContacts(listSize); } } private void listAllContacts(int listSize) { - TextUi.viewContactsListMessage(listSize); + TextUi.contactsListMessage(listSize); for (int index = 0; index < listSize; index++) { TextUi.printContactWithIndex(index, getContactName(index)); } diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 41fa87fd9b..c2f038f26b 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -68,13 +68,13 @@ public static void printContactWithIndex(int index, String contactName) { System.out.println(index + ". " + contactName); } - public static void viewContactsListMessage(int listSize) { + public static void contactsListMessage(int listSize) { String message = "ConTech has " + listSize + " contacts stored.\n" + "Here's the list :"; printDoubleLineMessage(message); } - public static void viewContactsEmptyListMessage() { + public static void contactsEmptyListMessage() { String message = "You have not stored any contacts in ConTech"; printDoubleLineMessage(message); } From 8c1c09fa99d31e5d993ab46f67028bbe16321253 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Wed, 6 Oct 2021 23:02:57 +0800 Subject: [PATCH 069/756] Implement view command in MainParser --- src/main/java/seedu/parser/MainParser.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index b0c12ee3e6..f5137cd102 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -1,15 +1,13 @@ package seedu.parser; -import seedu.command.AddContactCommand; -import seedu.command.Command; -import seedu.command.ExitCommand; -import seedu.command.FailedCommand; +import seedu.command.*; import seedu.contact.DetailType; import seedu.exception.InvalidFlagException; public class MainParser { private static final String ADD_TASK_COMD = "add"; private static final String EXIT_COMD = "exit"; + private static final String VIEW_COMD = "view"; private static final int COMD_WORD_INDEX = 0; private static final int ISOLATE_COMD_WORD = 2; @@ -27,6 +25,9 @@ public Command parseCommand(String userInput) { case EXIT_COMD: command = new ExitCommand(); break; + case VIEW_COMD: + command = parseViewContact(userInput); + break; default: command = new FailedCommand(FailedCommandType.GENERAL); } From 05e962e797175278c4d9951861ae19f2b9d851fe Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Wed, 6 Oct 2021 23:03:29 +0800 Subject: [PATCH 070/756] Implement parseViewContact method to get index --- src/main/java/seedu/parser/MainParser.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index f5137cd102..551c4a90d9 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -48,4 +48,9 @@ private Command parseAddContact(String userInput) { return new FailedCommand(FailedCommandType.INVALID_FLAG); } } + + private Command parseViewContact(String userInput) { + String[] destructuredInputs = userInput.split(" ", ISOLATE_COMD_WORD); + return new ViewCommand(Integer.parseInt(destructuredInputs[1])); + } } From 0cb83c96b38b1718544c03073961d509d653c649 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Wed, 6 Oct 2021 23:03:55 +0800 Subject: [PATCH 071/756] Implement viewContactMessage in TextUi --- src/main/java/seedu/ui/TextUi.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 50f07d5fae..f742a2666e 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -1,5 +1,7 @@ package seedu.ui; +import seedu.contact.Contact; + import java.util.Scanner; public class TextUi { @@ -57,6 +59,12 @@ public static void addContactMessage(String contactName, int listSize) { printDoubleLineMessage(message); } + public static void viewContactMessage(Contact viewingContact, int index) { + String message = index + ". " + "Name: " + viewingContact.getName() + " GitHub: " + + viewingContact.getGithub(); + printDoubleLineMessage(message); + } + public static void exitMessage() { String message = "ConTech will now shutdown.\n" + "We hope you have enjoyed using it."; From 749c815db96d84c60b372d6d01cb5bff11c3f6e7 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Wed, 6 Oct 2021 23:04:20 +0800 Subject: [PATCH 072/756] Implement ViewCommand for command execution --- src/main/java/seedu/command/ViewCommand.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/main/java/seedu/command/ViewCommand.java diff --git a/src/main/java/seedu/command/ViewCommand.java b/src/main/java/seedu/command/ViewCommand.java new file mode 100644 index 0000000000..0970ae9efb --- /dev/null +++ b/src/main/java/seedu/command/ViewCommand.java @@ -0,0 +1,17 @@ +package seedu.command; + +import seedu.contact.Contact; +import seedu.ui.TextUi; + +public class ViewCommand extends Command{ + private final int index; + + public ViewCommand(int index) { + this.index = index; + } + + public void execute() { + Contact viewingContact = contactList.getContactAtIndex(index); + TextUi.viewContactMessage(viewingContact, index); + } +} From 571053d8bd798b3649d339f736dea2138d77e037 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Wed, 6 Oct 2021 23:11:25 +0800 Subject: [PATCH 073/756] Add new view input and change expected output --- text-ui-test/ACTUAL.TXT | 4 ++++ text-ui-test/EXPECTED-UNIX.TXT | 4 ++++ text-ui-test/EXPECTED.TXT | 4 ++++ text-ui-test/input.txt | 1 + 4 files changed, 13 insertions(+) diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index 26e883946b..2d7c45223c 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -27,6 +27,10 @@ ConTech has added the specified contact: lezong You now have 2 contact(s). ____________________________________________________________ +____________________________________________________________ +0. Name: ng andre GitHub: ng-andre +____________________________________________________________ + ____________________________________________________________ ConTech will now shutdown. We hope you have enjoyed using it. diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index 26e883946b..2d7c45223c 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -27,6 +27,10 @@ ConTech has added the specified contact: lezong You now have 2 contact(s). ____________________________________________________________ +____________________________________________________________ +0. Name: ng andre GitHub: ng-andre +____________________________________________________________ + ____________________________________________________________ ConTech will now shutdown. We hope you have enjoyed using it. diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 26e883946b..2d7c45223c 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -27,6 +27,10 @@ ConTech has added the specified contact: lezong You now have 2 contact(s). ____________________________________________________________ +____________________________________________________________ +0. Name: ng andre GitHub: ng-andre +____________________________________________________________ + ____________________________________________________________ ConTech will now shutdown. We hope you have enjoyed using it. diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index 2a8005f15d..46c8923c77 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -1,3 +1,4 @@ add -n ng andre -g ng-andre add -g lezongmun -n lezong +view 0 exit \ No newline at end of file From 84483ee957527bcaa8b0cc877e0ab52977a4b8b2 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Wed, 6 Oct 2021 23:16:01 +0800 Subject: [PATCH 074/756] Bug fix for first flag not being detected --- src/main/java/seedu/parser/EditContactParser.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/EditContactParser.java b/src/main/java/seedu/parser/EditContactParser.java index 17f3c1a9ee..8d6bdcc8c5 100644 --- a/src/main/java/seedu/parser/EditContactParser.java +++ b/src/main/java/seedu/parser/EditContactParser.java @@ -10,7 +10,8 @@ public class EditContactParser extends ContactParser { public String[] parseContactDetails(String userInput) throws InvalidFlagException { String[] contactDetails = new String[NUMBER_OF_DETAILS]; Arrays.fill(contactDetails, null); - String[] destructuredInputs = userInput.split(DETAIL_SEPARATOR); + String[] destructuredInputs = (" " + userInput).split(DETAIL_SEPARATOR); + System.out.println("editcontactparser" + Arrays.toString(destructuredInputs)); for (int i = CONTACT_PARAMS_START_INDEX; i < destructuredInputs.length; i++) { parseDetail(contactDetails, destructuredInputs[i]); } From 035a2c8d0b7275afbb5db03e3ded5c31d7bf34b7 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Wed, 6 Oct 2021 23:16:34 +0800 Subject: [PATCH 075/756] Refactor code according to checkstyle --- src/main/java/seedu/command/ViewCommand.java | 2 +- src/main/java/seedu/parser/MainParser.java | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/command/ViewCommand.java b/src/main/java/seedu/command/ViewCommand.java index 0970ae9efb..ec9360b6a0 100644 --- a/src/main/java/seedu/command/ViewCommand.java +++ b/src/main/java/seedu/command/ViewCommand.java @@ -3,7 +3,7 @@ import seedu.contact.Contact; import seedu.ui.TextUi; -public class ViewCommand extends Command{ +public class ViewCommand extends Command { private final int index; public ViewCommand(int index) { diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 551c4a90d9..834b4ee042 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -1,6 +1,10 @@ package seedu.parser; -import seedu.command.*; +import seedu.command.Command; +import seedu.command.ViewCommand; +import seedu.command.AddContactCommand; +import seedu.command.FailedCommand; +import seedu.command.ExitCommand; import seedu.contact.DetailType; import seedu.exception.InvalidFlagException; From f28f169dbcd29b9d850c5fb2a5f8a2274fb9abc4 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Wed, 6 Oct 2021 23:27:57 +0800 Subject: [PATCH 076/756] Handle exception for invalid index and minor refactoring --- src/main/java/seedu/parser/EditContactParser.java | 4 +++- src/main/java/seedu/parser/MainParser.java | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/parser/EditContactParser.java b/src/main/java/seedu/parser/EditContactParser.java index 8d6bdcc8c5..80f81cdd08 100644 --- a/src/main/java/seedu/parser/EditContactParser.java +++ b/src/main/java/seedu/parser/EditContactParser.java @@ -6,11 +6,13 @@ import java.util.Arrays; public class EditContactParser extends ContactParser { + public static final String BUFFER = " "; + @Override public String[] parseContactDetails(String userInput) throws InvalidFlagException { String[] contactDetails = new String[NUMBER_OF_DETAILS]; Arrays.fill(contactDetails, null); - String[] destructuredInputs = (" " + userInput).split(DETAIL_SEPARATOR); + String[] destructuredInputs = (BUFFER + userInput).split(DETAIL_SEPARATOR); System.out.println("editcontactparser" + Arrays.toString(destructuredInputs)); for (int i = CONTACT_PARAMS_START_INDEX; i < destructuredInputs.length; i++) { parseDetail(contactDetails, destructuredInputs[i]); diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 23e06af5b0..9cf0f217cb 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -66,14 +66,14 @@ private Command parseEditContact(String userInput) { //userInput is raw user inp try { //split into array of size 3 with command, index and details String[] details = userInput.split(" ", NUMBER_OF_EDIT_DETAILS); + System.out.println(Arrays.toString(details)); int userIndex = Integer.parseInt(details[EDIT_USER_INDEX]) - 1; - String[] userDetails = editContactParser.parseContactDetails(details[ISOLATE_USER_INPUT]); System.out.println(Arrays.toString(userDetails)); return new EditContactCommand(userDetails, userIndex); } catch (InvalidFlagException e) { return new FailedCommand(FailedCommandType.INVALID_FLAG); - } catch (IndexOutOfBoundsException e) { + } catch (IndexOutOfBoundsException | NumberFormatException e) { return new FailedCommand(FailedCommandType.INVALID_INDEX); } } From 947c6e099bc4ced69ccde5a44df988aad24a7627 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Wed, 6 Oct 2021 23:33:03 +0800 Subject: [PATCH 077/756] Refactor parseDetail method into abstract class ContactParser --- .../java/seedu/parser/AddContactParser.java | 24 ----------------- src/main/java/seedu/parser/ContactParser.java | 26 +++++++++++++++++++ .../java/seedu/parser/EditContactParser.java | 16 ------------ 3 files changed, 26 insertions(+), 40 deletions(-) diff --git a/src/main/java/seedu/parser/AddContactParser.java b/src/main/java/seedu/parser/AddContactParser.java index b24c6aa5a3..9d4697f312 100644 --- a/src/main/java/seedu/parser/AddContactParser.java +++ b/src/main/java/seedu/parser/AddContactParser.java @@ -24,28 +24,4 @@ public String[] parseContactDetails(String userInput) throws InvalidFlagExceptio } return contactDetails; } - - /** - * This method takes in the contactDetails array and populates it with contact details. - * It will sift out the flags to decide what details to populate, using the - * enumeration from DetailType. - * @param contactDetails String array containing contact details - * @param detail Unparsed detail - * @throws InvalidFlagException If the flag given is not recognised - */ - private void parseDetail(String[] contactDetails, String detail) throws InvalidFlagException { - String[] destructuredDetails = detail.split(" ", DETAILS_TO_SPLIT); - int indexToStore; - switch (destructuredDetails[FLAG_INDEX_IN_DETAILS]) { - case NAME_FLAG: - indexToStore = DetailType.NAME.getIndex(); - break; - case GITHUB_FLAG: - indexToStore = DetailType.GITHUB.getIndex(); - break; - default: - throw new InvalidFlagException(); - } - contactDetails[indexToStore] = destructuredDetails[DETAIL_INDEX_IN_DETAILS]; - } } diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index f47a9dba45..1a1ccd9823 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -1,5 +1,6 @@ package seedu.parser; +import seedu.contact.DetailType; import seedu.exception.InvalidFlagException; public abstract class ContactParser { @@ -16,4 +17,29 @@ public abstract class ContactParser { public static final String GITHUB_FLAG = "g"; public abstract String[] parseContactDetails(String userInput) throws InvalidFlagException; + + /** + * This method takes in the contactDetails array and populates it with contact details. + * It will sift out the flags to decide what details to populate, using the + * enumeration from DetailType. + * + * @param contactDetails String array containing contact details + * @param detail Unparsed detail + * @throws InvalidFlagException If the flag given is not recognised + */ + public void parseDetail(String[] contactDetails, String detail) throws InvalidFlagException { + String[] destructuredDetails = detail.split(" ", NUMBER_OF_EDIT_DETAILS); + int indexToStore; + switch (destructuredDetails[FLAG_INDEX_IN_DETAILS]) { + case NAME_FLAG: + indexToStore = DetailType.NAME.getIndex(); + break; + case GITHUB_FLAG: + indexToStore = DetailType.GITHUB.getIndex(); + break; + default: + throw new InvalidFlagException(); + } + contactDetails[indexToStore] = destructuredDetails[DETAIL_INDEX_IN_DETAILS]; + } } diff --git a/src/main/java/seedu/parser/EditContactParser.java b/src/main/java/seedu/parser/EditContactParser.java index 80f81cdd08..86f0584960 100644 --- a/src/main/java/seedu/parser/EditContactParser.java +++ b/src/main/java/seedu/parser/EditContactParser.java @@ -19,20 +19,4 @@ public String[] parseContactDetails(String userInput) throws InvalidFlagExceptio } return contactDetails; } - - private void parseDetail(String[] contactDetails, String detail) throws InvalidFlagException { - String[] destructuredDetails = detail.split(" ", NUMBER_OF_EDIT_DETAILS); - int indexToStore; - switch (destructuredDetails[FLAG_INDEX_IN_DETAILS]) { - case NAME_FLAG: - indexToStore = DetailType.NAME.getIndex(); - break; - case GITHUB_FLAG: - indexToStore = DetailType.GITHUB.getIndex(); - break; - default: - throw new InvalidFlagException(); - } - contactDetails[indexToStore] = destructuredDetails[DETAIL_INDEX_IN_DETAILS]; - } } From 49a9c39674f51f78018547ad87122abbcf821d1b Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Wed, 6 Oct 2021 23:36:58 +0800 Subject: [PATCH 078/756] Remove debugging print statements --- src/main/java/seedu/parser/EditContactParser.java | 1 - src/main/java/seedu/parser/MainParser.java | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/main/java/seedu/parser/EditContactParser.java b/src/main/java/seedu/parser/EditContactParser.java index 86f0584960..630e05061e 100644 --- a/src/main/java/seedu/parser/EditContactParser.java +++ b/src/main/java/seedu/parser/EditContactParser.java @@ -13,7 +13,6 @@ public String[] parseContactDetails(String userInput) throws InvalidFlagExceptio String[] contactDetails = new String[NUMBER_OF_DETAILS]; Arrays.fill(contactDetails, null); String[] destructuredInputs = (BUFFER + userInput).split(DETAIL_SEPARATOR); - System.out.println("editcontactparser" + Arrays.toString(destructuredInputs)); for (int i = CONTACT_PARAMS_START_INDEX; i < destructuredInputs.length; i++) { parseDetail(contactDetails, destructuredInputs[i]); } diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 9cf0f217cb..72287affe7 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -66,10 +66,8 @@ private Command parseEditContact(String userInput) { //userInput is raw user inp try { //split into array of size 3 with command, index and details String[] details = userInput.split(" ", NUMBER_OF_EDIT_DETAILS); - System.out.println(Arrays.toString(details)); int userIndex = Integer.parseInt(details[EDIT_USER_INDEX]) - 1; String[] userDetails = editContactParser.parseContactDetails(details[ISOLATE_USER_INPUT]); - System.out.println(Arrays.toString(userDetails)); return new EditContactCommand(userDetails, userIndex); } catch (InvalidFlagException e) { return new FailedCommand(FailedCommandType.INVALID_FLAG); From 2cbee2e1fb3248ae2b354ea33c11045ea7d20606 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Wed, 6 Oct 2021 23:38:07 +0800 Subject: [PATCH 079/756] Remove unused variables in MainParser --- src/main/java/seedu/parser/MainParser.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 72287affe7..8639372077 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -7,9 +7,6 @@ import seedu.command.FailedCommand; import seedu.contact.DetailType; import seedu.exception.InvalidFlagException; -import seedu.contact.Contact; - -import java.util.Arrays; public class MainParser { private static final String ADD_CONTACT_COMD = "add"; @@ -18,7 +15,6 @@ public class MainParser { private static final int COMD_WORD_INDEX = 0; private static final int EDIT_USER_INDEX = 1; - private static final int EDIT_INFO_INDEX = 2; private static final int ISOLATE_COMD_WORD = 2; private static final int ISOLATE_USER_INPUT = 2; public static final int NUMBER_OF_EDIT_DETAILS = 3; From 3af9b7c3963bbd3e013de7d51a8aa1a1d7c33652 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Thu, 7 Oct 2021 01:03:17 +0800 Subject: [PATCH 080/756] Fix checkstyle --- src/main/java/seedu/parser/ContactParser.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index bc789daafa..618e1134aa 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -18,7 +18,8 @@ public abstract class ContactParser { public static final String NAME_FLAG = "n"; public static final String GITHUB_FLAG = "g"; - public abstract String[] parseContactDetails(String userInput) throws InvalidFlagException, MissingArgException, MissingDetailException; + public abstract String[] parseContactDetails(String userInput) throws InvalidFlagException, + MissingArgException, MissingDetailException; /** * This method takes in the contactDetails array and populates it with contact details. From 36494c233bb666ff1a1605f69e57dbdf6ca4e390 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Thu, 7 Oct 2021 01:08:55 +0800 Subject: [PATCH 081/756] Catch exception for ArrayIndexOutOfBoundsException --- src/main/java/seedu/parser/MainParser.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index d20a01a2bd..454469435e 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -106,6 +106,8 @@ private Command parseViewContact(String userInput) { return new ViewCommand(Integer.parseInt(destructuredInputs[1])); } catch (NumberFormatException e) { return new FailedCommand(FailedCommandType.INVALID_NUM); + } catch (IndexOutOfBoundsException e) { + return new FailedCommand(FailedCommandType.INVALID_INDEX); } } @@ -122,6 +124,8 @@ private Command parseDeleteContact(String userInput) { return new DeleteContactCommand(deletedIndex); } catch (NumberFormatException e) { return new FailedCommand(FailedCommandType.INVALID_NUM); + } catch (IndexOutOfBoundsException e) { + return new FailedCommand(FailedCommandType.INVALID_INDEX); } } From ecb9de947ed0d6bd8ee3f8e79ac655d17c481830 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Thu, 7 Oct 2021 01:30:57 +0800 Subject: [PATCH 082/756] Fix exception errors --- .../java/seedu/parser/AddContactParser.java | 29 +++++++++++++++++++ src/main/java/seedu/parser/ContactParser.java | 24 --------------- .../java/seedu/parser/EditContactParser.java | 25 ++++++++++++++++ src/main/java/seedu/parser/MainParser.java | 4 --- 4 files changed, 54 insertions(+), 28 deletions(-) diff --git a/src/main/java/seedu/parser/AddContactParser.java b/src/main/java/seedu/parser/AddContactParser.java index a8521be956..2074fad404 100644 --- a/src/main/java/seedu/parser/AddContactParser.java +++ b/src/main/java/seedu/parser/AddContactParser.java @@ -30,4 +30,33 @@ public String[] parseContactDetails(String userInput) throws InvalidFlagExceptio } return contactDetails; } + + /** + * This method takes in the contactDetails array and populates it with contact details. + * It will sift out the flags to decide what details to populate, using the + * enumeration from DetailType. + * + * @param contactDetails String array containing contact details + * @param detail Unparsed detail + * @throws InvalidFlagException If the flag given is not recognised + */ + public void parseDetail(String[] contactDetails, String detail) throws InvalidFlagException, + MissingDetailException { + String[] destructuredDetails = detail.split(" ", NUMBER_OF_DETAILS); + if (destructuredDetails.length < 2) { + throw new MissingDetailException(); + } + int indexToStore; + switch (destructuredDetails[FLAG_INDEX_IN_DETAILS]) { + case NAME_FLAG: + indexToStore = DetailType.NAME.getIndex(); + break; + case GITHUB_FLAG: + indexToStore = DetailType.GITHUB.getIndex(); + break; + default: + throw new InvalidFlagException(); + } + contactDetails[indexToStore] = destructuredDetails[DETAIL_INDEX_IN_DETAILS]; + } } diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index 618e1134aa..a7a3682124 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -21,28 +21,4 @@ public abstract class ContactParser { public abstract String[] parseContactDetails(String userInput) throws InvalidFlagException, MissingArgException, MissingDetailException; - /** - * This method takes in the contactDetails array and populates it with contact details. - * It will sift out the flags to decide what details to populate, using the - * enumeration from DetailType. - * - * @param contactDetails String array containing contact details - * @param detail Unparsed detail - * @throws InvalidFlagException If the flag given is not recognised - */ - public void parseDetail(String[] contactDetails, String detail) throws InvalidFlagException { - String[] destructuredDetails = detail.split(" ", NUMBER_OF_EDIT_DETAILS); - int indexToStore; - switch (destructuredDetails[FLAG_INDEX_IN_DETAILS]) { - case NAME_FLAG: - indexToStore = DetailType.NAME.getIndex(); - break; - case GITHUB_FLAG: - indexToStore = DetailType.GITHUB.getIndex(); - break; - default: - throw new InvalidFlagException(); - } - contactDetails[indexToStore] = destructuredDetails[DETAIL_INDEX_IN_DETAILS]; - } } diff --git a/src/main/java/seedu/parser/EditContactParser.java b/src/main/java/seedu/parser/EditContactParser.java index 630e05061e..22d57abfc5 100644 --- a/src/main/java/seedu/parser/EditContactParser.java +++ b/src/main/java/seedu/parser/EditContactParser.java @@ -18,4 +18,29 @@ public String[] parseContactDetails(String userInput) throws InvalidFlagExceptio } return contactDetails; } + + /** + * This method takes in the contactDetails array and populates it with contact details. + * It will sift out the flags to decide what details to populate, using the + * enumeration from DetailType. + * + * @param contactDetails String array containing contact details + * @param detail Unparsed detail + * @throws InvalidFlagException If the flag given is not recognised + */ + public void parseDetail(String[] contactDetails, String detail) throws InvalidFlagException { + String[] destructuredDetails = detail.split(" ", NUMBER_OF_EDIT_DETAILS); + int indexToStore; + switch (destructuredDetails[FLAG_INDEX_IN_DETAILS]) { + case NAME_FLAG: + indexToStore = DetailType.NAME.getIndex(); + break; + case GITHUB_FLAG: + indexToStore = DetailType.GITHUB.getIndex(); + break; + default: + throw new InvalidFlagException(); + } + contactDetails[indexToStore] = destructuredDetails[DETAIL_INDEX_IN_DETAILS]; + } } diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 454469435e..d20a01a2bd 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -106,8 +106,6 @@ private Command parseViewContact(String userInput) { return new ViewCommand(Integer.parseInt(destructuredInputs[1])); } catch (NumberFormatException e) { return new FailedCommand(FailedCommandType.INVALID_NUM); - } catch (IndexOutOfBoundsException e) { - return new FailedCommand(FailedCommandType.INVALID_INDEX); } } @@ -124,8 +122,6 @@ private Command parseDeleteContact(String userInput) { return new DeleteContactCommand(deletedIndex); } catch (NumberFormatException e) { return new FailedCommand(FailedCommandType.INVALID_NUM); - } catch (IndexOutOfBoundsException e) { - return new FailedCommand(FailedCommandType.INVALID_INDEX); } } From 7f540e2be723eb0d044262f23bac99b8f797f691 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Thu, 7 Oct 2021 11:55:44 +0800 Subject: [PATCH 083/756] Add exception handling for missing inputs in edit function --- src/main/java/seedu/parser/MainParser.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index d20a01a2bd..1162186c55 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -14,6 +14,8 @@ import seedu.exception.MissingArgException; import seedu.exception.MissingDetailException; +import java.util.Arrays; + public class MainParser { private static final String ADD_CONTACT_COMD = "add"; private static final String EDIT_CONTACT_COMD = "edit"; @@ -84,12 +86,18 @@ private Command parseEditContact(String userInput) { // userInput is raw user in try { // split into array of size 3 with command, index and details String[] details = userInput.split(" ", NUMBER_OF_EDIT_DETAILS); + System.out.println(Arrays.toString(details)); + if (details[2].trim().equalsIgnoreCase("")) { + throw new MissingDetailException(); + } int userIndex = Integer.parseInt(details[EDIT_USER_INDEX]); String[] userDetails = editContactParser.parseContactDetails(details[ISOLATE_USER_INPUT]); return new EditContactCommand(userDetails, userIndex); } catch (InvalidFlagException e) { return new FailedCommand(FailedCommandType.INVALID_FLAG); - } catch (IndexOutOfBoundsException | NumberFormatException e) { + } catch (IndexOutOfBoundsException | MissingDetailException e) { + return new FailedCommand(FailedCommandType.MISSING_ARG); + } catch (NumberFormatException e) { return new FailedCommand(FailedCommandType.INVALID_INDEX); } } From 268c5fd5da2fbe7dcc328509b9967bd0982b79c4 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Thu, 7 Oct 2021 12:01:22 +0800 Subject: [PATCH 084/756] Require name input for AddContact command --- src/main/java/seedu/parser/MainParser.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 1162186c55..3331e1ca15 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -29,6 +29,7 @@ public class MainParser { private static final int ISOLATE_COMD_WORD = 2; private static final int ISOLATE_USER_INPUT = 2; public static final int NUMBER_OF_EDIT_DETAILS = 3; + public static final int NAME_INDEX = 0; private ContactParser contactParser; private AddContactParser addContactParser = new AddContactParser(); @@ -71,6 +72,10 @@ private Command parseAddContact(String userInput) { contactParser = addContactParser; try { String[] details = contactParser.parseContactDetails(userInput); + //check if name is specified in input + if (details[NAME_INDEX] == null) { + throw new MissingDetailException(); + } return new AddContactCommand(details[DetailType.NAME.getIndex()], details[DetailType.GITHUB.getIndex()]); } catch (InvalidFlagException e) { return new FailedCommand(FailedCommandType.INVALID_FLAG); @@ -86,8 +91,7 @@ private Command parseEditContact(String userInput) { // userInput is raw user in try { // split into array of size 3 with command, index and details String[] details = userInput.split(" ", NUMBER_OF_EDIT_DETAILS); - System.out.println(Arrays.toString(details)); - if (details[2].trim().equalsIgnoreCase("")) { + if (details[ISOLATE_USER_INPUT].trim().equalsIgnoreCase("")) { throw new MissingDetailException(); } int userIndex = Integer.parseInt(details[EDIT_USER_INDEX]); From abfe8fdaff1b1201e34d68b3c9f6d8a32b1ad233 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Thu, 7 Oct 2021 12:10:38 +0800 Subject: [PATCH 085/756] Handle exception for missing parameters for edit function --- src/main/java/seedu/parser/EditContactParser.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/parser/EditContactParser.java b/src/main/java/seedu/parser/EditContactParser.java index 22d57abfc5..e2524f6d6b 100644 --- a/src/main/java/seedu/parser/EditContactParser.java +++ b/src/main/java/seedu/parser/EditContactParser.java @@ -2,6 +2,7 @@ import seedu.contact.DetailType; import seedu.exception.InvalidFlagException; +import seedu.exception.MissingDetailException; import java.util.Arrays; @@ -9,7 +10,7 @@ public class EditContactParser extends ContactParser { public static final String BUFFER = " "; @Override - public String[] parseContactDetails(String userInput) throws InvalidFlagException { + public String[] parseContactDetails(String userInput) throws InvalidFlagException, MissingDetailException { String[] contactDetails = new String[NUMBER_OF_DETAILS]; Arrays.fill(contactDetails, null); String[] destructuredInputs = (BUFFER + userInput).split(DETAIL_SEPARATOR); @@ -28,8 +29,12 @@ public String[] parseContactDetails(String userInput) throws InvalidFlagExceptio * @param detail Unparsed detail * @throws InvalidFlagException If the flag given is not recognised */ - public void parseDetail(String[] contactDetails, String detail) throws InvalidFlagException { + public void parseDetail(String[] contactDetails, String detail) + throws InvalidFlagException, MissingDetailException { String[] destructuredDetails = detail.split(" ", NUMBER_OF_EDIT_DETAILS); + if (destructuredDetails[1].trim().equalsIgnoreCase("")) { + throw new MissingDetailException(); + } int indexToStore; switch (destructuredDetails[FLAG_INDEX_IN_DETAILS]) { case NAME_FLAG: From 41a32ad7edbe72023f1a8bd3ba81428c3b92cc66 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Thu, 7 Oct 2021 19:58:30 +0800 Subject: [PATCH 086/756] handle exception for index out of bounds --- src/main/java/seedu/command/EditContactCommand.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index 58491a5d27..ffd7ef2187 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -13,7 +13,11 @@ public EditContactCommand(String[] contactDetails, int contactIndex) { } public void execute() { - contactList.editContact(contactDetails, contactIndex); - TextUi.editContactMessage(contactList.getContactAtIndex(contactIndex).getName()); + try { + contactList.editContact(contactDetails, contactIndex); + TextUi.editContactMessage(contactList.getContactAtIndex(contactIndex).getName()); + } catch (IndexOutOfBoundsException e) { + TextUi.invalidIndexMessage(); + } } } From 1e7066cdf386b542183d46552a7432e5305f98d6 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Thu, 7 Oct 2021 19:59:47 +0800 Subject: [PATCH 087/756] Add missing name message for textUI and MISSING_NAME FailedCommand and exception --- src/main/java/seedu/command/FailedCommand.java | 3 +++ src/main/java/seedu/exception/MissingNameException.java | 4 ++++ src/main/java/seedu/parser/FailedCommandType.java | 2 +- src/main/java/seedu/parser/MainParser.java | 4 +++- src/main/java/seedu/ui/TextUi.java | 6 ++++++ 5 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 src/main/java/seedu/exception/MissingNameException.java diff --git a/src/main/java/seedu/command/FailedCommand.java b/src/main/java/seedu/command/FailedCommand.java index ce78815502..629b0f7a6e 100644 --- a/src/main/java/seedu/command/FailedCommand.java +++ b/src/main/java/seedu/command/FailedCommand.java @@ -36,6 +36,9 @@ public void execute() { case NUM_OUT_OF_BOUND: TextUi.numOutOfRangeMessage(contactList.getListSize() - 1); break; + case MISSING_NAME: + TextUi.missingNameMessage(); + break; default: return; } diff --git a/src/main/java/seedu/exception/MissingNameException.java b/src/main/java/seedu/exception/MissingNameException.java new file mode 100644 index 0000000000..683ffcf8cd --- /dev/null +++ b/src/main/java/seedu/exception/MissingNameException.java @@ -0,0 +1,4 @@ +package seedu.exception; + +public class MissingNameException extends Exception { +} diff --git a/src/main/java/seedu/parser/FailedCommandType.java b/src/main/java/seedu/parser/FailedCommandType.java index ef99ce6fdf..559a423077 100644 --- a/src/main/java/seedu/parser/FailedCommandType.java +++ b/src/main/java/seedu/parser/FailedCommandType.java @@ -1,5 +1,5 @@ package seedu.parser; public enum FailedCommandType { - GENERAL, INVALID_FLAG, MISSING_ARG, MISSING_DETAIL, INVALID_NUM, INVALID_FORMAT, NUM_OUT_OF_BOUND, INVALID_INDEX + GENERAL, INVALID_FLAG, MISSING_ARG, MISSING_DETAIL, INVALID_NUM, INVALID_FORMAT, NUM_OUT_OF_BOUND, INVALID_INDEX, MISSING_NAME; } diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 3331e1ca15..f08c632591 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -74,13 +74,15 @@ private Command parseAddContact(String userInput) { String[] details = contactParser.parseContactDetails(userInput); //check if name is specified in input if (details[NAME_INDEX] == null) { - throw new MissingDetailException(); + throw new MissingNameException(); } return new AddContactCommand(details[DetailType.NAME.getIndex()], details[DetailType.GITHUB.getIndex()]); } catch (InvalidFlagException e) { return new FailedCommand(FailedCommandType.INVALID_FLAG); } catch (MissingArgException e) { return new FailedCommand(FailedCommandType.MISSING_ARG); + } catch (MissingNameException e) { + return new FailedCommand(FailedCommandType.MISSING_NAME); } catch (MissingDetailException e) { return new FailedCommand(FailedCommandType.MISSING_DETAIL); } diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 48cd6c2485..c1435befae 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -134,6 +134,12 @@ public static void invalidFormatMessage() { printDoubleLineMessage(message); } + public static void missingNameMessage() { + String message = "There are missing details.\n" + + "Please specify a name when creating a contact with the flag -n"; + printDoubleLineMessage(message); + } + public static void numOutOfRangeMessage(int listSize) { String message; if (listSize == 0) { From 15b82f8027796459d4b1b98488304fab2eba392e Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Thu, 7 Oct 2021 19:59:55 +0800 Subject: [PATCH 088/756] Update constants --- src/main/java/seedu/parser/ContactParser.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index a7a3682124..26273b0b17 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -11,9 +11,10 @@ public abstract class ContactParser { public static final int NUMBER_OF_EDIT_DETAILS = 3; public static final String DETAIL_SEPARATOR = " -"; - public static final int DETAILS_TO_SPLIT = 2; public static final int FLAG_INDEX_IN_DETAILS = 0; public static final int DETAIL_INDEX_IN_DETAILS = 1; + public static final int EDIT_USER_INDEX = 1; + public static final int USER_INFO_INDEX = 2; public static final String NAME_FLAG = "n"; public static final String GITHUB_FLAG = "g"; From e43df14dc7c00cc3c4193bb0eb8ba607c5bad25d Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Thu, 7 Oct 2021 20:00:21 +0800 Subject: [PATCH 089/756] Refactor methods for edit contact --- .../java/seedu/parser/EditContactParser.java | 28 +++++++++++++++---- src/main/java/seedu/parser/MainParser.java | 18 ++++++------ 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/src/main/java/seedu/parser/EditContactParser.java b/src/main/java/seedu/parser/EditContactParser.java index e2524f6d6b..b794e141fc 100644 --- a/src/main/java/seedu/parser/EditContactParser.java +++ b/src/main/java/seedu/parser/EditContactParser.java @@ -2,6 +2,7 @@ import seedu.contact.DetailType; import seedu.exception.InvalidFlagException; +import seedu.exception.MissingArgException; import seedu.exception.MissingDetailException; import java.util.Arrays; @@ -10,10 +11,16 @@ public class EditContactParser extends ContactParser { public static final String BUFFER = " "; @Override - public String[] parseContactDetails(String userInput) throws InvalidFlagException, MissingDetailException { - String[] contactDetails = new String[NUMBER_OF_DETAILS]; - Arrays.fill(contactDetails, null); - String[] destructuredInputs = (BUFFER + userInput).split(DETAIL_SEPARATOR); + public String[] parseContactDetails(String userInput) + throws InvalidFlagException, MissingDetailException, MissingArgException { + String[] inputDetails = userInput.split(" ", NUMBER_OF_EDIT_DETAILS); + if (inputDetails.length < 3 || inputDetails[2].trim().equalsIgnoreCase("")) { + //if arguments are missing e.g. edit 2 + throw new MissingArgException(); + } + String[] contactDetails = new String[NUMBER_OF_DETAILS]; //initialise null array of strings + //buffer is used to ensure first flag can be read + String[] destructuredInputs = (BUFFER + inputDetails[USER_INFO_INDEX]).split(DETAIL_SEPARATOR); for (int i = CONTACT_PARAMS_START_INDEX; i < destructuredInputs.length; i++) { parseDetail(contactDetails, destructuredInputs[i]); } @@ -32,7 +39,9 @@ public String[] parseContactDetails(String userInput) throws InvalidFlagExceptio public void parseDetail(String[] contactDetails, String detail) throws InvalidFlagException, MissingDetailException { String[] destructuredDetails = detail.split(" ", NUMBER_OF_EDIT_DETAILS); - if (destructuredDetails[1].trim().equalsIgnoreCase("")) { + //for commands that specify a flag, but do not specify any argument for that flag + //IndexOutOfBoundsException should not be thrown as the first if case will be true + if (destructuredDetails.length == 1 || destructuredDetails[1].trim().equalsIgnoreCase("")) { throw new MissingDetailException(); } int indexToStore; @@ -48,4 +57,13 @@ public void parseDetail(String[] contactDetails, String detail) } contactDetails[indexToStore] = destructuredDetails[DETAIL_INDEX_IN_DETAILS]; } + + public int getIndex(String input) throws MissingArgException { + String[] destructuredInputs = input.split(" ", NUMBER_OF_EDIT_DETAILS); + if (destructuredInputs.length < 3) { + //if arguments are missing e.g. edit 2 + throw new MissingArgException(); + } + return Integer.parseInt(destructuredInputs[EDIT_USER_INDEX]); + } } diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index f08c632591..0ea06b778f 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -13,6 +13,7 @@ import seedu.exception.InvalidFlagException; import seedu.exception.MissingArgException; import seedu.exception.MissingDetailException; +import seedu.exception.MissingNameException; import java.util.Arrays; @@ -25,7 +26,6 @@ public class MainParser { private static final String LIST_COMD = "list"; private static final int COMD_WORD_INDEX = 0; - private static final int EDIT_USER_INDEX = 1; private static final int ISOLATE_COMD_WORD = 2; private static final int ISOLATE_USER_INPUT = 2; public static final int NUMBER_OF_EDIT_DETAILS = 3; @@ -91,20 +91,18 @@ private Command parseAddContact(String userInput) { private Command parseEditContact(String userInput) { // userInput is raw user input contactParser = editContactParser; try { - // split into array of size 3 with command, index and details - String[] details = userInput.split(" ", NUMBER_OF_EDIT_DETAILS); - if (details[ISOLATE_USER_INPUT].trim().equalsIgnoreCase("")) { - throw new MissingDetailException(); - } - int userIndex = Integer.parseInt(details[EDIT_USER_INDEX]); - String[] userDetails = editContactParser.parseContactDetails(details[ISOLATE_USER_INPUT]); - return new EditContactCommand(userDetails, userIndex); + int userIndex = editContactParser.getIndex(userInput); //throws MissingArgException + String[] details = editContactParser.parseContactDetails(userInput); + //throws InvalidFlagException, MissingDetailException, MissingArgException + return new EditContactCommand(details, userIndex); } catch (InvalidFlagException e) { return new FailedCommand(FailedCommandType.INVALID_FLAG); - } catch (IndexOutOfBoundsException | MissingDetailException e) { + } catch (MissingArgException e) { return new FailedCommand(FailedCommandType.MISSING_ARG); } catch (NumberFormatException e) { return new FailedCommand(FailedCommandType.INVALID_INDEX); + } catch (MissingDetailException e) { + return new FailedCommand(FailedCommandType.MISSING_DETAIL); } } From b9931277a545b7485b1dd611dbae3faffa6334d9 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Thu, 7 Oct 2021 20:05:04 +0800 Subject: [PATCH 090/756] CheckStyle fix --- src/main/java/seedu/parser/FailedCommandType.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/FailedCommandType.java b/src/main/java/seedu/parser/FailedCommandType.java index 559a423077..d92cc5c16f 100644 --- a/src/main/java/seedu/parser/FailedCommandType.java +++ b/src/main/java/seedu/parser/FailedCommandType.java @@ -1,5 +1,6 @@ package seedu.parser; public enum FailedCommandType { - GENERAL, INVALID_FLAG, MISSING_ARG, MISSING_DETAIL, INVALID_NUM, INVALID_FORMAT, NUM_OUT_OF_BOUND, INVALID_INDEX, MISSING_NAME; + GENERAL, INVALID_FLAG, MISSING_ARG, MISSING_DETAIL, INVALID_NUM, + INVALID_FORMAT, NUM_OUT_OF_BOUND, INVALID_INDEX, MISSING_NAME; } From 933172eb9bca56767606ce9ee548d5037e29f355 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 7 Oct 2021 22:34:22 +0800 Subject: [PATCH 091/756] Implement error handling for empty details (full of spaces) --- src/main/java/seedu/parser/AddContactParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/AddContactParser.java b/src/main/java/seedu/parser/AddContactParser.java index 2074fad404..76dd73c223 100644 --- a/src/main/java/seedu/parser/AddContactParser.java +++ b/src/main/java/seedu/parser/AddContactParser.java @@ -43,7 +43,7 @@ public String[] parseContactDetails(String userInput) throws InvalidFlagExceptio public void parseDetail(String[] contactDetails, String detail) throws InvalidFlagException, MissingDetailException { String[] destructuredDetails = detail.split(" ", NUMBER_OF_DETAILS); - if (destructuredDetails.length < 2) { + if (destructuredDetails.length < 2 || destructuredDetails[1].trim().equalsIgnoreCase("")) { throw new MissingDetailException(); } int indexToStore; From 1a24ff9f156a0ab9f0cf9c13816fa61eda06941d Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 7 Oct 2021 22:34:54 +0800 Subject: [PATCH 092/756] Implement trim for user input to ignore trailing spaces --- src/main/java/seedu/ui/TextUi.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index c1435befae..7939633e4a 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -20,7 +20,7 @@ public TextUi() { } public String getUserInput() { - return scanner.nextLine(); + return scanner.nextLine().trim(); } // Used for print messages after user inputs From a20cfb95a59f5886d5e0c897a291731ee82a4dc4 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 7 Oct 2021 22:35:03 +0800 Subject: [PATCH 093/756] Delete commented out code --- src/main/java/seedu/parser/MainParser.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 0ea06b778f..4eaf7ba737 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -136,11 +136,4 @@ private Command parseDeleteContact(String userInput) { return new FailedCommand(FailedCommandType.INVALID_NUM); } } - - // Will create a function to parse details soon, hardcoding for V0.1 (7/10/21 - // version) - // private String parseDetail(String contactParameters, String tag) { - // - // } - } From 52ba12d61711c280d858d32a96a62badbb5f0828 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 7 Oct 2021 22:35:20 +0800 Subject: [PATCH 094/756] Remove safety code due to trimmed user input implementation --- src/main/java/seedu/parser/EditContactParser.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/seedu/parser/EditContactParser.java b/src/main/java/seedu/parser/EditContactParser.java index b794e141fc..afec72ecef 100644 --- a/src/main/java/seedu/parser/EditContactParser.java +++ b/src/main/java/seedu/parser/EditContactParser.java @@ -5,8 +5,6 @@ import seedu.exception.MissingArgException; import seedu.exception.MissingDetailException; -import java.util.Arrays; - public class EditContactParser extends ContactParser { public static final String BUFFER = " "; @@ -14,7 +12,7 @@ public class EditContactParser extends ContactParser { public String[] parseContactDetails(String userInput) throws InvalidFlagException, MissingDetailException, MissingArgException { String[] inputDetails = userInput.split(" ", NUMBER_OF_EDIT_DETAILS); - if (inputDetails.length < 3 || inputDetails[2].trim().equalsIgnoreCase("")) { + if (inputDetails.length < 3) { //if arguments are missing e.g. edit 2 throw new MissingArgException(); } From caed2a281293e2cecd0159595668c4c6e31ab350 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 7 Oct 2021 22:49:59 +0800 Subject: [PATCH 095/756] Remove unnecessary constants --- src/main/java/seedu/parser/MainParser.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 4eaf7ba737..3c0bebf45f 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -27,8 +27,6 @@ public class MainParser { private static final int COMD_WORD_INDEX = 0; private static final int ISOLATE_COMD_WORD = 2; - private static final int ISOLATE_USER_INPUT = 2; - public static final int NUMBER_OF_EDIT_DETAILS = 3; public static final int NAME_INDEX = 0; private ContactParser contactParser; From bca862874288daaacde8c7071966b3f6894cb74c Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 7 Oct 2021 22:52:09 +0800 Subject: [PATCH 096/756] Remove unnecessary @Override --- src/main/java/seedu/command/ListContactsCommand.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/seedu/command/ListContactsCommand.java b/src/main/java/seedu/command/ListContactsCommand.java index 49d09b98fa..5ee646c2ed 100644 --- a/src/main/java/seedu/command/ListContactsCommand.java +++ b/src/main/java/seedu/command/ListContactsCommand.java @@ -3,7 +3,6 @@ import seedu.ui.TextUi; public class ListContactsCommand extends Command { - @Override public void execute() { int listSize = contactList.getListSize(); if (listSize == 0) { From e9e436a210bfac77bf6ff0920be66120d52cef7c Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 7 Oct 2021 23:02:18 +0800 Subject: [PATCH 097/756] Revert "Remove unnecessary @Override" This reverts commit bca862874288daaacde8c7071966b3f6894cb74c. --- src/main/java/seedu/command/ListContactsCommand.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/seedu/command/ListContactsCommand.java b/src/main/java/seedu/command/ListContactsCommand.java index 5ee646c2ed..49d09b98fa 100644 --- a/src/main/java/seedu/command/ListContactsCommand.java +++ b/src/main/java/seedu/command/ListContactsCommand.java @@ -3,6 +3,7 @@ import seedu.ui.TextUi; public class ListContactsCommand extends Command { + @Override public void execute() { int listSize = contactList.getListSize(); if (listSize == 0) { From ee803a919f6a2addad18c824ec1279a06d95f981 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 7 Oct 2021 23:02:41 +0800 Subject: [PATCH 098/756] Remove unnecessary @Overrides --- src/main/java/seedu/command/ListContactsCommand.java | 1 - src/main/java/seedu/parser/EditContactParser.java | 1 - 2 files changed, 2 deletions(-) diff --git a/src/main/java/seedu/command/ListContactsCommand.java b/src/main/java/seedu/command/ListContactsCommand.java index 49d09b98fa..5ee646c2ed 100644 --- a/src/main/java/seedu/command/ListContactsCommand.java +++ b/src/main/java/seedu/command/ListContactsCommand.java @@ -3,7 +3,6 @@ import seedu.ui.TextUi; public class ListContactsCommand extends Command { - @Override public void execute() { int listSize = contactList.getListSize(); if (listSize == 0) { diff --git a/src/main/java/seedu/parser/EditContactParser.java b/src/main/java/seedu/parser/EditContactParser.java index afec72ecef..7e574c7192 100644 --- a/src/main/java/seedu/parser/EditContactParser.java +++ b/src/main/java/seedu/parser/EditContactParser.java @@ -8,7 +8,6 @@ public class EditContactParser extends ContactParser { public static final String BUFFER = " "; - @Override public String[] parseContactDetails(String userInput) throws InvalidFlagException, MissingDetailException, MissingArgException { String[] inputDetails = userInput.split(" ", NUMBER_OF_EDIT_DETAILS); From d3d16b4df130a77ca6713f8e77700d1a59df4733 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Fri, 8 Oct 2021 00:29:02 +0800 Subject: [PATCH 099/756] Add getIndex method to ViewCommand --- src/main/java/seedu/command/ViewCommand.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/seedu/command/ViewCommand.java b/src/main/java/seedu/command/ViewCommand.java index e9862ba572..99246a502f 100644 --- a/src/main/java/seedu/command/ViewCommand.java +++ b/src/main/java/seedu/command/ViewCommand.java @@ -10,6 +10,10 @@ public ViewCommand(int index) { this.index = index; } + public int getIndex() { + return index; + } + public void execute() { try { Contact viewingContact = contactList.getContactAtIndex(index); From 7627b222a22d4202795f5a2bbc38a662cf8293e1 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Fri, 8 Oct 2021 00:29:21 +0800 Subject: [PATCH 100/756] Add JUnit test for View Command --- src/test/java/seedu/parser/MainParserTest.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/test/java/seedu/parser/MainParserTest.java b/src/test/java/seedu/parser/MainParserTest.java index 02464c8b01..3c9c986190 100644 --- a/src/test/java/seedu/parser/MainParserTest.java +++ b/src/test/java/seedu/parser/MainParserTest.java @@ -8,6 +8,7 @@ import org.junit.jupiter.api.Test; import seedu.command.Command; import seedu.command.DeleteContactCommand; +import seedu.command.ViewCommand; import seedu.parser.MainParser; @@ -27,6 +28,14 @@ public void parseDeleteCommand() { assertEquals(testIndex,testResultCommand.getDeletedIndex()); } + @Test + public void parseViewCommand() { + final int testIndex = 1; + final String testUserInput = "view " + testIndex; + final ViewCommand testResultCommand = assertParseCommand(testUserInput, ViewCommand.class); + assertEquals(testIndex,testResultCommand.getIndex()); + } + private T assertParseCommand(String userInput, Class commandClass) { final Command result = mainParser.parseCommand(userInput); From 55c21e6cdd838c1dd8b6fc7cacfec12c6b38b2c7 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Fri, 8 Oct 2021 01:16:45 +0800 Subject: [PATCH 101/756] Rename to getParsedCommand; Implement trim for input to match TextUi --- src/test/java/seedu/parser/MainParserTest.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/test/java/seedu/parser/MainParserTest.java b/src/test/java/seedu/parser/MainParserTest.java index 02464c8b01..9b78fc2526 100644 --- a/src/test/java/seedu/parser/MainParserTest.java +++ b/src/test/java/seedu/parser/MainParserTest.java @@ -19,6 +19,13 @@ public void setUp() { mainParser = new MainParser(); } + private T getParsedCommand(String userInput, Class commandClass) { + // This is because user input is normally trimmed by TextUi + String trimmedUserInput = userInput.trim(); + final Command result = mainParser.parseCommand(trimmedUserInput); + assertTrue(commandClass.isInstance(result)); + return (T) result; + } @Test public void parseDeleteCommand() { final int testIndex = 1; From 255dde0b36288f27ba5847679ee3a187c9c37d66 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Fri, 8 Oct 2021 01:17:19 +0800 Subject: [PATCH 102/756] Implement unchecked to avoid warnings for unchecked types --- src/test/java/seedu/parser/MainParserTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/seedu/parser/MainParserTest.java b/src/test/java/seedu/parser/MainParserTest.java index 9b78fc2526..0ed08bbcda 100644 --- a/src/test/java/seedu/parser/MainParserTest.java +++ b/src/test/java/seedu/parser/MainParserTest.java @@ -19,6 +19,7 @@ public void setUp() { mainParser = new MainParser(); } + @SuppressWarnings("unchecked") private T getParsedCommand(String userInput, Class commandClass) { // This is because user input is normally trimmed by TextUi String trimmedUserInput = userInput.trim(); From ca9d97f9e9a47c6438d411846e75077a625e0700 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Fri, 8 Oct 2021 01:17:35 +0800 Subject: [PATCH 103/756] Add docs for getParsedCommand --- src/test/java/seedu/parser/MainParserTest.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/test/java/seedu/parser/MainParserTest.java b/src/test/java/seedu/parser/MainParserTest.java index 0ed08bbcda..7d94f77340 100644 --- a/src/test/java/seedu/parser/MainParserTest.java +++ b/src/test/java/seedu/parser/MainParserTest.java @@ -19,6 +19,14 @@ public void setUp() { mainParser = new MainParser(); } + /** + * Returns type of Command the parseCommand returns. This is required because most of the MainParser's + * internal parsing methods are private. + * @param userInput Expected user input + * @param commandClass Expected Command class/type returned + * @param Type of Command expected + * @return Command Returns a Command for verification + */ @SuppressWarnings("unchecked") private T getParsedCommand(String userInput, Class commandClass) { // This is because user input is normally trimmed by TextUi From 80f3b115495239f471192f789ed681eb416ac7b7 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Fri, 8 Oct 2021 01:18:15 +0800 Subject: [PATCH 104/756] Update rename parseDeleteCommand to match test style --- src/test/java/seedu/parser/MainParserTest.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/test/java/seedu/parser/MainParserTest.java b/src/test/java/seedu/parser/MainParserTest.java index 7d94f77340..e87849bb39 100644 --- a/src/test/java/seedu/parser/MainParserTest.java +++ b/src/test/java/seedu/parser/MainParserTest.java @@ -36,11 +36,11 @@ private T getParsedCommand(String userInput, Class comman return (T) result; } @Test - public void parseDeleteCommand() { - final int testIndex = 1; - final String testUserInput = "rm " + testIndex; - final DeleteContactCommand testResultCommand = assertParseCommand(testUserInput, DeleteContactCommand.class); - assertEquals(testIndex,testResultCommand.getDeletedIndex()); + public void parseDeleteCommand_validIndex_expectDeleteContactCommand() { + testIndex = 1; + testUserInput = "rm " + testIndex; + final DeleteContactCommand testResultCommand = getParsedCommand(testUserInput, DeleteContactCommand.class); + assertEquals(testIndex, testResultCommand.getDeletedIndex()); } From 9a60de854300068f69f6c70d831600340379f35e Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Fri, 8 Oct 2021 01:18:45 +0800 Subject: [PATCH 105/756] Implement MainParserTest testing for AddContact feature --- .../java/seedu/parser/MainParserTest.java | 35 ++++++++++++++++--- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/src/test/java/seedu/parser/MainParserTest.java b/src/test/java/seedu/parser/MainParserTest.java index e87849bb39..c238f0930e 100644 --- a/src/test/java/seedu/parser/MainParserTest.java +++ b/src/test/java/seedu/parser/MainParserTest.java @@ -3,16 +3,21 @@ import org.junit.jupiter.api.BeforeEach; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; +import seedu.command.AddContactCommand; import seedu.command.Command; import seedu.command.DeleteContactCommand; -import seedu.parser.MainParser; +import seedu.command.FailedCommand; +import seedu.exception.MissingNameException; public class MainParserTest { private MainParser mainParser; + private String testUserInput; + private int testIndex; // For commands that require index @BeforeEach public void setUp() { @@ -35,6 +40,7 @@ private T getParsedCommand(String userInput, Class comman assertTrue(commandClass.isInstance(result)); return (T) result; } + @Test public void parseDeleteCommand_validIndex_expectDeleteContactCommand() { testIndex = 1; @@ -43,11 +49,30 @@ public void parseDeleteCommand_validIndex_expectDeleteContactCommand() { assertEquals(testIndex, testResultCommand.getDeletedIndex()); } + @Test + public void parseAddCommand_validInputsWithIrregularSpaces_expectAddContactCommand() { + testUserInput = " add -n andre -g ng-andre "; + AddContactCommand actualCommand = getParsedCommand(testUserInput, AddContactCommand.class); + AddContactCommand expectedCommand = new AddContactCommand("andre", "ng-andre"); + assertEquals(expectedCommand.getName(), actualCommand.getName()); + assertEquals(expectedCommand.getGithub(), actualCommand.getGithub()); + } - private T assertParseCommand(String userInput, Class commandClass) { - final Command result = mainParser.parseCommand(userInput); - assertTrue(commandClass.isInstance(result)); - return (T) result; + @Test + public void parseAddCommand_validInputs_expectAddContactCommand() { + testUserInput = "add -n andre -g ng-andre"; + final AddContactCommand actualCommand = getParsedCommand(testUserInput, AddContactCommand.class); + final AddContactCommand expectedCommand = new AddContactCommand("andre", "ng-andre"); + assertEquals(expectedCommand.getName(), actualCommand.getName()); + assertEquals(expectedCommand.getGithub(), actualCommand.getGithub()); + } + + @Test + public void parseAddCommand_missingName_expectFailedCommand() { + testUserInput = " add -g github "; + final FailedCommand actualCommand = getParsedCommand(testUserInput, FailedCommand.class); + final FailedCommand expectedCommand = new FailedCommand(FailedCommandType.MISSING_NAME); + assertEquals(expectedCommand.getType(), actualCommand.getType()); } } From f31618872bfe998f6a0d2ecff26271e9f4f3d587 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Fri, 8 Oct 2021 01:19:07 +0800 Subject: [PATCH 106/756] Implement getters for AddContactCommand and FailedCommand --- src/main/java/seedu/command/AddContactCommand.java | 8 ++++++++ src/main/java/seedu/command/FailedCommand.java | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/src/main/java/seedu/command/AddContactCommand.java b/src/main/java/seedu/command/AddContactCommand.java index 593dc6262e..830110bc4e 100644 --- a/src/main/java/seedu/command/AddContactCommand.java +++ b/src/main/java/seedu/command/AddContactCommand.java @@ -7,6 +7,14 @@ public class AddContactCommand extends Command { private final String name; private final String github; + public String getName() { + return name; + } + + public String getGithub() { + return github; + } + public AddContactCommand(String name, String github) { this.name = name; this.github = github; diff --git a/src/main/java/seedu/command/FailedCommand.java b/src/main/java/seedu/command/FailedCommand.java index 629b0f7a6e..8c64216e1c 100644 --- a/src/main/java/seedu/command/FailedCommand.java +++ b/src/main/java/seedu/command/FailedCommand.java @@ -10,6 +10,10 @@ public FailedCommand(FailedCommandType type) { this.type = type; } + public FailedCommandType getType() { + return type; + } + public void execute() { switch (type) { case GENERAL: From 27a008841c00e8cb2ec9c1c796254578c2df6739 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Fri, 8 Oct 2021 01:19:30 +0800 Subject: [PATCH 107/756] Implement AddContactParser JUnit tests --- .../seedu/parser/AddContactParserTest.java | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 src/test/java/seedu/parser/AddContactParserTest.java diff --git a/src/test/java/seedu/parser/AddContactParserTest.java b/src/test/java/seedu/parser/AddContactParserTest.java new file mode 100644 index 0000000000..4a0a094d9d --- /dev/null +++ b/src/test/java/seedu/parser/AddContactParserTest.java @@ -0,0 +1,95 @@ +package seedu.parser; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import seedu.contact.DetailType; +import seedu.exception.InvalidFlagException; +import seedu.exception.MissingArgException; +import seedu.exception.MissingDetailException; + +import static org.junit.jupiter.api.Assertions.*; + +class AddContactParserTest { + private AddContactParser addContactParser; + private String[] inputContactDetails; + private String inputDetail; + private String inputUserInput; + private String[] expectedOutput; + private String[] actualOutput; + public static final int NUMBER_OF_DETAILS = 2; + + @BeforeEach + public void setUp() { + addContactParser = new AddContactParser(); + inputContactDetails = new String[NUMBER_OF_DETAILS]; + } + + @Test + void parseContactDetails_inputsWithIrregularSpacing_expectCorrectDetails() throws InvalidFlagException, + MissingDetailException, MissingArgException { + inputUserInput = "add -n andre -g ng-andre "; + actualOutput = addContactParser.parseContactDetails(inputUserInput); + expectedOutput = new String[]{"andre", "ng-andre"}; + assertArrayEquals(expectedOutput, actualOutput); + } + + @Test + void parseContactDetails_onlyAddInput_expectException() { + inputUserInput = " add "; + assertThrows(MissingArgException.class, + () -> addContactParser.parseContactDetails(inputUserInput)); + } + + @Test + void parseContactDetails_missingAllArguments_expectException() { + inputUserInput = " add -n -g "; + assertThrows(MissingDetailException.class, + () -> addContactParser.parseContactDetails(inputUserInput)); + } + + @Test + void parseContactDetails_invalidFlags_expectException() { + inputUserInput = " add -p pinterest -f facebook "; + assertThrows(InvalidFlagException.class, + () -> addContactParser.parseContactDetails(inputUserInput)); + } + + @Test + void parseContactDetails_missingDetails_expectException() { + inputUserInput = " add -p -f "; + assertThrows(MissingDetailException.class, + () -> addContactParser.parseContactDetails(inputUserInput)); + } + + @Test + void parseDetail_emptyDetail_expectException() { + // Upon user input being split, input detail may contain empty details + inputDetail = "n "; + assertThrows(MissingDetailException.class, + () -> addContactParser.parseDetail(inputContactDetails, inputDetail)); + } + + @Test + void parseDetail_invalidFlagUsed_expectException() { + // As of V1.0, only GitHub (-g) and Name (-n) flags are used + inputDetail = "f facebook"; + assertThrows(InvalidFlagException.class, + () -> addContactParser.parseDetail(inputContactDetails, inputDetail)); + } + + @Test + void parseDetail_inputsWithTrailingSpaces_expectNewContactDetail() throws InvalidFlagException, + MissingDetailException { + inputDetail = "n andre"; + addContactParser.parseDetail(inputContactDetails, inputDetail); + assertEquals("andre", inputContactDetails[DetailType.NAME.getIndex()]); + } + + @Test + void parseDetail_inputsWithSpaceInDetail_expectNewContactDetail() throws InvalidFlagException, + MissingDetailException { + inputDetail = "n Marcus Bory"; + addContactParser.parseDetail(inputContactDetails, inputDetail); + assertEquals("Marcus Bory", inputContactDetails[DetailType.NAME.getIndex()]); + } +} \ No newline at end of file From d13c09b097a2f5f6f540f36efcfb3f675ad529b5 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Fri, 8 Oct 2021 01:19:47 +0800 Subject: [PATCH 108/756] Fix trim bug found in JUnit test implemented --- src/main/java/seedu/parser/AddContactParser.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/AddContactParser.java b/src/main/java/seedu/parser/AddContactParser.java index 76dd73c223..6bcda6f3a0 100644 --- a/src/main/java/seedu/parser/AddContactParser.java +++ b/src/main/java/seedu/parser/AddContactParser.java @@ -4,6 +4,7 @@ import seedu.exception.InvalidFlagException; import seedu.exception.MissingArgException; import seedu.exception.MissingDetailException; +import seedu.exception.MissingNameException; public class AddContactParser extends ContactParser { /** @@ -57,6 +58,6 @@ public void parseDetail(String[] contactDetails, String detail) throws InvalidFl default: throw new InvalidFlagException(); } - contactDetails[indexToStore] = destructuredDetails[DETAIL_INDEX_IN_DETAILS]; + contactDetails[indexToStore] = destructuredDetails[DETAIL_INDEX_IN_DETAILS].trim(); } } From 2cd44c9a270a608ae1a19b5093eadac2541ca0fe Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Fri, 8 Oct 2021 01:31:26 +0800 Subject: [PATCH 109/756] Update to fix checkstyle errors --- .../seedu/parser/AddContactParserTest.java | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/test/java/seedu/parser/AddContactParserTest.java b/src/test/java/seedu/parser/AddContactParserTest.java index 4a0a094d9d..f91ddacdf6 100644 --- a/src/test/java/seedu/parser/AddContactParserTest.java +++ b/src/test/java/seedu/parser/AddContactParserTest.java @@ -7,7 +7,9 @@ import seedu.exception.MissingArgException; import seedu.exception.MissingDetailException; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; class AddContactParserTest { private AddContactParser addContactParser; @@ -36,29 +38,25 @@ void parseContactDetails_inputsWithIrregularSpacing_expectCorrectDetails() throw @Test void parseContactDetails_onlyAddInput_expectException() { inputUserInput = " add "; - assertThrows(MissingArgException.class, - () -> addContactParser.parseContactDetails(inputUserInput)); + assertThrows(MissingArgException.class, () -> addContactParser.parseContactDetails(inputUserInput)); } @Test void parseContactDetails_missingAllArguments_expectException() { inputUserInput = " add -n -g "; - assertThrows(MissingDetailException.class, - () -> addContactParser.parseContactDetails(inputUserInput)); + assertThrows(MissingDetailException.class, () -> addContactParser.parseContactDetails(inputUserInput)); } @Test void parseContactDetails_invalidFlags_expectException() { inputUserInput = " add -p pinterest -f facebook "; - assertThrows(InvalidFlagException.class, - () -> addContactParser.parseContactDetails(inputUserInput)); + assertThrows(InvalidFlagException.class, () -> addContactParser.parseContactDetails(inputUserInput)); } @Test void parseContactDetails_missingDetails_expectException() { inputUserInput = " add -p -f "; - assertThrows(MissingDetailException.class, - () -> addContactParser.parseContactDetails(inputUserInput)); + assertThrows(MissingDetailException.class, () -> addContactParser.parseContactDetails(inputUserInput)); } @Test @@ -66,15 +64,14 @@ void parseDetail_emptyDetail_expectException() { // Upon user input being split, input detail may contain empty details inputDetail = "n "; assertThrows(MissingDetailException.class, - () -> addContactParser.parseDetail(inputContactDetails, inputDetail)); + () -> addContactParser.parseDetail(inputContactDetails, inputDetail)); } @Test void parseDetail_invalidFlagUsed_expectException() { // As of V1.0, only GitHub (-g) and Name (-n) flags are used inputDetail = "f facebook"; - assertThrows(InvalidFlagException.class, - () -> addContactParser.parseDetail(inputContactDetails, inputDetail)); + assertThrows(InvalidFlagException.class, () -> addContactParser.parseDetail(inputContactDetails, inputDetail)); } @Test From c63075fe1e991510882586bfa43ce11202a31329 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Fri, 8 Oct 2021 11:55:25 +0800 Subject: [PATCH 110/756] Add test for editContactParser --- .../seedu/parser/EditContactParserTest.java | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/test/java/seedu/parser/EditContactParserTest.java diff --git a/src/test/java/seedu/parser/EditContactParserTest.java b/src/test/java/seedu/parser/EditContactParserTest.java new file mode 100644 index 0000000000..124b93368f --- /dev/null +++ b/src/test/java/seedu/parser/EditContactParserTest.java @@ -0,0 +1,33 @@ +package seedu.parser; + +import org.junit.jupiter.api.Test; + +import seedu.exception.InvalidFlagException; +import seedu.exception.MissingArgException; +import seedu.exception.MissingDetailException; +import seedu.parser.EditContactParser; + +import java.util.Arrays; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; + +class EditContactParserTest { + private EditContactParser editContactParser = new EditContactParser(); + + @Test + void testParseContactDetails() throws MissingDetailException, MissingArgException, InvalidFlagException { + String[] expectedResult = {null, "github"}; + String testInput = "edit 1 -g github"; + String[] actualResult = editContactParser.parseContactDetails(testInput); + assertArrayEquals(expectedResult, actualResult); + } + + @Test + void testgetIndex() throws MissingArgException { + int expectedResult = 3; + String testInput = "edit 3 "; + int actualResult = editContactParser.getIndex(testInput); + assertEquals(expectedResult, actualResult); + } +} From 7463edd6cc95a0dee04dc6be02735cb0303d50ca Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Fri, 8 Oct 2021 12:13:50 +0800 Subject: [PATCH 111/756] Add JUnit test for valid input with extra characters --- src/test/java/seedu/parser/MainParserTest.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/test/java/seedu/parser/MainParserTest.java b/src/test/java/seedu/parser/MainParserTest.java index ba7c7297b2..09bfb69bb8 100644 --- a/src/test/java/seedu/parser/MainParserTest.java +++ b/src/test/java/seedu/parser/MainParserTest.java @@ -57,6 +57,15 @@ public void parseAddCommand_validInputsWithIrregularSpaces_expectAddContactComma assertEquals(expectedCommand.getGithub(), actualCommand.getGithub()); } + @Test + public void parseAddCommand_validInputsWithExtraCharacters_expectAddContactCommand() { + testUserInput = " add 1231267azldasd -n marcus -g marcus-bory "; + AddContactCommand actualCommand = getParsedCommand(testUserInput, AddContactCommand.class); + AddContactCommand expectedCommand = new AddContactCommand("marcus", "marcus-bory"); + assertEquals(expectedCommand.getName(), actualCommand.getName()); + assertEquals(expectedCommand.getGithub(), actualCommand.getGithub()); + } + @Test public void parseAddCommand_validInputs_expectAddContactCommand() { testUserInput = "add -n andre -g ng-andre"; From 78b6106e37e811fd191f31021a3f75d5c7f7e589 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Fri, 8 Oct 2021 12:16:00 +0800 Subject: [PATCH 112/756] Rename methods --- src/test/java/seedu/parser/EditContactParserTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/seedu/parser/EditContactParserTest.java b/src/test/java/seedu/parser/EditContactParserTest.java index 124b93368f..490c3583b3 100644 --- a/src/test/java/seedu/parser/EditContactParserTest.java +++ b/src/test/java/seedu/parser/EditContactParserTest.java @@ -16,7 +16,7 @@ class EditContactParserTest { private EditContactParser editContactParser = new EditContactParser(); @Test - void testParseContactDetails() throws MissingDetailException, MissingArgException, InvalidFlagException { + void parseContactDetails() throws MissingDetailException, MissingArgException, InvalidFlagException { String[] expectedResult = {null, "github"}; String testInput = "edit 1 -g github"; String[] actualResult = editContactParser.parseContactDetails(testInput); @@ -24,7 +24,7 @@ void testParseContactDetails() throws MissingDetailException, MissingArgExceptio } @Test - void testgetIndex() throws MissingArgException { + void getIndex() throws MissingArgException { int expectedResult = 3; String testInput = "edit 3 "; int actualResult = editContactParser.getIndex(testInput); From 793f802198608e705dd671941117d2314d4bb0d9 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Fri, 8 Oct 2021 12:42:04 +0800 Subject: [PATCH 113/756] Add JUnit test for view command with invalid index --- src/test/java/seedu/parser/MainParserTest.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/test/java/seedu/parser/MainParserTest.java b/src/test/java/seedu/parser/MainParserTest.java index 09bfb69bb8..9a41f9a383 100644 --- a/src/test/java/seedu/parser/MainParserTest.java +++ b/src/test/java/seedu/parser/MainParserTest.java @@ -2,9 +2,6 @@ import org.junit.jupiter.api.BeforeEach; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - import org.junit.jupiter.api.Test; import seedu.command.AddContactCommand; import seedu.command.Command; @@ -12,6 +9,10 @@ import seedu.command.FailedCommand; import seedu.command.ViewCommand; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + public class MainParserTest { private MainParser mainParser; @@ -83,6 +84,13 @@ public void parseViewCommand_validIndex_expectViewContactIndexMatch() { assertEquals(testIndex,testResultCommand.getIndex()); } + @Test + public void parseViewCommand_invalidIndex_expectException() { + testIndex = 99999; + final ViewCommand testResultCommand = new ViewCommand(testIndex); + assertThrows(NullPointerException.class, testResultCommand::execute); + } + @Test public void parseAddCommand_missingName_expectFailedCommand() { testUserInput = " add -g github "; From 697f70bc7df38c044cf3ee4f7cf60015443b22e6 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Fri, 8 Oct 2021 13:02:18 +0800 Subject: [PATCH 114/756] Update IO redirection tests --- text-ui-test/ACTUAL.TXT | 138 ++++++++++++++++++++++++++++++++++++-- text-ui-test/EXPECTED.TXT | 138 ++++++++++++++++++++++++++++++++++++-- text-ui-test/input.txt | 25 ++++++- 3 files changed, 285 insertions(+), 16 deletions(-) diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index 67878559d0..55a90041bd 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -22,33 +22,118 @@ ConTech has added the specified contact: ng andre You now have 1 contact(s). ____________________________________________________________ +____________________________________________________________ +That does not seem to be a number. +Please provide a number instead. +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: ashraf +You now have 2 contact(s). +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: mayank +You now have 3 contact(s). +____________________________________________________________ + +____________________________________________________________ +The number you have input is out of range. +Please input a number between 0 and 2. +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: bory +You now have 4 contact(s). +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: andre +You now have 5 contact(s). +____________________________________________________________ + +____________________________________________________________ +ConTech has 5 contacts stored. +Here's the list : +____________________________________________________________ + +0. ng andre +1. ashraf +2. mayank +3. bory +4. andre + +____________________________________________________________ + +____________________________________________________________ +1. Name: ashraf GitHub: ashraf +____________________________________________________________ + ____________________________________________________________ There are missing details. Please remove any flags with no details ____________________________________________________________ +____________________________________________________________ +The number you have input is out of range. +Please input a number between 0 and 4. +____________________________________________________________ + ____________________________________________________________ ConTech has added the specified contact: lezong -You now have 2 contact(s). +You now have 6 contact(s). ____________________________________________________________ ____________________________________________________________ -ConTech has 2 contacts stored. +There are missing details. +Please specify a name when creating a contact with the flag -n +____________________________________________________________ + +____________________________________________________________ +ConTech has 6 contacts stored. Here's the list : ____________________________________________________________ 0. ng andre -1. lezong +1. ashraf +2. mayank +3. bory +4. andre +5. lezong ____________________________________________________________ ____________________________________________________________ -0. Name: ng andre GitHub: ng-andre +3. Name: bory GitHub: marcus ____________________________________________________________ ____________________________________________________________ ConTech has removed the specified contact: ng andre -You now have 1 contact(s). +You now have 5 contact(s). +____________________________________________________________ + +____________________________________________________________ +There are missing details. +Please remove any flags with no details +____________________________________________________________ + +____________________________________________________________ +2. Name: bory GitHub: marcus +____________________________________________________________ + +____________________________________________________________ +ConTech is unable to understand your request. +Please try again with a valid command. +____________________________________________________________ + +____________________________________________________________ +ConTech is unable to understand your request. +Please try again with a valid command. +____________________________________________________________ + +____________________________________________________________ +ConTech is unable to understand your request. +Please try again with a valid command. ____________________________________________________________ ____________________________________________________________ @@ -57,8 +142,47 @@ Please provide a number instead. ____________________________________________________________ ____________________________________________________________ -The number you have input is out of range. -Please input 0 as you only have 1 contact saved. +There appears to be a flag that is not recognised. +Please try again with a valid flag. + -n NAME + -g GITHUB +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: lezongmun +You now have 6 contact(s). +____________________________________________________________ + +____________________________________________________________ +ConTech has removed the specified contact: mayank +You now have 5 contact(s). +____________________________________________________________ + +____________________________________________________________ +ConTech has 5 contacts stored. +Here's the list : +____________________________________________________________ + +0. ashraf +1. bory +2. andre +3. lezong +4. lezongmun + +____________________________________________________________ + +____________________________________________________________ +That does not seem to be a number. +Please provide a number instead. +____________________________________________________________ + +____________________________________________________________ +0. Name: ashraf GitHub: ashraf +____________________________________________________________ + +____________________________________________________________ +There are missing details. +Please remove any flags with no details ____________________________________________________________ ____________________________________________________________ diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 67878559d0..55a90041bd 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -22,33 +22,118 @@ ConTech has added the specified contact: ng andre You now have 1 contact(s). ____________________________________________________________ +____________________________________________________________ +That does not seem to be a number. +Please provide a number instead. +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: ashraf +You now have 2 contact(s). +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: mayank +You now have 3 contact(s). +____________________________________________________________ + +____________________________________________________________ +The number you have input is out of range. +Please input a number between 0 and 2. +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: bory +You now have 4 contact(s). +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: andre +You now have 5 contact(s). +____________________________________________________________ + +____________________________________________________________ +ConTech has 5 contacts stored. +Here's the list : +____________________________________________________________ + +0. ng andre +1. ashraf +2. mayank +3. bory +4. andre + +____________________________________________________________ + +____________________________________________________________ +1. Name: ashraf GitHub: ashraf +____________________________________________________________ + ____________________________________________________________ There are missing details. Please remove any flags with no details ____________________________________________________________ +____________________________________________________________ +The number you have input is out of range. +Please input a number between 0 and 4. +____________________________________________________________ + ____________________________________________________________ ConTech has added the specified contact: lezong -You now have 2 contact(s). +You now have 6 contact(s). ____________________________________________________________ ____________________________________________________________ -ConTech has 2 contacts stored. +There are missing details. +Please specify a name when creating a contact with the flag -n +____________________________________________________________ + +____________________________________________________________ +ConTech has 6 contacts stored. Here's the list : ____________________________________________________________ 0. ng andre -1. lezong +1. ashraf +2. mayank +3. bory +4. andre +5. lezong ____________________________________________________________ ____________________________________________________________ -0. Name: ng andre GitHub: ng-andre +3. Name: bory GitHub: marcus ____________________________________________________________ ____________________________________________________________ ConTech has removed the specified contact: ng andre -You now have 1 contact(s). +You now have 5 contact(s). +____________________________________________________________ + +____________________________________________________________ +There are missing details. +Please remove any flags with no details +____________________________________________________________ + +____________________________________________________________ +2. Name: bory GitHub: marcus +____________________________________________________________ + +____________________________________________________________ +ConTech is unable to understand your request. +Please try again with a valid command. +____________________________________________________________ + +____________________________________________________________ +ConTech is unable to understand your request. +Please try again with a valid command. +____________________________________________________________ + +____________________________________________________________ +ConTech is unable to understand your request. +Please try again with a valid command. ____________________________________________________________ ____________________________________________________________ @@ -57,8 +142,47 @@ Please provide a number instead. ____________________________________________________________ ____________________________________________________________ -The number you have input is out of range. -Please input 0 as you only have 1 contact saved. +There appears to be a flag that is not recognised. +Please try again with a valid flag. + -n NAME + -g GITHUB +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: lezongmun +You now have 6 contact(s). +____________________________________________________________ + +____________________________________________________________ +ConTech has removed the specified contact: mayank +You now have 5 contact(s). +____________________________________________________________ + +____________________________________________________________ +ConTech has 5 contacts stored. +Here's the list : +____________________________________________________________ + +0. ashraf +1. bory +2. andre +3. lezong +4. lezongmun + +____________________________________________________________ + +____________________________________________________________ +That does not seem to be a number. +Please provide a number instead. +____________________________________________________________ + +____________________________________________________________ +0. Name: ashraf GitHub: ashraf +____________________________________________________________ + +____________________________________________________________ +There are missing details. +Please remove any flags with no details ____________________________________________________________ ____________________________________________________________ diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index 8c57f40390..fd16ae4b56 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -1,9 +1,30 @@ add -n ng andre -g ng-andre +view 999aa +add -n ashraf -g ashraf +add -n mayank -g mayankp123 +rm 9909 +add -n bory -g marcus +add -n andre -g ng-andre +list +view 1 add -n bory -g +rm 1223 add -g lezongmun -n lezong +add -g github list -view 0 +view 3 rm 0 -rm a + add -p -f +view 2 +n andre +f facebook +n +rm anc + add -p pinterest -f facebook + add 1231267azldasd -n lezongmun -g lezong rm 1 +list +view abc +view 0 + add -n -g exit \ No newline at end of file From b80565ce5c6bd49643910f4a265a5e3395da5e9d Mon Sep 17 00:00:00 2001 From: lezong Date: Fri, 8 Oct 2021 20:22:59 +0800 Subject: [PATCH 115/756] Add JUnit tests for delete command and some tweaks to delete and view commands --- .../seedu/command/DeleteContactCommand.java | 6 +- src/main/java/seedu/command/ViewCommand.java | 4 +- src/main/java/seedu/parser/MainParser.java | 17 ++---- src/main/java/seedu/ui/TextUi.java | 7 ++- .../java/seedu/parser/MainParserTest.java | 57 ++++++++++++++++++- 5 files changed, 71 insertions(+), 20 deletions(-) diff --git a/src/main/java/seedu/command/DeleteContactCommand.java b/src/main/java/seedu/command/DeleteContactCommand.java index 7e572dcc27..1e378b92ba 100644 --- a/src/main/java/seedu/command/DeleteContactCommand.java +++ b/src/main/java/seedu/command/DeleteContactCommand.java @@ -1,7 +1,9 @@ package seedu.command; import seedu.contact.Contact; +import seedu.parser.FailedCommandType; import seedu.ui.TextUi; +import seedu.command.FailedCommand; public class DeleteContactCommand extends Command { private final int deletedIndex; @@ -19,8 +21,8 @@ public void execute() { Contact deletedContact = contactList.getContactAtIndex(deletedIndex); this.contactList.deleteContact(deletedIndex); TextUi.deleteContactMessage(deletedContact.getName(), contactList.getListSize()); - } catch (IndexOutOfBoundsException | NullPointerException e) { - TextUi.numOutOfRangeMessage(contactList.getListSize() - 1); + } catch (IndexOutOfBoundsException e) { + TextUi.numOutOfRangeMessage(contactList.getListSize()); } } } diff --git a/src/main/java/seedu/command/ViewCommand.java b/src/main/java/seedu/command/ViewCommand.java index 99246a502f..7a391c7c8d 100644 --- a/src/main/java/seedu/command/ViewCommand.java +++ b/src/main/java/seedu/command/ViewCommand.java @@ -18,8 +18,8 @@ public void execute() { try { Contact viewingContact = contactList.getContactAtIndex(index); TextUi.viewContactMessage(viewingContact, index); - } catch (IndexOutOfBoundsException | NullPointerException e) { - TextUi.numOutOfRangeMessage(contactList.getListSize() - 1); + } catch (IndexOutOfBoundsException e) { + TextUi.numOutOfRangeMessage(contactList.getListSize()); } } } diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 3c0bebf45f..aa91c02fd1 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -109,29 +109,24 @@ private Command parseViewContact(String userInput) { if (destructuredInputs.length == 1) { return new FailedCommand(FailedCommandType.MISSING_ARG); } - if (destructuredInputs.length > 2) { - return new FailedCommand(FailedCommandType.INVALID_FORMAT); - } try { - return new ViewCommand(Integer.parseInt(destructuredInputs[1])); + return new ViewCommand(Integer.parseInt(destructuredInputs[1].trim())); } catch (NumberFormatException e) { - return new FailedCommand(FailedCommandType.INVALID_NUM); + return new FailedCommand(FailedCommandType.INVALID_INDEX); } } private Command parseDeleteContact(String userInput) { - String[] destructuredInputs = userInput.split(" "); + String[] destructuredInputs = userInput.split(" ", ISOLATE_COMD_WORD); + //check if there is only the command word and no arguments in input if (destructuredInputs.length == 1) { return new FailedCommand(FailedCommandType.MISSING_ARG); } - if (destructuredInputs.length > 2) { - return new FailedCommand(FailedCommandType.INVALID_FORMAT); - } try { - int deletedIndex = Integer.parseInt(destructuredInputs[1]); + int deletedIndex = Integer.parseInt(destructuredInputs[1].trim()); return new DeleteContactCommand(deletedIndex); } catch (NumberFormatException e) { - return new FailedCommand(FailedCommandType.INVALID_NUM); + return new FailedCommand(FailedCommandType.INVALID_INDEX); } } } diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 7939633e4a..a45f5726ad 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -142,12 +142,15 @@ public static void missingNameMessage() { public static void numOutOfRangeMessage(int listSize) { String message; + int maxIndex = listSize - 1; if (listSize == 0) { + message = "There are no contacts stored in ConTech."; + } else if (listSize == 1) { message = "The number you have input is out of range.\n" - + "Please input 0 as you only have 1 contact saved."; + + "You only have 1 contact stored."; } else { message = "The number you have input is out of range.\n" - + "Please input a number between 0 and " + listSize + "."; + + "Please input a number between 0 and " + maxIndex + "."; } printDoubleLineMessage(message); } diff --git a/src/test/java/seedu/parser/MainParserTest.java b/src/test/java/seedu/parser/MainParserTest.java index ba7c7297b2..a750f30430 100644 --- a/src/test/java/seedu/parser/MainParserTest.java +++ b/src/test/java/seedu/parser/MainParserTest.java @@ -2,15 +2,15 @@ import org.junit.jupiter.api.BeforeEach; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - import org.junit.jupiter.api.Test; import seedu.command.AddContactCommand; import seedu.command.Command; import seedu.command.DeleteContactCommand; import seedu.command.FailedCommand; import seedu.command.ViewCommand; +import seedu.contact.ContactList; + +import static org.junit.jupiter.api.Assertions.*; public class MainParserTest { @@ -40,6 +40,7 @@ private T getParsedCommand(String userInput, Class comman return (T) result; } + @Test public void parseDeleteCommand_validIndex_expectDeleteContactIndexMatch() { testIndex = 1; @@ -48,6 +49,56 @@ public void parseDeleteCommand_validIndex_expectDeleteContactIndexMatch() { assertEquals(testIndex, testResultCommand.getDeletedIndex()); } + @Test + public void parseDeleteCommand_validIndexWithSpaces_expectDeleteContactIndexMatch() { + testIndex = 1; + testUserInput = "rm " + testIndex; + final DeleteContactCommand testResultCommand = getParsedCommand(testUserInput, DeleteContactCommand.class); + assertEquals(testIndex, testResultCommand.getDeletedIndex()); + } + + @Test + public void parseDeleteCommand_missingIndex_expectFailedCommandType() { + testUserInput = "rm"; + FailedCommandType expectedFailedCommandType = FailedCommandType.MISSING_ARG; + final FailedCommand actualFailedCommand = getParsedCommand(testUserInput, FailedCommand.class); + assertEquals(expectedFailedCommandType, actualFailedCommand.getType()); + } + + @Test + public void parseDeleteCommand_invalidNumber_expectFailedCommandType() { + testUserInput = "rm abc"; + FailedCommandType expectedFailedCommandType = FailedCommandType.INVALID_INDEX; + final FailedCommand actualFailedCommand = getParsedCommand(testUserInput, FailedCommand.class); + assertEquals(expectedFailedCommandType, actualFailedCommand.getType()); + } + + @Test + public void parseDeleteCommand_invalidIndexFormatting_expectFailedCommandType() { + testUserInput = "rm 1 2"; + FailedCommandType expectedFailedCommandType = FailedCommandType.INVALID_INDEX; + final FailedCommand actualFailedCommand = getParsedCommand(testUserInput, FailedCommand.class); + assertEquals(expectedFailedCommandType, actualFailedCommand.getType()); + } + + @Test + public void parseDeleteCommand_outOfRangeIndex_expectFailedCommandType() { + ContactList contactList = new ContactList(); + testUserInput = "rm 3"; + // adding 1 input contact into contactList + String addContactInput = "add -n wangyih -g ongzai"; + AddContactCommand addContactCommand = getParsedCommand(addContactInput, AddContactCommand.class); + addContactCommand.setContactList(contactList); + addContactCommand.execute(); + // trying to delete the contact with index 3 when there is only 1 contact (with index 0) in the contact list + DeleteContactCommand deleteContactCommand = getParsedCommand(testUserInput, DeleteContactCommand.class); + deleteContactCommand.setContactList(contactList); + int deletedIndex = deleteContactCommand.getDeletedIndex(); + + assertThrows(IndexOutOfBoundsException.class, () -> contactList.deleteContact(deletedIndex)); + } + + @Test public void parseAddCommand_validInputsWithIrregularSpaces_expectAddContactCommand() { testUserInput = " add -n andre -g ng-andre "; From 62cc6fb0054b103ee8266c0ca12f2dc7af731964 Mon Sep 17 00:00:00 2001 From: lezong Date: Fri, 8 Oct 2021 21:11:59 +0800 Subject: [PATCH 116/756] Fix CheckStyle --- src/test/java/seedu/parser/MainParserTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/test/java/seedu/parser/MainParserTest.java b/src/test/java/seedu/parser/MainParserTest.java index 43a3354bda..b918dca579 100644 --- a/src/test/java/seedu/parser/MainParserTest.java +++ b/src/test/java/seedu/parser/MainParserTest.java @@ -10,8 +10,6 @@ import seedu.command.ViewCommand; import seedu.contact.ContactList; -import static org.junit.jupiter.api.Assertions.*; - import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; From c160e8601f820527a1beaacb5a5038afccd7ad36 Mon Sep 17 00:00:00 2001 From: lezong Date: Fri, 8 Oct 2021 21:17:55 +0800 Subject: [PATCH 117/756] Fix text-ui-test --- text-ui-test/ACTUAL.TXT | 50 ++++++----- text-ui-test/EXPECTED-UNIX.TXT | 148 +++++++++++++++++++++++++++++++-- text-ui-test/EXPECTED.TXT | 50 ++++++----- text-ui-test/input.txt | 6 +- 4 files changed, 199 insertions(+), 55 deletions(-) diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index 55a90041bd..7419045e36 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -23,8 +23,12 @@ You now have 1 contact(s). ____________________________________________________________ ____________________________________________________________ -That does not seem to be a number. -Please provide a number instead. +The number you have input is out of range. +You only have 1 contact stored. +____________________________________________________________ + +____________________________________________________________ +Please enter a valid contact index. ____________________________________________________________ ____________________________________________________________ @@ -32,6 +36,11 @@ ConTech has added the specified contact: ashraf You now have 2 contact(s). ____________________________________________________________ +____________________________________________________________ +The number you have input is out of range. +Please input a number between 0 and 1. +____________________________________________________________ + ____________________________________________________________ ConTech has added the specified contact: mayank You now have 3 contact(s). @@ -75,8 +84,7 @@ Please remove any flags with no details ____________________________________________________________ ____________________________________________________________ -The number you have input is out of range. -Please input a number between 0 and 4. +Please enter a valid contact index. ____________________________________________________________ ____________________________________________________________ @@ -112,13 +120,18 @@ ConTech has removed the specified contact: ng andre You now have 5 contact(s). ____________________________________________________________ +____________________________________________________________ +ConTech has removed the specified contact: ashraf +You now have 4 contact(s). +____________________________________________________________ + ____________________________________________________________ There are missing details. Please remove any flags with no details ____________________________________________________________ ____________________________________________________________ -2. Name: bory GitHub: marcus +2. Name: andre GitHub: ng-andre ____________________________________________________________ ____________________________________________________________ @@ -136,11 +149,6 @@ ConTech is unable to understand your request. Please try again with a valid command. ____________________________________________________________ -____________________________________________________________ -That does not seem to be a number. -Please provide a number instead. -____________________________________________________________ - ____________________________________________________________ There appears to be a flag that is not recognised. Please try again with a valid flag. @@ -150,34 +158,32 @@ ____________________________________________________________ ____________________________________________________________ ConTech has added the specified contact: lezongmun -You now have 6 contact(s). +You now have 5 contact(s). ____________________________________________________________ ____________________________________________________________ -ConTech has removed the specified contact: mayank -You now have 5 contact(s). +ConTech has removed the specified contact: bory +You now have 4 contact(s). ____________________________________________________________ ____________________________________________________________ -ConTech has 5 contacts stored. +ConTech has 4 contacts stored. Here's the list : ____________________________________________________________ -0. ashraf -1. bory -2. andre -3. lezong -4. lezongmun +0. mayank +1. andre +2. lezong +3. lezongmun ____________________________________________________________ ____________________________________________________________ -That does not seem to be a number. -Please provide a number instead. +Please enter a valid contact index. ____________________________________________________________ ____________________________________________________________ -0. Name: ashraf GitHub: ashraf +0. Name: mayank GitHub: mayankp123 ____________________________________________________________ ____________________________________________________________ diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index 67878559d0..7419045e36 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -22,43 +22,173 @@ ConTech has added the specified contact: ng andre You now have 1 contact(s). ____________________________________________________________ +____________________________________________________________ +The number you have input is out of range. +You only have 1 contact stored. +____________________________________________________________ + +____________________________________________________________ +Please enter a valid contact index. +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: ashraf +You now have 2 contact(s). +____________________________________________________________ + +____________________________________________________________ +The number you have input is out of range. +Please input a number between 0 and 1. +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: mayank +You now have 3 contact(s). +____________________________________________________________ + +____________________________________________________________ +The number you have input is out of range. +Please input a number between 0 and 2. +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: bory +You now have 4 contact(s). +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: andre +You now have 5 contact(s). +____________________________________________________________ + +____________________________________________________________ +ConTech has 5 contacts stored. +Here's the list : +____________________________________________________________ + +0. ng andre +1. ashraf +2. mayank +3. bory +4. andre + +____________________________________________________________ + +____________________________________________________________ +1. Name: ashraf GitHub: ashraf +____________________________________________________________ + ____________________________________________________________ There are missing details. Please remove any flags with no details ____________________________________________________________ +____________________________________________________________ +Please enter a valid contact index. +____________________________________________________________ + ____________________________________________________________ ConTech has added the specified contact: lezong -You now have 2 contact(s). +You now have 6 contact(s). +____________________________________________________________ + +____________________________________________________________ +There are missing details. +Please specify a name when creating a contact with the flag -n ____________________________________________________________ ____________________________________________________________ -ConTech has 2 contacts stored. +ConTech has 6 contacts stored. Here's the list : ____________________________________________________________ 0. ng andre -1. lezong +1. ashraf +2. mayank +3. bory +4. andre +5. lezong ____________________________________________________________ ____________________________________________________________ -0. Name: ng andre GitHub: ng-andre +3. Name: bory GitHub: marcus ____________________________________________________________ ____________________________________________________________ ConTech has removed the specified contact: ng andre -You now have 1 contact(s). +You now have 5 contact(s). ____________________________________________________________ ____________________________________________________________ -That does not seem to be a number. -Please provide a number instead. +ConTech has removed the specified contact: ashraf +You now have 4 contact(s). ____________________________________________________________ ____________________________________________________________ -The number you have input is out of range. -Please input 0 as you only have 1 contact saved. +There are missing details. +Please remove any flags with no details +____________________________________________________________ + +____________________________________________________________ +2. Name: andre GitHub: ng-andre +____________________________________________________________ + +____________________________________________________________ +ConTech is unable to understand your request. +Please try again with a valid command. +____________________________________________________________ + +____________________________________________________________ +ConTech is unable to understand your request. +Please try again with a valid command. +____________________________________________________________ + +____________________________________________________________ +ConTech is unable to understand your request. +Please try again with a valid command. +____________________________________________________________ + +____________________________________________________________ +There appears to be a flag that is not recognised. +Please try again with a valid flag. + -n NAME + -g GITHUB +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: lezongmun +You now have 5 contact(s). +____________________________________________________________ + +____________________________________________________________ +ConTech has removed the specified contact: bory +You now have 4 contact(s). +____________________________________________________________ + +____________________________________________________________ +ConTech has 4 contacts stored. +Here's the list : +____________________________________________________________ + +0. mayank +1. andre +2. lezong +3. lezongmun + +____________________________________________________________ + +____________________________________________________________ +Please enter a valid contact index. +____________________________________________________________ + +____________________________________________________________ +0. Name: mayank GitHub: mayankp123 +____________________________________________________________ + +____________________________________________________________ +There are missing details. +Please remove any flags with no details ____________________________________________________________ ____________________________________________________________ diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 55a90041bd..7419045e36 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -23,8 +23,12 @@ You now have 1 contact(s). ____________________________________________________________ ____________________________________________________________ -That does not seem to be a number. -Please provide a number instead. +The number you have input is out of range. +You only have 1 contact stored. +____________________________________________________________ + +____________________________________________________________ +Please enter a valid contact index. ____________________________________________________________ ____________________________________________________________ @@ -32,6 +36,11 @@ ConTech has added the specified contact: ashraf You now have 2 contact(s). ____________________________________________________________ +____________________________________________________________ +The number you have input is out of range. +Please input a number between 0 and 1. +____________________________________________________________ + ____________________________________________________________ ConTech has added the specified contact: mayank You now have 3 contact(s). @@ -75,8 +84,7 @@ Please remove any flags with no details ____________________________________________________________ ____________________________________________________________ -The number you have input is out of range. -Please input a number between 0 and 4. +Please enter a valid contact index. ____________________________________________________________ ____________________________________________________________ @@ -112,13 +120,18 @@ ConTech has removed the specified contact: ng andre You now have 5 contact(s). ____________________________________________________________ +____________________________________________________________ +ConTech has removed the specified contact: ashraf +You now have 4 contact(s). +____________________________________________________________ + ____________________________________________________________ There are missing details. Please remove any flags with no details ____________________________________________________________ ____________________________________________________________ -2. Name: bory GitHub: marcus +2. Name: andre GitHub: ng-andre ____________________________________________________________ ____________________________________________________________ @@ -136,11 +149,6 @@ ConTech is unable to understand your request. Please try again with a valid command. ____________________________________________________________ -____________________________________________________________ -That does not seem to be a number. -Please provide a number instead. -____________________________________________________________ - ____________________________________________________________ There appears to be a flag that is not recognised. Please try again with a valid flag. @@ -150,34 +158,32 @@ ____________________________________________________________ ____________________________________________________________ ConTech has added the specified contact: lezongmun -You now have 6 contact(s). +You now have 5 contact(s). ____________________________________________________________ ____________________________________________________________ -ConTech has removed the specified contact: mayank -You now have 5 contact(s). +ConTech has removed the specified contact: bory +You now have 4 contact(s). ____________________________________________________________ ____________________________________________________________ -ConTech has 5 contacts stored. +ConTech has 4 contacts stored. Here's the list : ____________________________________________________________ -0. ashraf -1. bory -2. andre -3. lezong -4. lezongmun +0. mayank +1. andre +2. lezong +3. lezongmun ____________________________________________________________ ____________________________________________________________ -That does not seem to be a number. -Please provide a number instead. +Please enter a valid contact index. ____________________________________________________________ ____________________________________________________________ -0. Name: ashraf GitHub: ashraf +0. Name: mayank GitHub: mayankp123 ____________________________________________________________ ____________________________________________________________ diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index fd16ae4b56..9e33e0ccdf 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -1,6 +1,8 @@ add -n ng andre -g ng-andre +rm 2 view 999aa add -n ashraf -g ashraf +rm 3 add -n mayank -g mayankp123 rm 9909 add -n bory -g marcus @@ -8,18 +10,18 @@ add -n andre -g ng-andre list view 1 add -n bory -g -rm 1223 +rm abc add -g lezongmun -n lezong add -g github list view 3 rm 0 +rm 0 add -p -f view 2 n andre f facebook n -rm anc add -p pinterest -f facebook add 1231267azldasd -n lezongmun -g lezong rm 1 From 1be4cd028e0a5acf59a420940ccd67f41c318c16 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sun, 10 Oct 2021 01:25:21 +0800 Subject: [PATCH 118/756] Update TextUi user input to remove commas for command parsing --- src/main/java/seedu/ui/TextUi.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index a45f5726ad..826c33f08f 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -20,7 +20,13 @@ public TextUi() { } public String getUserInput() { - return scanner.nextLine().trim(); + String userInput = scanner.nextLine().trim(); + if (userInput.contains(",")) { + String newUserInput = userInput.replace(",", ""); + forbiddenInputCommaMessage(newUserInput); + return newUserInput; + } + return userInput; } // Used for print messages after user inputs From af7196fc2080f8f67ca3a0c8095de91d64b69279 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sun, 10 Oct 2021 01:25:39 +0800 Subject: [PATCH 119/756] Add printTopLineMessage into TextUi --- src/main/java/seedu/ui/TextUi.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 826c33f08f..f0515783ac 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -39,6 +39,10 @@ private static void printBottomLineMessage(String message) { System.out.println(message + "\n" + LINE); } + private static void printTopLineMessage(String message) { + System.out.println(LINE + "\n" + message); + } + // Used to print a line after displayed data public static void printBottomLine() { System.out.println("\n" + LINE); From 1115a5756461db1acb1fe6327580b2c3f1f861e7 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sun, 10 Oct 2021 01:26:09 +0800 Subject: [PATCH 120/756] Add corruptLineMessage, forbiddenInputMessage, forbiddenDetailMessage to TextUi --- src/main/java/seedu/ui/TextUi.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index f0515783ac..ff1fe38dd7 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -164,4 +164,21 @@ public static void numOutOfRangeMessage(int listSize) { } printDoubleLineMessage(message); } + + public static void corruptLineMessage(String line) { + printBottomLineMessage("Line \"" + line + "\" is corrupted and not loaded."); + } + + private void forbiddenInputCommaMessage(String newUserInput) { + String message = "Due to the storage nature of ConTech, we will remove\n" + + "commas (\",\"), and attempt to parse it as:\n" + + newUserInput; + printTopLineMessage(message); + } + + public static void forbiddenDetailMessage() { + String message = "As one of the details to be stored is \"null\", \n" + + "ConTech is unable to process it"; + printDoubleLineMessage(message); + } } From 3d053ca7131159dfa4928030ac8dfa1369a4028a Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sun, 10 Oct 2021 01:27:22 +0800 Subject: [PATCH 121/756] Implement failsafe in ContactsDecoder to detect any unparseable save data --- .../java/seedu/storage/ContactsDecoder.java | 33 +++++++++++++++---- 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index dcb692ac91..b97eb29c0c 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -4,7 +4,10 @@ import seedu.contact.ContactList; import seedu.contact.DetailType; import seedu.exception.FileErrorException; +import seedu.ui.TextUi; + import static seedu.storage.Storage.SEPARATOR; +import static seedu.parser.ContactParser.NUMBER_OF_DETAILS; import java.io.File; import java.io.FileNotFoundException; @@ -17,7 +20,7 @@ public static ContactList readContacts(File contactFile) throws FileErrorExcepti Scanner fileScanner = new Scanner(contactFile); while (fileScanner.hasNext()) { String contactText = fileScanner.nextLine(); - decodeContacts(updatedContactList, contactText); + decodeContact(updatedContactList, contactText); } } catch (FileNotFoundException e) { throw new FileErrorException(); @@ -25,11 +28,29 @@ public static ContactList readContacts(File contactFile) throws FileErrorExcepti return updatedContactList; } - private static void decodeContacts(ContactList contactList, String contactText) { + private static void decodeContact(ContactList contactList, String contactText) { String[] destructuredInputs = contactText.split(SEPARATOR); - String contactName = destructuredInputs[DetailType.NAME.getIndex()]; - String contactGithub = destructuredInputs[DetailType.GITHUB.getIndex()]; - // Add more later - contactList.addContact(new Contact(contactName, contactGithub)); + String[] compiledDetails = new String[NUMBER_OF_DETAILS]; + assert destructuredInputs.length > 0; + decodeDetails(compiledDetails, destructuredInputs); + // Add the decoded details into the contact list + try { + String contactName = destructuredInputs[DetailType.NAME.getIndex()]; + String contactGithub = destructuredInputs[DetailType.GITHUB.getIndex()]; + Contact newContact = new Contact(contactName, contactGithub); + contactList.addContact(newContact); + } catch (IndexOutOfBoundsException e) { + TextUi.corruptLineMessage(contactText); + } + } + + private static void decodeDetails(String[] compiledDetails, String[] destructuredInputs) { + if (compiledDetails.length != destructuredInputs.length) { + return; + } + assert compiledDetails.length == NUMBER_OF_DETAILS; + for (int i = 0; i < NUMBER_OF_DETAILS; i++) { + compiledDetails[i] = destructuredInputs[i]; + } } } From 9e7553bb228f554de1f3e0bddf358ed334157826 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sun, 10 Oct 2021 01:28:17 +0800 Subject: [PATCH 122/756] Abstract parseDetail function to abstract ContactParser as it is shared --- src/main/java/seedu/parser/ContactParser.java | 45 ++++++++++++++++++- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index 26273b0b17..183d6425df 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -1,6 +1,7 @@ package seedu.parser; import seedu.contact.DetailType; +import seedu.exception.ForbiddenDetailException; import seedu.exception.InvalidFlagException; import seedu.exception.MissingArgException; import seedu.exception.MissingDetailException; @@ -8,7 +9,8 @@ public abstract class ContactParser { public static final int CONTACT_PARAMS_START_INDEX = 1; public static final int NUMBER_OF_DETAILS = 2; - public static final int NUMBER_OF_EDIT_DETAILS = 3; + public static final int NUMBER_OF_ADD_ARGS = 2; + public static final int NUMBER_OF_EDIT_ARGS = 3; public static final String DETAIL_SEPARATOR = " -"; public static final int FLAG_INDEX_IN_DETAILS = 0; @@ -20,6 +22,45 @@ public abstract class ContactParser { public static final String GITHUB_FLAG = "g"; public abstract String[] parseContactDetails(String userInput) throws InvalidFlagException, - MissingArgException, MissingDetailException; + MissingArgException, MissingDetailException, ForbiddenDetailException; + /** + * This method takes in the contactDetails array and populates it with contact details. + * It will sift out the flags to decide what details to populate, using the + * enumeration from DetailType. + * + * @param contactDetails String array containing contact details + * @param detail Unparsed detail + * @throws InvalidFlagException If the flag given is not recognised + */ + public void parseDetail(String[] contactDetails, String detail) + throws InvalidFlagException, MissingDetailException, ForbiddenDetailException { + String[] destructuredDetails = detail.split(" ", NUMBER_OF_DETAILS); + //for commands that specify a flag, but do not specify any argument for that flag + //IndexOutOfBoundsException should not be thrown as the first if case will be true + if (destructuredDetails.length == 1 || destructuredDetails[1].trim().equalsIgnoreCase("")) { + throw new MissingDetailException(); + } + int indexToStore; + assert destructuredDetails.length == NUMBER_OF_DETAILS; + String flag = destructuredDetails[FLAG_INDEX_IN_DETAILS]; + String detailToStore = destructuredDetails[DETAIL_INDEX_IN_DETAILS].trim(); + indexToStore = getIndexToStore(flag); + contactDetails[indexToStore] = detailToStore; + } + + private int getIndexToStore(String flag) throws InvalidFlagException { + int indexToStore; + switch (flag) { + case NAME_FLAG: + indexToStore = DetailType.NAME.getIndex(); + break; + case GITHUB_FLAG: + indexToStore = DetailType.GITHUB.getIndex(); + break; + default: + throw new InvalidFlagException(); + } + return indexToStore; + } } From 47ee242351acb83d13437ebfe38703117d72dc7a Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sun, 10 Oct 2021 01:28:34 +0800 Subject: [PATCH 123/756] Implement "null" handling for input details --- src/main/java/seedu/parser/ContactParser.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index 183d6425df..d105380b54 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -45,6 +45,9 @@ public void parseDetail(String[] contactDetails, String detail) assert destructuredDetails.length == NUMBER_OF_DETAILS; String flag = destructuredDetails[FLAG_INDEX_IN_DETAILS]; String detailToStore = destructuredDetails[DETAIL_INDEX_IN_DETAILS].trim(); + if (detailToStore.equals("null")) { + throw new ForbiddenDetailException(); + } indexToStore = getIndexToStore(flag); contactDetails[indexToStore] = detailToStore; } From b1249e67dde8fbf88374f0ec911e96e0f12a6738 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sun, 10 Oct 2021 01:29:21 +0800 Subject: [PATCH 124/756] Introduce and implement ForbiddenDetailException in parsers and parserTests --- .../exception/ForbiddenDetailException.java | 4 ++ .../java/seedu/parser/AddContactParser.java | 34 +--------------- .../java/seedu/parser/EditContactParser.java | 39 ++----------------- .../seedu/parser/AddContactParserTest.java | 8 ++-- .../seedu/parser/EditContactParserTest.java | 3 +- 5 files changed, 17 insertions(+), 71 deletions(-) create mode 100644 src/main/java/seedu/exception/ForbiddenDetailException.java diff --git a/src/main/java/seedu/exception/ForbiddenDetailException.java b/src/main/java/seedu/exception/ForbiddenDetailException.java new file mode 100644 index 0000000000..81c74047cf --- /dev/null +++ b/src/main/java/seedu/exception/ForbiddenDetailException.java @@ -0,0 +1,4 @@ +package seedu.exception; + +public class ForbiddenDetailException extends Exception { +} diff --git a/src/main/java/seedu/parser/AddContactParser.java b/src/main/java/seedu/parser/AddContactParser.java index 6bcda6f3a0..535f735a52 100644 --- a/src/main/java/seedu/parser/AddContactParser.java +++ b/src/main/java/seedu/parser/AddContactParser.java @@ -1,10 +1,9 @@ package seedu.parser; -import seedu.contact.DetailType; +import seedu.exception.ForbiddenDetailException; import seedu.exception.InvalidFlagException; import seedu.exception.MissingArgException; import seedu.exception.MissingDetailException; -import seedu.exception.MissingNameException; public class AddContactParser extends ContactParser { /** @@ -20,7 +19,7 @@ public class AddContactParser extends ContactParser { * @throws InvalidFlagException If the flag given is not recognised */ public String[] parseContactDetails(String userInput) throws InvalidFlagException, MissingArgException, - MissingDetailException { + MissingDetailException, ForbiddenDetailException { String[] contactDetails = new String[NUMBER_OF_DETAILS]; String[] destructuredInputs = userInput.split(DETAIL_SEPARATOR); if (destructuredInputs.length == 1) { @@ -31,33 +30,4 @@ public String[] parseContactDetails(String userInput) throws InvalidFlagExceptio } return contactDetails; } - - /** - * This method takes in the contactDetails array and populates it with contact details. - * It will sift out the flags to decide what details to populate, using the - * enumeration from DetailType. - * - * @param contactDetails String array containing contact details - * @param detail Unparsed detail - * @throws InvalidFlagException If the flag given is not recognised - */ - public void parseDetail(String[] contactDetails, String detail) throws InvalidFlagException, - MissingDetailException { - String[] destructuredDetails = detail.split(" ", NUMBER_OF_DETAILS); - if (destructuredDetails.length < 2 || destructuredDetails[1].trim().equalsIgnoreCase("")) { - throw new MissingDetailException(); - } - int indexToStore; - switch (destructuredDetails[FLAG_INDEX_IN_DETAILS]) { - case NAME_FLAG: - indexToStore = DetailType.NAME.getIndex(); - break; - case GITHUB_FLAG: - indexToStore = DetailType.GITHUB.getIndex(); - break; - default: - throw new InvalidFlagException(); - } - contactDetails[indexToStore] = destructuredDetails[DETAIL_INDEX_IN_DETAILS].trim(); - } } diff --git a/src/main/java/seedu/parser/EditContactParser.java b/src/main/java/seedu/parser/EditContactParser.java index 7e574c7192..c2bc0afbc2 100644 --- a/src/main/java/seedu/parser/EditContactParser.java +++ b/src/main/java/seedu/parser/EditContactParser.java @@ -1,6 +1,6 @@ package seedu.parser; -import seedu.contact.DetailType; +import seedu.exception.ForbiddenDetailException; import seedu.exception.InvalidFlagException; import seedu.exception.MissingArgException; import seedu.exception.MissingDetailException; @@ -9,8 +9,8 @@ public class EditContactParser extends ContactParser { public static final String BUFFER = " "; public String[] parseContactDetails(String userInput) - throws InvalidFlagException, MissingDetailException, MissingArgException { - String[] inputDetails = userInput.split(" ", NUMBER_OF_EDIT_DETAILS); + throws InvalidFlagException, MissingDetailException, MissingArgException, ForbiddenDetailException { + String[] inputDetails = userInput.split(" ", NUMBER_OF_EDIT_ARGS); if (inputDetails.length < 3) { //if arguments are missing e.g. edit 2 throw new MissingArgException(); @@ -24,39 +24,8 @@ public String[] parseContactDetails(String userInput) return contactDetails; } - /** - * This method takes in the contactDetails array and populates it with contact details. - * It will sift out the flags to decide what details to populate, using the - * enumeration from DetailType. - * - * @param contactDetails String array containing contact details - * @param detail Unparsed detail - * @throws InvalidFlagException If the flag given is not recognised - */ - public void parseDetail(String[] contactDetails, String detail) - throws InvalidFlagException, MissingDetailException { - String[] destructuredDetails = detail.split(" ", NUMBER_OF_EDIT_DETAILS); - //for commands that specify a flag, but do not specify any argument for that flag - //IndexOutOfBoundsException should not be thrown as the first if case will be true - if (destructuredDetails.length == 1 || destructuredDetails[1].trim().equalsIgnoreCase("")) { - throw new MissingDetailException(); - } - int indexToStore; - switch (destructuredDetails[FLAG_INDEX_IN_DETAILS]) { - case NAME_FLAG: - indexToStore = DetailType.NAME.getIndex(); - break; - case GITHUB_FLAG: - indexToStore = DetailType.GITHUB.getIndex(); - break; - default: - throw new InvalidFlagException(); - } - contactDetails[indexToStore] = destructuredDetails[DETAIL_INDEX_IN_DETAILS]; - } - public int getIndex(String input) throws MissingArgException { - String[] destructuredInputs = input.split(" ", NUMBER_OF_EDIT_DETAILS); + String[] destructuredInputs = input.split(" ", NUMBER_OF_EDIT_ARGS); if (destructuredInputs.length < 3) { //if arguments are missing e.g. edit 2 throw new MissingArgException(); diff --git a/src/test/java/seedu/parser/AddContactParserTest.java b/src/test/java/seedu/parser/AddContactParserTest.java index f91ddacdf6..86cc3f22c8 100644 --- a/src/test/java/seedu/parser/AddContactParserTest.java +++ b/src/test/java/seedu/parser/AddContactParserTest.java @@ -3,10 +3,12 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import seedu.contact.DetailType; +import seedu.exception.ForbiddenDetailException; import seedu.exception.InvalidFlagException; import seedu.exception.MissingArgException; import seedu.exception.MissingDetailException; +import static seedu.parser.ContactParser.NUMBER_OF_ADD_ARGS; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -28,7 +30,7 @@ public void setUp() { @Test void parseContactDetails_inputsWithIrregularSpacing_expectCorrectDetails() throws InvalidFlagException, - MissingDetailException, MissingArgException { + MissingDetailException, MissingArgException, ForbiddenDetailException { inputUserInput = "add -n andre -g ng-andre "; actualOutput = addContactParser.parseContactDetails(inputUserInput); expectedOutput = new String[]{"andre", "ng-andre"}; @@ -76,7 +78,7 @@ void parseDetail_invalidFlagUsed_expectException() { @Test void parseDetail_inputsWithTrailingSpaces_expectNewContactDetail() throws InvalidFlagException, - MissingDetailException { + MissingDetailException, ForbiddenDetailException { inputDetail = "n andre"; addContactParser.parseDetail(inputContactDetails, inputDetail); assertEquals("andre", inputContactDetails[DetailType.NAME.getIndex()]); @@ -84,7 +86,7 @@ void parseDetail_inputsWithTrailingSpaces_expectNewContactDetail() throws Invali @Test void parseDetail_inputsWithSpaceInDetail_expectNewContactDetail() throws InvalidFlagException, - MissingDetailException { + MissingDetailException, ForbiddenDetailException { inputDetail = "n Marcus Bory"; addContactParser.parseDetail(inputContactDetails, inputDetail); assertEquals("Marcus Bory", inputContactDetails[DetailType.NAME.getIndex()]); diff --git a/src/test/java/seedu/parser/EditContactParserTest.java b/src/test/java/seedu/parser/EditContactParserTest.java index 490c3583b3..10595b0a3c 100644 --- a/src/test/java/seedu/parser/EditContactParserTest.java +++ b/src/test/java/seedu/parser/EditContactParserTest.java @@ -2,6 +2,7 @@ import org.junit.jupiter.api.Test; +import seedu.exception.ForbiddenDetailException; import seedu.exception.InvalidFlagException; import seedu.exception.MissingArgException; import seedu.exception.MissingDetailException; @@ -16,7 +17,7 @@ class EditContactParserTest { private EditContactParser editContactParser = new EditContactParser(); @Test - void parseContactDetails() throws MissingDetailException, MissingArgException, InvalidFlagException { + void parseContactDetails() throws MissingDetailException, MissingArgException, InvalidFlagException, ForbiddenDetailException { String[] expectedResult = {null, "github"}; String testInput = "edit 1 -g github"; String[] actualResult = editContactParser.parseContactDetails(testInput); From 1166be0ac4f466c792caacadf06d71556ec67ed3 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sun, 10 Oct 2021 01:29:48 +0800 Subject: [PATCH 125/756] Implement forbidden detail command --- src/main/java/seedu/command/FailedCommand.java | 3 +++ src/main/java/seedu/parser/FailedCommandType.java | 3 ++- src/main/java/seedu/parser/MainParser.java | 8 ++++++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/command/FailedCommand.java b/src/main/java/seedu/command/FailedCommand.java index 8c64216e1c..4a46a7c58c 100644 --- a/src/main/java/seedu/command/FailedCommand.java +++ b/src/main/java/seedu/command/FailedCommand.java @@ -43,6 +43,9 @@ public void execute() { case MISSING_NAME: TextUi.missingNameMessage(); break; + case FORBIDDEN_DETAIL: + TextUi.forbiddenDetailMessage(); + break; default: return; } diff --git a/src/main/java/seedu/parser/FailedCommandType.java b/src/main/java/seedu/parser/FailedCommandType.java index d92cc5c16f..29beb0fab0 100644 --- a/src/main/java/seedu/parser/FailedCommandType.java +++ b/src/main/java/seedu/parser/FailedCommandType.java @@ -2,5 +2,6 @@ public enum FailedCommandType { GENERAL, INVALID_FLAG, MISSING_ARG, MISSING_DETAIL, INVALID_NUM, - INVALID_FORMAT, NUM_OUT_OF_BOUND, INVALID_INDEX, MISSING_NAME; + INVALID_FORMAT, NUM_OUT_OF_BOUND, INVALID_INDEX, MISSING_NAME, + FORBIDDEN_DETAIL; } diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index aa91c02fd1..b0d8a09583 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -10,13 +10,12 @@ import seedu.command.ListContactsCommand; import seedu.contact.DetailType; +import seedu.exception.ForbiddenDetailException; import seedu.exception.InvalidFlagException; import seedu.exception.MissingArgException; import seedu.exception.MissingDetailException; import seedu.exception.MissingNameException; -import java.util.Arrays; - public class MainParser { private static final String ADD_CONTACT_COMD = "add"; private static final String EDIT_CONTACT_COMD = "edit"; @@ -24,6 +23,7 @@ public class MainParser { private static final String EXIT_COMD = "exit"; private static final String VIEW_COMD = "view"; private static final String LIST_COMD = "list"; + private static final String FORBIDDEN_COMD = "forbidden"; private static final int COMD_WORD_INDEX = 0; private static final int ISOLATE_COMD_WORD = 2; @@ -83,6 +83,8 @@ private Command parseAddContact(String userInput) { return new FailedCommand(FailedCommandType.MISSING_NAME); } catch (MissingDetailException e) { return new FailedCommand(FailedCommandType.MISSING_DETAIL); + } catch (ForbiddenDetailException e) { + return new FailedCommand(FailedCommandType.FORBIDDEN_DETAIL); } } @@ -101,6 +103,8 @@ private Command parseEditContact(String userInput) { // userInput is raw user in return new FailedCommand(FailedCommandType.INVALID_INDEX); } catch (MissingDetailException e) { return new FailedCommand(FailedCommandType.MISSING_DETAIL); + } catch (ForbiddenDetailException e) { + return new FailedCommand(FailedCommandType.FORBIDDEN_DETAIL); } } From 59f47acb7eea5336a1aa80048d4487f110324faa Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sun, 10 Oct 2021 01:30:09 +0800 Subject: [PATCH 126/756] Update IO redirection tests to include forbidden details, commas --- text-ui-test/ACTUAL.TXT | 29 +++++++++++++++++++++++++++++ text-ui-test/EXPECTED-UNIX.TXT | 29 +++++++++++++++++++++++++++++ text-ui-test/EXPECTED.TXT | 29 +++++++++++++++++++++++++++++ text-ui-test/input.txt | 5 +++++ 4 files changed, 92 insertions(+) diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index 7419045e36..ffe0a3671f 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -191,6 +191,35 @@ There are missing details. Please remove any flags with no details ____________________________________________________________ +____________________________________________________________ + +Due to the storage nature of ConTech, we will remove +commas (","), and attempt to parse it as: +add -n lezong mun -g lezaimun +____________________________________________________________ +ConTech has added the specified contact: lezong mun +You now have 5 contact(s). +____________________________________________________________ + +____________________________________________________________ +As one of the details to be stored is "null", +ConTech is unable to process it +____________________________________________________________ + +____________________________________________________________ +As one of the details to be stored is "null", +ConTech is unable to process it +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: dev +You now have 6 contact(s). +____________________________________________________________ + +____________________________________________________________ +ConTech has edited the specified contact: lezongmun +____________________________________________________________ + ____________________________________________________________ ConTech will now shutdown. We hope you have enjoyed using it. diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index 7419045e36..ffe0a3671f 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -191,6 +191,35 @@ There are missing details. Please remove any flags with no details ____________________________________________________________ +____________________________________________________________ + +Due to the storage nature of ConTech, we will remove +commas (","), and attempt to parse it as: +add -n lezong mun -g lezaimun +____________________________________________________________ +ConTech has added the specified contact: lezong mun +You now have 5 contact(s). +____________________________________________________________ + +____________________________________________________________ +As one of the details to be stored is "null", +ConTech is unable to process it +____________________________________________________________ + +____________________________________________________________ +As one of the details to be stored is "null", +ConTech is unable to process it +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: dev +You now have 6 contact(s). +____________________________________________________________ + +____________________________________________________________ +ConTech has edited the specified contact: lezongmun +____________________________________________________________ + ____________________________________________________________ ConTech will now shutdown. We hope you have enjoyed using it. diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 7419045e36..ffe0a3671f 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -191,6 +191,35 @@ There are missing details. Please remove any flags with no details ____________________________________________________________ +____________________________________________________________ + +Due to the storage nature of ConTech, we will remove +commas (","), and attempt to parse it as: +add -n lezong mun -g lezaimun +____________________________________________________________ +ConTech has added the specified contact: lezong mun +You now have 5 contact(s). +____________________________________________________________ + +____________________________________________________________ +As one of the details to be stored is "null", +ConTech is unable to process it +____________________________________________________________ + +____________________________________________________________ +As one of the details to be stored is "null", +ConTech is unable to process it +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: dev +You now have 6 contact(s). +____________________________________________________________ + +____________________________________________________________ +ConTech has edited the specified contact: lezongmun +____________________________________________________________ + ____________________________________________________________ ConTech will now shutdown. We hope you have enjoyed using it. diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index 9e33e0ccdf..5aca152a2c 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -29,4 +29,9 @@ list view abc view 0 add -n -g + add -n le,zong, mun -g lezaimun + add -n null -g legit + add -n name -g null + add -n dev -g nullptr + edit 3 -g new-git exit \ No newline at end of file From 6f019f70c1187efa3c4b4f03b5c25f65e7547307 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sun, 10 Oct 2021 01:44:43 +0800 Subject: [PATCH 127/756] Update to fix checkstyle --- src/test/java/seedu/parser/EditContactParserTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/seedu/parser/EditContactParserTest.java b/src/test/java/seedu/parser/EditContactParserTest.java index 10595b0a3c..851fb955a0 100644 --- a/src/test/java/seedu/parser/EditContactParserTest.java +++ b/src/test/java/seedu/parser/EditContactParserTest.java @@ -17,7 +17,8 @@ class EditContactParserTest { private EditContactParser editContactParser = new EditContactParser(); @Test - void parseContactDetails() throws MissingDetailException, MissingArgException, InvalidFlagException, ForbiddenDetailException { + void parseContactDetails() throws MissingDetailException, + MissingArgException, InvalidFlagException, ForbiddenDetailException { String[] expectedResult = {null, "github"}; String testInput = "edit 1 -g github"; String[] actualResult = editContactParser.parseContactDetails(testInput); From c9c1a06d9cd0fa3de6b5c40a1d52e273a7798c99 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sun, 10 Oct 2021 02:22:31 +0800 Subject: [PATCH 128/756] Update to use isBlank() method for string to check missing details in ContactParser --- src/main/java/seedu/parser/ContactParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index d105380b54..f42df6185a 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -38,7 +38,7 @@ public void parseDetail(String[] contactDetails, String detail) String[] destructuredDetails = detail.split(" ", NUMBER_OF_DETAILS); //for commands that specify a flag, but do not specify any argument for that flag //IndexOutOfBoundsException should not be thrown as the first if case will be true - if (destructuredDetails.length == 1 || destructuredDetails[1].trim().equalsIgnoreCase("")) { + if (destructuredDetails.length == 1 || destructuredDetails[1].isBlank()) { throw new MissingDetailException(); } int indexToStore; From d2737c159140b63a187977460a213fa6dffdf0cc Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sun, 10 Oct 2021 02:22:45 +0800 Subject: [PATCH 129/756] Update missing detail error message --- src/main/java/seedu/ui/TextUi.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index ff1fe38dd7..297174c5d1 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -124,7 +124,8 @@ public static void invalidIndexMessage() { } public static void missingDetailMessage() { - String message = "There are missing details.\n" + "Please remove any flags with no details"; + String message = "There are missing details.\n" + "Please remove any flags with no details, \n" + + "and ensure that your flags used are correct:\n" + " -n NAME\n" + " -g GITHUB"; printDoubleLineMessage(message); } From 2d3520c979b0704c2343c3ef2d55c938265939a8 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sun, 10 Oct 2021 02:22:57 +0800 Subject: [PATCH 130/756] Update IO redirection tests due to updates in TextUi --- text-ui-test/ACTUAL.TXT | 15 ++++++++++++--- text-ui-test/EXPECTED-UNIX.TXT | 15 ++++++++++++--- text-ui-test/EXPECTED.TXT | 15 ++++++++++++--- 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index ffe0a3671f..ab1543b581 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -80,7 +80,10 @@ ____________________________________________________________ ____________________________________________________________ There are missing details. -Please remove any flags with no details +Please remove any flags with no details, +and ensure that your flags used are correct: + -n NAME + -g GITHUB ____________________________________________________________ ____________________________________________________________ @@ -127,7 +130,10 @@ ____________________________________________________________ ____________________________________________________________ There are missing details. -Please remove any flags with no details +Please remove any flags with no details, +and ensure that your flags used are correct: + -n NAME + -g GITHUB ____________________________________________________________ ____________________________________________________________ @@ -188,7 +194,10 @@ ____________________________________________________________ ____________________________________________________________ There are missing details. -Please remove any flags with no details +Please remove any flags with no details, +and ensure that your flags used are correct: + -n NAME + -g GITHUB ____________________________________________________________ ____________________________________________________________ diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index ffe0a3671f..ab1543b581 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -80,7 +80,10 @@ ____________________________________________________________ ____________________________________________________________ There are missing details. -Please remove any flags with no details +Please remove any flags with no details, +and ensure that your flags used are correct: + -n NAME + -g GITHUB ____________________________________________________________ ____________________________________________________________ @@ -127,7 +130,10 @@ ____________________________________________________________ ____________________________________________________________ There are missing details. -Please remove any flags with no details +Please remove any flags with no details, +and ensure that your flags used are correct: + -n NAME + -g GITHUB ____________________________________________________________ ____________________________________________________________ @@ -188,7 +194,10 @@ ____________________________________________________________ ____________________________________________________________ There are missing details. -Please remove any flags with no details +Please remove any flags with no details, +and ensure that your flags used are correct: + -n NAME + -g GITHUB ____________________________________________________________ ____________________________________________________________ diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index ffe0a3671f..ab1543b581 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -80,7 +80,10 @@ ____________________________________________________________ ____________________________________________________________ There are missing details. -Please remove any flags with no details +Please remove any flags with no details, +and ensure that your flags used are correct: + -n NAME + -g GITHUB ____________________________________________________________ ____________________________________________________________ @@ -127,7 +130,10 @@ ____________________________________________________________ ____________________________________________________________ There are missing details. -Please remove any flags with no details +Please remove any flags with no details, +and ensure that your flags used are correct: + -n NAME + -g GITHUB ____________________________________________________________ ____________________________________________________________ @@ -188,7 +194,10 @@ ____________________________________________________________ ____________________________________________________________ There are missing details. -Please remove any flags with no details +Please remove any flags with no details, +and ensure that your flags used are correct: + -n NAME + -g GITHUB ____________________________________________________________ ____________________________________________________________ From 3d19eb18cae8672f346273689a03d10354d6dd1a Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Mon, 11 Oct 2021 10:13:51 +0800 Subject: [PATCH 131/756] Add new fields for contact with getter and setter methods --- src/main/java/seedu/contact/Contact.java | 36 ++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/main/java/seedu/contact/Contact.java b/src/main/java/seedu/contact/Contact.java index 072f1920b2..b115a7eb7d 100644 --- a/src/main/java/seedu/contact/Contact.java +++ b/src/main/java/seedu/contact/Contact.java @@ -3,6 +3,10 @@ public class Contact { private String name; private String github; + private String email; + private String linkedin; + private String twitter; + private String telegram; public Contact(String name, String github) { this.name = name; @@ -24,4 +28,36 @@ public void setName(String name) { public void setGithub(String github) { this.github = github; } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getLinkedin() { + return linkedin; + } + + public void setLinkedin(String linkedin) { + this.linkedin = linkedin; + } + + public String getTwitter() { + return twitter; + } + + public void setTwitter(String twitter) { + this.twitter = twitter; + } + + public String getTelegram() { + return telegram; + } + + public void setTelegram(String telegram) { + this.telegram = telegram; + } } From 7932aedbbf56b3bc77f29fb88a14d59945bf5d21 Mon Sep 17 00:00:00 2001 From: ng-andre Date: Mon, 11 Oct 2021 14:31:01 +0800 Subject: [PATCH 132/756] Update flag constants --- src/main/java/seedu/parser/ContactParser.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index f42df6185a..ed42b24f99 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -20,6 +20,10 @@ public abstract class ContactParser { public static final String NAME_FLAG = "n"; public static final String GITHUB_FLAG = "g"; + public static final String EMAIL_FLAG = "e"; + public static final String TWITTER_FLAG = "tw"; + public static final String LINKEDIN_FLAG = "l"; + public static final String TELEGRAM_FLAG = "te"; public abstract String[] parseContactDetails(String userInput) throws InvalidFlagException, MissingArgException, MissingDetailException, ForbiddenDetailException; From 9d7af9d3bfd56060de900300b27e2095bf6ca1e1 Mon Sep 17 00:00:00 2001 From: ng-andre Date: Mon, 11 Oct 2021 14:42:20 +0800 Subject: [PATCH 133/756] Update constants --- src/main/java/seedu/parser/ContactParser.java | 1 + src/main/java/seedu/parser/EditContactParser.java | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index ed42b24f99..29d88c1c0f 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -11,6 +11,7 @@ public abstract class ContactParser { public static final int NUMBER_OF_DETAILS = 2; public static final int NUMBER_OF_ADD_ARGS = 2; public static final int NUMBER_OF_EDIT_ARGS = 3; + public static final int NUMBER_OF_FIELDS = 6; public static final String DETAIL_SEPARATOR = " -"; public static final int FLAG_INDEX_IN_DETAILS = 0; diff --git a/src/main/java/seedu/parser/EditContactParser.java b/src/main/java/seedu/parser/EditContactParser.java index c2bc0afbc2..17297bdbad 100644 --- a/src/main/java/seedu/parser/EditContactParser.java +++ b/src/main/java/seedu/parser/EditContactParser.java @@ -11,11 +11,11 @@ public class EditContactParser extends ContactParser { public String[] parseContactDetails(String userInput) throws InvalidFlagException, MissingDetailException, MissingArgException, ForbiddenDetailException { String[] inputDetails = userInput.split(" ", NUMBER_OF_EDIT_ARGS); - if (inputDetails.length < 3) { + if (inputDetails.length < NUMBER_OF_EDIT_ARGS) { //if arguments are missing e.g. edit 2 throw new MissingArgException(); } - String[] contactDetails = new String[NUMBER_OF_DETAILS]; //initialise null array of strings + String[] contactDetails = new String[NUMBER_OF_FIELDS]; //initialise null array of strings //buffer is used to ensure first flag can be read String[] destructuredInputs = (BUFFER + inputDetails[USER_INFO_INDEX]).split(DETAIL_SEPARATOR); for (int i = CONTACT_PARAMS_START_INDEX; i < destructuredInputs.length; i++) { @@ -26,7 +26,7 @@ public String[] parseContactDetails(String userInput) public int getIndex(String input) throws MissingArgException { String[] destructuredInputs = input.split(" ", NUMBER_OF_EDIT_ARGS); - if (destructuredInputs.length < 3) { + if (destructuredInputs.length < NUMBER_OF_EDIT_ARGS) { //if arguments are missing e.g. edit 2 throw new MissingArgException(); } From 685fdb8cea81f8de17ea61a40db6f9aefeae5aa8 Mon Sep 17 00:00:00 2001 From: ng-andre Date: Mon, 11 Oct 2021 14:53:17 +0800 Subject: [PATCH 134/756] Update switch cases for indexToStore --- src/main/java/seedu/parser/ContactParser.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index 29d88c1c0f..9667eb42c2 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -66,6 +66,18 @@ private int getIndexToStore(String flag) throws InvalidFlagException { case GITHUB_FLAG: indexToStore = DetailType.GITHUB.getIndex(); break; + case TELEGRAM_FLAG: + indexToStore = DetailType.TELEGRAM.getIndex(); + break; + case TWITTER_FLAG: + indexToStore = DetailType.TWITTER.getIndex(); + break; + case EMAIL_FLAG: + indexToStore = DetailType.EMAIL.getIndex(); + break; + case LINKEDIN_FLAG: + indexToStore = DetailType.LINKEDIN.getIndex(); + break; default: throw new InvalidFlagException(); } From 814729a7e998c108be4e341f7670c652699fb720 Mon Sep 17 00:00:00 2001 From: ng-andre Date: Mon, 11 Oct 2021 14:54:20 +0800 Subject: [PATCH 135/756] Update order of declaration of constants to match enum index --- src/main/java/seedu/parser/ContactParser.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index 9667eb42c2..8ec4bcf5dd 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -21,10 +21,10 @@ public abstract class ContactParser { public static final String NAME_FLAG = "n"; public static final String GITHUB_FLAG = "g"; - public static final String EMAIL_FLAG = "e"; + public static final String TELEGRAM_FLAG = "te"; public static final String TWITTER_FLAG = "tw"; + public static final String EMAIL_FLAG = "e"; public static final String LINKEDIN_FLAG = "l"; - public static final String TELEGRAM_FLAG = "te"; public abstract String[] parseContactDetails(String userInput) throws InvalidFlagException, MissingArgException, MissingDetailException, ForbiddenDetailException; From 0df871bb3ea667c780638129a424d8c839e640fc Mon Sep 17 00:00:00 2001 From: ng-andre Date: Mon, 11 Oct 2021 15:26:27 +0800 Subject: [PATCH 136/756] Update JUnit test to match the correct number of fields --- src/test/java/seedu/parser/EditContactParserTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/seedu/parser/EditContactParserTest.java b/src/test/java/seedu/parser/EditContactParserTest.java index 851fb955a0..79970a3d1c 100644 --- a/src/test/java/seedu/parser/EditContactParserTest.java +++ b/src/test/java/seedu/parser/EditContactParserTest.java @@ -19,7 +19,7 @@ class EditContactParserTest { @Test void parseContactDetails() throws MissingDetailException, MissingArgException, InvalidFlagException, ForbiddenDetailException { - String[] expectedResult = {null, "github"}; + String[] expectedResult = {null, "github", null, null, null, null}; String testInput = "edit 1 -g github"; String[] actualResult = editContactParser.parseContactDetails(testInput); assertArrayEquals(expectedResult, actualResult); From 4b59221792734e3fa90f6959b286c2b897910ef3 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Mon, 11 Oct 2021 22:33:25 +0800 Subject: [PATCH 137/756] Update Contact constructor to include additional fields --- src/main/java/seedu/contact/Contact.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/contact/Contact.java b/src/main/java/seedu/contact/Contact.java index b115a7eb7d..b1ba302b8b 100644 --- a/src/main/java/seedu/contact/Contact.java +++ b/src/main/java/seedu/contact/Contact.java @@ -3,14 +3,18 @@ public class Contact { private String name; private String github; - private String email; private String linkedin; - private String twitter; private String telegram; + private String twitter; + private String email; - public Contact(String name, String github) { + public Contact(String name, String github, String linkedin, String telegram, String twitter, String email) { this.name = name; this.github = github; + this.linkedin = linkedin; + this.telegram = telegram; + this.twitter = twitter; + this.email = email; } public String getName() { From 2898c0e495b892d83830f79da340636a2924da74 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Mon, 11 Oct 2021 22:45:34 +0800 Subject: [PATCH 138/756] Add additional field attributes to AddContactCommand --- src/main/java/seedu/command/AddContactCommand.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/seedu/command/AddContactCommand.java b/src/main/java/seedu/command/AddContactCommand.java index 830110bc4e..7262476bb0 100644 --- a/src/main/java/seedu/command/AddContactCommand.java +++ b/src/main/java/seedu/command/AddContactCommand.java @@ -6,6 +6,10 @@ public class AddContactCommand extends Command { private final String name; private final String github; + private final String linkedin; + private final String telegram; + private final String twitter; + private final String email; public String getName() { return name; From c4e460f24779efa50f32aa8c83f4e6de84c7e6b1 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Mon, 11 Oct 2021 22:50:22 +0800 Subject: [PATCH 139/756] Implement getters for additional attributes --- .../java/seedu/command/AddContactCommand.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/main/java/seedu/command/AddContactCommand.java b/src/main/java/seedu/command/AddContactCommand.java index 7262476bb0..819c607fd2 100644 --- a/src/main/java/seedu/command/AddContactCommand.java +++ b/src/main/java/seedu/command/AddContactCommand.java @@ -11,6 +11,22 @@ public class AddContactCommand extends Command { private final String twitter; private final String email; + public String getLinkedin() { + return linkedin; + } + + public String getTelegram() { + return telegram; + } + + public String getTwitter() { + return twitter; + } + + public String getEmail() { + return email; + } + public String getName() { return name; } From 49d34652e92dddfc67c4d80cd2e0babf65d1c6b5 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Mon, 11 Oct 2021 22:50:56 +0800 Subject: [PATCH 140/756] Update AddContactCommand constructor to include additional fields --- src/main/java/seedu/command/AddContactCommand.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/command/AddContactCommand.java b/src/main/java/seedu/command/AddContactCommand.java index 819c607fd2..b52bd7d97e 100644 --- a/src/main/java/seedu/command/AddContactCommand.java +++ b/src/main/java/seedu/command/AddContactCommand.java @@ -35,9 +35,14 @@ public String getGithub() { return github; } - public AddContactCommand(String name, String github) { + public AddContactCommand(String name, String github, String linkedin, String telegram, String twitter, + String email) { this.name = name; this.github = github; + this.linkedin = linkedin; + this.telegram = telegram; + this.twitter = twitter; + this.email = email; } public void execute() { From c68077fa9a2cb7dc60d86ed826b1a83e1e6940eb Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Mon, 11 Oct 2021 22:51:14 +0800 Subject: [PATCH 141/756] Update AddContactCommand.execute() to include new fields --- src/main/java/seedu/command/AddContactCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/command/AddContactCommand.java b/src/main/java/seedu/command/AddContactCommand.java index b52bd7d97e..2aa17be17a 100644 --- a/src/main/java/seedu/command/AddContactCommand.java +++ b/src/main/java/seedu/command/AddContactCommand.java @@ -46,7 +46,7 @@ public AddContactCommand(String name, String github, String linkedin, String tel } public void execute() { - Contact addedContact = new Contact(name, github); + Contact addedContact = new Contact(name, github, linkedin, telegram, twitter, email); contactList.addContact(addedContact); TextUi.addContactMessage(name, contactList.getListSize()); } From 16398575a3eb63421ce4ebe8b1bda55d87280a96 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Mon, 11 Oct 2021 22:56:01 +0800 Subject: [PATCH 142/756] Update AddContactParser javadocs --- src/main/java/seedu/parser/AddContactParser.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/parser/AddContactParser.java b/src/main/java/seedu/parser/AddContactParser.java index 535f735a52..82769dc7ab 100644 --- a/src/main/java/seedu/parser/AddContactParser.java +++ b/src/main/java/seedu/parser/AddContactParser.java @@ -10,8 +10,8 @@ public class AddContactParser extends ContactParser { * Returns a String[] containing the user's input and the arguments specified for * each detail flag. Each detail is parsed individually using parseDetail. *

- * Eg. userInput => add -n andre -g ng-andre - * output => ["andre", "ng-andre"] + * Eg. userInput => add -n andre -g ng-andre -te ng_andre -tw andre -e andre@gmail.com -l ng-andre + * output => ["andre", "ng-andre", "ng_andre", "ng-andre", "ng_andre", "andre", "andre@gmail.com"] *

* Note: Each index is properly identified by enumeration in contact/DetailType * @param userInput User's complete untouched input From 78d7495eb211d5a197b1bb1d2fcf47b1badc5906 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Mon, 11 Oct 2021 22:56:15 +0800 Subject: [PATCH 143/756] Update constants in AddContactParser --- src/main/java/seedu/parser/AddContactParser.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/parser/AddContactParser.java b/src/main/java/seedu/parser/AddContactParser.java index 82769dc7ab..09802ab3b2 100644 --- a/src/main/java/seedu/parser/AddContactParser.java +++ b/src/main/java/seedu/parser/AddContactParser.java @@ -20,9 +20,9 @@ public class AddContactParser extends ContactParser { */ public String[] parseContactDetails(String userInput) throws InvalidFlagException, MissingArgException, MissingDetailException, ForbiddenDetailException { - String[] contactDetails = new String[NUMBER_OF_DETAILS]; + String[] contactDetails = new String[NUMBER_OF_FIELDS]; String[] destructuredInputs = userInput.split(DETAIL_SEPARATOR); - if (destructuredInputs.length == 1) { + if (destructuredInputs.length < NUMBER_OF_ADD_ARGS) { throw new MissingArgException(); } for (int i = CONTACT_PARAMS_START_INDEX; i < destructuredInputs.length; i++) { From 970375762ea4b36a36ab4a91d0d39a6657ff4ec9 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Mon, 11 Oct 2021 23:10:29 +0800 Subject: [PATCH 144/756] Add new constant for number of fields; Add additional flags --- src/main/java/seedu/parser/ContactParser.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index f42df6185a..c036b966b3 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -11,6 +11,7 @@ public abstract class ContactParser { public static final int NUMBER_OF_DETAILS = 2; public static final int NUMBER_OF_ADD_ARGS = 2; public static final int NUMBER_OF_EDIT_ARGS = 3; + public static final int NUMBER_OF_FIELDS = 6; public static final String DETAIL_SEPARATOR = " -"; public static final int FLAG_INDEX_IN_DETAILS = 0; @@ -20,6 +21,10 @@ public abstract class ContactParser { public static final String NAME_FLAG = "n"; public static final String GITHUB_FLAG = "g"; + public static final String TELEGRAM_FLAG = "te"; + public static final String TWITTER_FLAG = "tw"; + public static final String EMAIL_FLAG = "e"; + public static final String LINKEDIN_FLAG = "l"; public abstract String[] parseContactDetails(String userInput) throws InvalidFlagException, MissingArgException, MissingDetailException, ForbiddenDetailException; From 856611dec57f6a635d6b4216a5c4fdabe33b00b0 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Mon, 11 Oct 2021 23:10:47 +0800 Subject: [PATCH 145/756] Add more cases for additional flags in getIndexToStore() --- src/main/java/seedu/parser/ContactParser.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index c036b966b3..8ec4bcf5dd 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -66,6 +66,18 @@ private int getIndexToStore(String flag) throws InvalidFlagException { case GITHUB_FLAG: indexToStore = DetailType.GITHUB.getIndex(); break; + case TELEGRAM_FLAG: + indexToStore = DetailType.TELEGRAM.getIndex(); + break; + case TWITTER_FLAG: + indexToStore = DetailType.TWITTER.getIndex(); + break; + case EMAIL_FLAG: + indexToStore = DetailType.EMAIL.getIndex(); + break; + case LINKEDIN_FLAG: + indexToStore = DetailType.LINKEDIN.getIndex(); + break; default: throw new InvalidFlagException(); } From c5e8e712fde5640a7eb03341b348679a9064c64e Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Mon, 11 Oct 2021 23:11:04 +0800 Subject: [PATCH 146/756] Update constants in EditContactParser --- src/main/java/seedu/parser/EditContactParser.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/parser/EditContactParser.java b/src/main/java/seedu/parser/EditContactParser.java index c2bc0afbc2..17297bdbad 100644 --- a/src/main/java/seedu/parser/EditContactParser.java +++ b/src/main/java/seedu/parser/EditContactParser.java @@ -11,11 +11,11 @@ public class EditContactParser extends ContactParser { public String[] parseContactDetails(String userInput) throws InvalidFlagException, MissingDetailException, MissingArgException, ForbiddenDetailException { String[] inputDetails = userInput.split(" ", NUMBER_OF_EDIT_ARGS); - if (inputDetails.length < 3) { + if (inputDetails.length < NUMBER_OF_EDIT_ARGS) { //if arguments are missing e.g. edit 2 throw new MissingArgException(); } - String[] contactDetails = new String[NUMBER_OF_DETAILS]; //initialise null array of strings + String[] contactDetails = new String[NUMBER_OF_FIELDS]; //initialise null array of strings //buffer is used to ensure first flag can be read String[] destructuredInputs = (BUFFER + inputDetails[USER_INFO_INDEX]).split(DETAIL_SEPARATOR); for (int i = CONTACT_PARAMS_START_INDEX; i < destructuredInputs.length; i++) { @@ -26,7 +26,7 @@ public String[] parseContactDetails(String userInput) public int getIndex(String input) throws MissingArgException { String[] destructuredInputs = input.split(" ", NUMBER_OF_EDIT_ARGS); - if (destructuredInputs.length < 3) { + if (destructuredInputs.length < NUMBER_OF_EDIT_ARGS) { //if arguments are missing e.g. edit 2 throw new MissingArgException(); } From 6faa0d784b110675e65accfd7391efc904b44e79 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Mon, 11 Oct 2021 23:12:01 +0800 Subject: [PATCH 147/756] Add additional details to be handled in MainParser for adding contacts --- src/main/java/seedu/parser/MainParser.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index b0d8a09583..939eeed01a 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -16,6 +16,8 @@ import seedu.exception.MissingDetailException; import seedu.exception.MissingNameException; +import static seedu.parser.ContactParser.NUMBER_OF_FIELDS; + public class MainParser { private static final String ADD_CONTACT_COMD = "add"; private static final String EDIT_CONTACT_COMD = "edit"; @@ -74,7 +76,14 @@ private Command parseAddContact(String userInput) { if (details[NAME_INDEX] == null) { throw new MissingNameException(); } - return new AddContactCommand(details[DetailType.NAME.getIndex()], details[DetailType.GITHUB.getIndex()]); + assert details.length == NUMBER_OF_FIELDS; + String name = details[DetailType.NAME.getIndex()]; + String github = details[DetailType.GITHUB.getIndex()]; + String linkedin = details[DetailType.LINKEDIN.getIndex()]; + String telegram = details[DetailType.TELEGRAM.getIndex()]; + String twitter = details[DetailType.TWITTER.getIndex()]; + String email = details[DetailType.EMAIL.getIndex()]; + return new AddContactCommand(name, github, linkedin, telegram, twitter, email); } catch (InvalidFlagException e) { return new FailedCommand(FailedCommandType.INVALID_FLAG); } catch (MissingArgException e) { From 234c944a8ddb8b2afd400f6c9296fce63a7cb5bd Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Mon, 11 Oct 2021 23:14:15 +0800 Subject: [PATCH 148/756] Update decoding of contacts from save file --- src/main/java/seedu/storage/ContactsDecoder.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index b97eb29c0c..ed6d096b98 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -7,7 +7,7 @@ import seedu.ui.TextUi; import static seedu.storage.Storage.SEPARATOR; -import static seedu.parser.ContactParser.NUMBER_OF_DETAILS; +import static seedu.parser.ContactParser.NUMBER_OF_FIELDS; import java.io.File; import java.io.FileNotFoundException; @@ -30,14 +30,19 @@ public static ContactList readContacts(File contactFile) throws FileErrorExcepti private static void decodeContact(ContactList contactList, String contactText) { String[] destructuredInputs = contactText.split(SEPARATOR); - String[] compiledDetails = new String[NUMBER_OF_DETAILS]; + String[] compiledDetails = new String[NUMBER_OF_FIELDS]; assert destructuredInputs.length > 0; decodeDetails(compiledDetails, destructuredInputs); // Add the decoded details into the contact list try { String contactName = destructuredInputs[DetailType.NAME.getIndex()]; String contactGithub = destructuredInputs[DetailType.GITHUB.getIndex()]; - Contact newContact = new Contact(contactName, contactGithub); + String contactLinkedin = destructuredInputs[DetailType.LINKEDIN.getIndex()]; + String contactTelegram = destructuredInputs[DetailType.TELEGRAM.getIndex()]; + String contactTwitter = destructuredInputs[DetailType.TWITTER.getIndex()]; + String contactEmail = destructuredInputs[DetailType.EMAIL.getIndex()]; + Contact newContact = new Contact(contactName, contactGithub, contactLinkedin, contactTelegram, + contactTwitter, contactEmail); contactList.addContact(newContact); } catch (IndexOutOfBoundsException e) { TextUi.corruptLineMessage(contactText); @@ -48,8 +53,8 @@ private static void decodeDetails(String[] compiledDetails, String[] destructure if (compiledDetails.length != destructuredInputs.length) { return; } - assert compiledDetails.length == NUMBER_OF_DETAILS; - for (int i = 0; i < NUMBER_OF_DETAILS; i++) { + assert compiledDetails.length == NUMBER_OF_FIELDS; + for (int i = 0; i < NUMBER_OF_FIELDS; i++) { compiledDetails[i] = destructuredInputs[i]; } } From 0af3e59b9f33dc2de3a0328471d07aca048aef70 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Mon, 11 Oct 2021 23:14:28 +0800 Subject: [PATCH 149/756] Update encoding of contacts to save data --- src/main/java/seedu/storage/ContactsEncoder.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/storage/ContactsEncoder.java b/src/main/java/seedu/storage/ContactsEncoder.java index 1a6f76e694..d86e5b7a04 100644 --- a/src/main/java/seedu/storage/ContactsEncoder.java +++ b/src/main/java/seedu/storage/ContactsEncoder.java @@ -25,7 +25,9 @@ public static void saveContacts(String contactFilePath, ContactList contactList) } private static String encodeContact(Contact contact) { - String stringifiedContact = contact.getName() + SEPARATOR + contact.getGithub() + "\n"; + String stringifiedContact = contact.getName() + SEPARATOR + contact.getGithub() + SEPARATOR + + contact.getLinkedin() + SEPARATOR + contact.getTelegram() + SEPARATOR + + contact.getTwitter() + SEPARATOR + contact.getEmail() + "\n"; return stringifiedContact; } } From 3085af3991f613c4992b7bca024cd597fd29fd3a Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Mon, 11 Oct 2021 23:14:40 +0800 Subject: [PATCH 150/756] Remove unused forbidden command --- src/main/java/seedu/parser/MainParser.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 939eeed01a..34a1bd827e 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -25,7 +25,6 @@ public class MainParser { private static final String EXIT_COMD = "exit"; private static final String VIEW_COMD = "view"; private static final String LIST_COMD = "list"; - private static final String FORBIDDEN_COMD = "forbidden"; private static final int COMD_WORD_INDEX = 0; private static final int ISOLATE_COMD_WORD = 2; From 9e1a406271f79dfefdf83f169ab57f34a5548af4 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Mon, 11 Oct 2021 23:14:56 +0800 Subject: [PATCH 151/756] Update TextUi to include other flags in error message --- src/main/java/seedu/ui/TextUi.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 297174c5d1..7776913fe6 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -114,7 +114,8 @@ public static void invalidCommandMessage() { public static void invalidFlagMessage() { String message = "There appears to be a flag that is not recognised.\n" - + "Please try again with a valid flag.\n" + " -n NAME\n" + " -g GITHUB"; + + "Please try again with a valid flag.\n" + " -n NAME\n" + " -g GITHUB\n" + " -l LINKEDIN\n" + + " -te TELEGRAM\n" + " -tw TWITTER\n" + " -e EMAIL"; printDoubleLineMessage(message); } @@ -125,7 +126,8 @@ public static void invalidIndexMessage() { public static void missingDetailMessage() { String message = "There are missing details.\n" + "Please remove any flags with no details, \n" - + "and ensure that your flags used are correct:\n" + " -n NAME\n" + " -g GITHUB"; + + "and ensure that your flags used are correct:\n" + " -n NAME\n" + " -g GITHUB\n" + " -l LINKEDIN\n" + + " -te TELEGRAM\n" + " -tw TWITTER\n" + " -e EMAIL"; printDoubleLineMessage(message); } From b06b1af4c20a1e8c32aa66147cf7e95b64ece9c1 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Mon, 11 Oct 2021 23:15:23 +0800 Subject: [PATCH 152/756] Update AddContactParserTest and EditContactParserTest to include new fields --- src/test/java/seedu/parser/AddContactParserTest.java | 4 ++-- src/test/java/seedu/parser/EditContactParserTest.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/java/seedu/parser/AddContactParserTest.java b/src/test/java/seedu/parser/AddContactParserTest.java index 86cc3f22c8..f9440efaff 100644 --- a/src/test/java/seedu/parser/AddContactParserTest.java +++ b/src/test/java/seedu/parser/AddContactParserTest.java @@ -31,9 +31,9 @@ public void setUp() { @Test void parseContactDetails_inputsWithIrregularSpacing_expectCorrectDetails() throws InvalidFlagException, MissingDetailException, MissingArgException, ForbiddenDetailException { - inputUserInput = "add -n andre -g ng-andre "; + inputUserInput = " add -n andre -g ng-andre -l linkedin -tw twit -te tele -e email"; actualOutput = addContactParser.parseContactDetails(inputUserInput); - expectedOutput = new String[]{"andre", "ng-andre"}; + expectedOutput = new String[]{"andre", "ng-andre", "linkedin", "tele", "twit", "email"}; assertArrayEquals(expectedOutput, actualOutput); } diff --git a/src/test/java/seedu/parser/EditContactParserTest.java b/src/test/java/seedu/parser/EditContactParserTest.java index 851fb955a0..79970a3d1c 100644 --- a/src/test/java/seedu/parser/EditContactParserTest.java +++ b/src/test/java/seedu/parser/EditContactParserTest.java @@ -19,7 +19,7 @@ class EditContactParserTest { @Test void parseContactDetails() throws MissingDetailException, MissingArgException, InvalidFlagException, ForbiddenDetailException { - String[] expectedResult = {null, "github"}; + String[] expectedResult = {null, "github", null, null, null, null}; String testInput = "edit 1 -g github"; String[] actualResult = editContactParser.parseContactDetails(testInput); assertArrayEquals(expectedResult, actualResult); From e697c37aff26a3c97291920df914a13cce06c4c7 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Mon, 11 Oct 2021 23:15:40 +0800 Subject: [PATCH 153/756] Update MainParserTest to include new fields to test --- .../java/seedu/parser/MainParserTest.java | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/test/java/seedu/parser/MainParserTest.java b/src/test/java/seedu/parser/MainParserTest.java index b918dca579..25b625f5c0 100644 --- a/src/test/java/seedu/parser/MainParserTest.java +++ b/src/test/java/seedu/parser/MainParserTest.java @@ -103,29 +103,39 @@ public void parseDeleteCommand_outOfRangeIndex_expectFailedCommandType() { @Test public void parseAddCommand_validInputsWithIrregularSpaces_expectAddContactCommand() { - testUserInput = " add -n andre -g ng-andre "; + testUserInput = " add -n andre -g ng-andre -l linkedin -tw twit -te tele -e email"; AddContactCommand actualCommand = getParsedCommand(testUserInput, AddContactCommand.class); - AddContactCommand expectedCommand = new AddContactCommand("andre", "ng-andre"); + AddContactCommand expectedCommand = new AddContactCommand("andre", "ng-andre", "linkedin", "tele", "twit", + "email"); assertEquals(expectedCommand.getName(), actualCommand.getName()); assertEquals(expectedCommand.getGithub(), actualCommand.getGithub()); + assertEquals(expectedCommand.getLinkedin(), actualCommand.getLinkedin()); + assertEquals(expectedCommand.getTelegram(), actualCommand.getTelegram()); + assertEquals(expectedCommand.getTwitter(), actualCommand.getTwitter()); + assertEquals(expectedCommand.getEmail(), actualCommand.getEmail()); } @Test public void parseAddCommand_validInputsWithExtraCharacters_expectAddContactCommand() { testUserInput = " add 1231267azldasd -n marcus -g marcus-bory "; AddContactCommand actualCommand = getParsedCommand(testUserInput, AddContactCommand.class); - AddContactCommand expectedCommand = new AddContactCommand("marcus", "marcus-bory"); + AddContactCommand expectedCommand = new AddContactCommand("marcus", "marcus-bory", null, null, null, null); assertEquals(expectedCommand.getName(), actualCommand.getName()); assertEquals(expectedCommand.getGithub(), actualCommand.getGithub()); } @Test public void parseAddCommand_validInputs_expectAddContactCommand() { - testUserInput = "add -n andre -g ng-andre"; + testUserInput = "add -n andre -g ng-andre -l linkedin -tw twit -te tele -e email"; final AddContactCommand actualCommand = getParsedCommand(testUserInput, AddContactCommand.class); - final AddContactCommand expectedCommand = new AddContactCommand("andre", "ng-andre"); + final AddContactCommand expectedCommand = new AddContactCommand("andre", "ng-andre", "linkedin", "tele", "twit", + "email"); assertEquals(expectedCommand.getName(), actualCommand.getName()); assertEquals(expectedCommand.getGithub(), actualCommand.getGithub()); + assertEquals(expectedCommand.getLinkedin(), actualCommand.getLinkedin()); + assertEquals(expectedCommand.getTelegram(), actualCommand.getTelegram()); + assertEquals(expectedCommand.getTwitter(), actualCommand.getTwitter()); + assertEquals(expectedCommand.getEmail(), actualCommand.getEmail()); } @Test From 66ef9a038a847b506b19cb1a7fb027fa979576ce Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Mon, 11 Oct 2021 23:15:49 +0800 Subject: [PATCH 154/756] Update IO redirection input and outputs --- text-ui-test/ACTUAL.TXT | 42 ++++++++++++++++++++++++++++++++++ text-ui-test/EXPECTED-UNIX.TXT | 42 ++++++++++++++++++++++++++++++++++ text-ui-test/EXPECTED.TXT | 42 ++++++++++++++++++++++++++++++++++ text-ui-test/input.txt | 4 ++++ 4 files changed, 130 insertions(+) diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index ab1543b581..9b91a5873b 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -84,6 +84,10 @@ Please remove any flags with no details, and ensure that your flags used are correct: -n NAME -g GITHUB + -l LINKEDIN + -te TELEGRAM + -tw TWITTER + -e EMAIL ____________________________________________________________ ____________________________________________________________ @@ -134,6 +138,10 @@ Please remove any flags with no details, and ensure that your flags used are correct: -n NAME -g GITHUB + -l LINKEDIN + -te TELEGRAM + -tw TWITTER + -e EMAIL ____________________________________________________________ ____________________________________________________________ @@ -160,6 +168,10 @@ There appears to be a flag that is not recognised. Please try again with a valid flag. -n NAME -g GITHUB + -l LINKEDIN + -te TELEGRAM + -tw TWITTER + -e EMAIL ____________________________________________________________ ____________________________________________________________ @@ -198,6 +210,10 @@ Please remove any flags with no details, and ensure that your flags used are correct: -n NAME -g GITHUB + -l LINKEDIN + -te TELEGRAM + -tw TWITTER + -e EMAIL ____________________________________________________________ ____________________________________________________________ @@ -229,6 +245,32 @@ ____________________________________________________________ ConTech has edited the specified contact: lezongmun ____________________________________________________________ +____________________________________________________________ +ConTech has added the specified contact: name +You now have 7 contact(s). +____________________________________________________________ + +____________________________________________________________ +There appears to be a flag that is not recognised. +Please try again with a valid flag. + -n NAME + -g GITHUB + -l LINKEDIN + -te TELEGRAM + -tw TWITTER + -e EMAIL +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: lezai3 +You now have 8 contact(s). +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: lezongggg +You now have 9 contact(s). +____________________________________________________________ + ____________________________________________________________ ConTech will now shutdown. We hope you have enjoyed using it. diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index ab1543b581..9b91a5873b 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -84,6 +84,10 @@ Please remove any flags with no details, and ensure that your flags used are correct: -n NAME -g GITHUB + -l LINKEDIN + -te TELEGRAM + -tw TWITTER + -e EMAIL ____________________________________________________________ ____________________________________________________________ @@ -134,6 +138,10 @@ Please remove any flags with no details, and ensure that your flags used are correct: -n NAME -g GITHUB + -l LINKEDIN + -te TELEGRAM + -tw TWITTER + -e EMAIL ____________________________________________________________ ____________________________________________________________ @@ -160,6 +168,10 @@ There appears to be a flag that is not recognised. Please try again with a valid flag. -n NAME -g GITHUB + -l LINKEDIN + -te TELEGRAM + -tw TWITTER + -e EMAIL ____________________________________________________________ ____________________________________________________________ @@ -198,6 +210,10 @@ Please remove any flags with no details, and ensure that your flags used are correct: -n NAME -g GITHUB + -l LINKEDIN + -te TELEGRAM + -tw TWITTER + -e EMAIL ____________________________________________________________ ____________________________________________________________ @@ -229,6 +245,32 @@ ____________________________________________________________ ConTech has edited the specified contact: lezongmun ____________________________________________________________ +____________________________________________________________ +ConTech has added the specified contact: name +You now have 7 contact(s). +____________________________________________________________ + +____________________________________________________________ +There appears to be a flag that is not recognised. +Please try again with a valid flag. + -n NAME + -g GITHUB + -l LINKEDIN + -te TELEGRAM + -tw TWITTER + -e EMAIL +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: lezai3 +You now have 8 contact(s). +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: lezongggg +You now have 9 contact(s). +____________________________________________________________ + ____________________________________________________________ ConTech will now shutdown. We hope you have enjoyed using it. diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index ab1543b581..9b91a5873b 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -84,6 +84,10 @@ Please remove any flags with no details, and ensure that your flags used are correct: -n NAME -g GITHUB + -l LINKEDIN + -te TELEGRAM + -tw TWITTER + -e EMAIL ____________________________________________________________ ____________________________________________________________ @@ -134,6 +138,10 @@ Please remove any flags with no details, and ensure that your flags used are correct: -n NAME -g GITHUB + -l LINKEDIN + -te TELEGRAM + -tw TWITTER + -e EMAIL ____________________________________________________________ ____________________________________________________________ @@ -160,6 +168,10 @@ There appears to be a flag that is not recognised. Please try again with a valid flag. -n NAME -g GITHUB + -l LINKEDIN + -te TELEGRAM + -tw TWITTER + -e EMAIL ____________________________________________________________ ____________________________________________________________ @@ -198,6 +210,10 @@ Please remove any flags with no details, and ensure that your flags used are correct: -n NAME -g GITHUB + -l LINKEDIN + -te TELEGRAM + -tw TWITTER + -e EMAIL ____________________________________________________________ ____________________________________________________________ @@ -229,6 +245,32 @@ ____________________________________________________________ ConTech has edited the specified contact: lezongmun ____________________________________________________________ +____________________________________________________________ +ConTech has added the specified contact: name +You now have 7 contact(s). +____________________________________________________________ + +____________________________________________________________ +There appears to be a flag that is not recognised. +Please try again with a valid flag. + -n NAME + -g GITHUB + -l LINKEDIN + -te TELEGRAM + -tw TWITTER + -e EMAIL +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: lezai3 +You now have 8 contact(s). +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: lezongggg +You now have 9 contact(s). +____________________________________________________________ + ____________________________________________________________ ConTech will now shutdown. We hope you have enjoyed using it. diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index 5aca152a2c..cf042f3bab 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -34,4 +34,8 @@ view 0 add -n name -g null add -n dev -g nullptr edit 3 -g new-git +add -n name -l linkedin -g github -e email -tw twitter -te telegram +add -n lezai -g lezongmun -e lezongmun@gmail.com -linkedin lezongmun +add -n lezai3 -g lezongmun -e lezongmun@gmail.com -l lezongmun +add -n lezongggg -te testTelegram exit \ No newline at end of file From 4b5f4c38bd912fb7bdbf3685f1f196d89eed97cb Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 12 Oct 2021 00:12:17 +0800 Subject: [PATCH 155/756] Add switch cases for editContact command --- src/main/java/seedu/contact/ContactList.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/main/java/seedu/contact/ContactList.java b/src/main/java/seedu/contact/ContactList.java index 70db51dde1..c0827c8837 100644 --- a/src/main/java/seedu/contact/ContactList.java +++ b/src/main/java/seedu/contact/ContactList.java @@ -5,6 +5,10 @@ public class ContactList { public static final int NAME_INDEX = 0; public static final int GITHUB_INDEX = 1; + public static final int LINKEDIN_INDEX = 2; + public static final int TELEGRAM_INDEX = 3; + public static final int TWITTER_INDEX = 4; + public static final int EMAIL_INDEX = 5; private ArrayList contacts; @@ -26,6 +30,18 @@ public void editContact(String[] contactDetails, int contactIndex) { case GITHUB_INDEX: contacts.get(contactIndex).setGithub(contactDetails[i]); break; + case LINKEDIN_INDEX: + contacts.get(contactIndex).setLinkedin(contactDetails[i]); + break; + case TELEGRAM_INDEX: + contacts.get(contactIndex).setTelegram(contactDetails[i]); + break; + case TWITTER_INDEX: + contacts.get(contactIndex).setTwitter(contactDetails[i]); + break; + case EMAIL_INDEX:_INDEX: + contacts.get(contactIndex).setEmail(contactDetails[i]); + break; default: System.out.println("Index error has occurred."); break; From c247bbd1b226bb021ec189227a3f7e8b5d730940 Mon Sep 17 00:00:00 2001 From: lezong Date: Tue, 12 Oct 2021 00:26:43 +0800 Subject: [PATCH 156/756] Change getUserInput in TextUi to static --- .../seedu/command/DeleteContactCommand.java | 8 ++++++- src/main/java/seedu/ui/TextUi.java | 23 +++++++++++++++---- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/command/DeleteContactCommand.java b/src/main/java/seedu/command/DeleteContactCommand.java index 1e378b92ba..0a05017ad0 100644 --- a/src/main/java/seedu/command/DeleteContactCommand.java +++ b/src/main/java/seedu/command/DeleteContactCommand.java @@ -7,6 +7,7 @@ public class DeleteContactCommand extends Command { private final int deletedIndex; + private final String confirmMessage = ""; public DeleteContactCommand(int deletedIndex) { this.deletedIndex = deletedIndex; @@ -16,7 +17,7 @@ public int getDeletedIndex() { return deletedIndex; } - public void execute() { + public void deleteContact() { try { Contact deletedContact = contactList.getContactAtIndex(deletedIndex); this.contactList.deleteContact(deletedIndex); @@ -25,4 +26,9 @@ public void execute() { TextUi.numOutOfRangeMessage(contactList.getListSize()); } } + + public void execute() { + deleteContact(); + + } } diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 297174c5d1..b64d26c401 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -12,14 +12,13 @@ public class TextUi { private static final String LINE = "____________________________________________________________\n"; - private final Scanner scanner; + private static final Scanner scanner = new Scanner(System.in); public TextUi() { - scanner = new Scanner(System.in); initMessage(); } - public String getUserInput() { + public static String getUserInput() { String userInput = scanner.nextLine().trim(); if (userInput.contains(",")) { String newUserInput = userInput.replace(",", ""); @@ -29,6 +28,11 @@ public String getUserInput() { return userInput; } + public static String getUserDeleteConfirmation() { + String userDeleteConfirmation = scanner.nextLine().trim(); + return userDeleteConfirmation; + } + // Used for print messages after user inputs private static void printDoubleLineMessage(String message) { System.out.println(LINE + message + "\n" + LINE); @@ -89,6 +93,17 @@ public static void contactsEmptyListMessage() { printDoubleLineMessage(message); } + public static void deleteContactConfirmationMessage(Contact deleteContact, int index) { + String message = "Delete this contact? \n" + + index + ". " + "Name: " + deleteContact.getName() + " GitHub: " + deleteContact.getGithub() + "\n" + + "Enter \"y\" to delete"; + printDoubleLineMessage(message); + } + + public static void cancelDeleteContactMessage() { + String message = "Delete has been cancelled."; + } + public static void deleteContactMessage(String contactName, int listSize) { String message = "ConTech has removed the specified contact: " + contactName + "\n" + "You now have " + listSize + " contact(s)."; @@ -170,7 +185,7 @@ public static void corruptLineMessage(String line) { printBottomLineMessage("Line \"" + line + "\" is corrupted and not loaded."); } - private void forbiddenInputCommaMessage(String newUserInput) { + private static void forbiddenInputCommaMessage(String newUserInput) { String message = "Due to the storage nature of ConTech, we will remove\n" + "commas (\",\"), and attempt to parse it as:\n" + newUserInput; From b63e4ae90f4fa17ebe3e74d097b7c64ad1f293fe Mon Sep 17 00:00:00 2001 From: lezong Date: Tue, 12 Oct 2021 00:34:21 +0800 Subject: [PATCH 157/756] Add confirmation message when deleting contact --- src/main/java/seedu/command/DeleteContactCommand.java | 10 ++++++++-- src/main/java/seedu/ui/TextUi.java | 5 +++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/main/java/seedu/command/DeleteContactCommand.java b/src/main/java/seedu/command/DeleteContactCommand.java index 0a05017ad0..fdbce94353 100644 --- a/src/main/java/seedu/command/DeleteContactCommand.java +++ b/src/main/java/seedu/command/DeleteContactCommand.java @@ -28,7 +28,13 @@ public void deleteContact() { } public void execute() { - deleteContact(); - + Contact deletedContact = contactList.getContactAtIndex(deletedIndex); + TextUi.deleteContactConfirmationMessage(deletedContact, deletedIndex); + String userDeleteConfirmation = TextUi.getUserDeleteConfirmation(); + if (userDeleteConfirmation.equalsIgnoreCase("y")) { + deleteContact(); + } else { + TextUi.cancelDeleteContactMessage(); + } } } diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index b64d26c401..d27f7e13c1 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -95,13 +95,14 @@ public static void contactsEmptyListMessage() { public static void deleteContactConfirmationMessage(Contact deleteContact, int index) { String message = "Delete this contact? \n" - + index + ". " + "Name: " + deleteContact.getName() + " GitHub: " + deleteContact.getGithub() + "\n" - + "Enter \"y\" to delete"; + + " " + index + ". " + "Name: " + deleteContact.getName() + " GitHub: " + deleteContact.getGithub() + + "\nEnter \"y\" to delete."; printDoubleLineMessage(message); } public static void cancelDeleteContactMessage() { String message = "Delete has been cancelled."; + printDoubleLineMessage(message); } public static void deleteContactMessage(String contactName, int listSize) { From 4760a3a1bf64e87efb81f57d41460ed7dcdace4d Mon Sep 17 00:00:00 2001 From: lezong Date: Tue, 12 Oct 2021 11:50:54 +0800 Subject: [PATCH 158/756] Move confirmation message into getUserDeleteConfirmation --- .../java/seedu/command/DeleteContactCommand.java | 4 ++-- src/main/java/seedu/ui/TextUi.java | 14 ++++++-------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/main/java/seedu/command/DeleteContactCommand.java b/src/main/java/seedu/command/DeleteContactCommand.java index fdbce94353..49ce9dd161 100644 --- a/src/main/java/seedu/command/DeleteContactCommand.java +++ b/src/main/java/seedu/command/DeleteContactCommand.java @@ -29,8 +29,8 @@ public void deleteContact() { public void execute() { Contact deletedContact = contactList.getContactAtIndex(deletedIndex); - TextUi.deleteContactConfirmationMessage(deletedContact, deletedIndex); - String userDeleteConfirmation = TextUi.getUserDeleteConfirmation(); + // ask for confirmation to delete from user + String userDeleteConfirmation = TextUi.getUserDeleteConfirmation(deletedContact, deletedIndex); if (userDeleteConfirmation.equalsIgnoreCase("y")) { deleteContact(); } else { diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index cb328261d7..e94a96c355 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -28,7 +28,12 @@ public static String getUserInput() { return userInput; } - public static String getUserDeleteConfirmation() { + public static String getUserDeleteConfirmation(Contact deletedContact, int deletedIndex) { + String message = "Delete this contact? (y/n)\n" + + " " + deletedIndex + ". " + "Name: " + deletedContact.getName() + " GitHub: " + + deletedContact.getGithub(); + printDoubleLineMessage(message); + String userDeleteConfirmation = scanner.nextLine().trim(); return userDeleteConfirmation; } @@ -93,13 +98,6 @@ public static void contactsEmptyListMessage() { printDoubleLineMessage(message); } - public static void deleteContactConfirmationMessage(Contact deleteContact, int index) { - String message = "Delete this contact? \n" - + " " + index + ". " + "Name: " + deleteContact.getName() + " GitHub: " + deleteContact.getGithub() - + "\nEnter \"y\" to delete."; - printDoubleLineMessage(message); - } - public static void cancelDeleteContactMessage() { String message = "Delete has been cancelled."; printDoubleLineMessage(message); From 51a39f55935418ce60b849705885797de9885cd1 Mon Sep 17 00:00:00 2001 From: lezong Date: Tue, 12 Oct 2021 11:56:03 +0800 Subject: [PATCH 159/756] Change input.txt to include delete confirmation --- text-ui-test/input.txt | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index cf042f3bab..e875f47871 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -1,8 +1,12 @@ +rm 1 add -n ng andre -g ng-andre rm 2 view 999aa add -n ashraf -g ashraf -rm 3 +rm 1 +n +rm 1 +o add -n mayank -g mayankp123 rm 9909 add -n bory -g marcus @@ -16,7 +20,9 @@ add -g github list view 3 rm 0 +y rm 0 +y add -p -f view 2 n andre @@ -24,7 +30,10 @@ f facebook n add -p pinterest -f facebook add 1231267azldasd -n lezongmun -g lezong -rm 1 + rm 1 +n + rm 1 +y list view abc view 0 From 37ff8b2ad7f0322c2a1698f5811f766903a21765 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Tue, 12 Oct 2021 12:08:38 +0800 Subject: [PATCH 160/756] Implement new ExceptionTextUi class to hold exception messages --- src/main/java/seedu/ui/ExceptionTextUi.java | 109 ++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 src/main/java/seedu/ui/ExceptionTextUi.java diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java new file mode 100644 index 0000000000..04becf3e3a --- /dev/null +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -0,0 +1,109 @@ +package seedu.ui; + +public class ExceptionTextUi { + private static final String LINE = "____________________________________________________________\n"; + + // Used for print messages after user inputs + private static void printDoubleLineMessage(String message) { + System.out.println(LINE + message + "\n" + LINE); + } + + // Used for system messages without user inputs + private static void printBottomLineMessage(String message) { + System.out.println(message + "\n" + LINE); + } + + private static void printTopLineMessage(String message) { + System.out.println(LINE + "\n" + message); + } + + // Used to print a line after displayed data + public static void printBottomLine() { + System.out.println("\n" + LINE); + } + + // Error Messages + public static void fileErrorMessage(String contactFilePath) { + String message = "ConTech is unfortunately unable to access / create a\n" + " save file at " + contactFilePath + + ".\n" + "Please relocate the file and try again."; + printBottomLineMessage(message); + } + + public static void invalidCommandMessage() { + String message = "ConTech is unable to understand your request.\n" + "Please try again with a valid command."; + printDoubleLineMessage(message); + } + + public static void invalidFlagMessage() { + String message = "There appears to be a flag that is not recognised.\n" + + "Please try again with a valid flag.\n" + " -n NAME\n" + " -g GITHUB\n" + " -l LINKEDIN\n" + + " -te TELEGRAM\n" + " -tw TWITTER\n" + " -e EMAIL"; + printDoubleLineMessage(message); + } + + public static void invalidIndexMessage() { + String message = "Please enter a valid contact index."; + printDoubleLineMessage(message); + } + + public static void missingDetailMessage() { + String message = "There are missing details.\n" + "Please remove any flags with no details, \n" + + "and ensure that your flags used are correct:\n" + " -n NAME\n" + " -g GITHUB\n" + " -l LINKEDIN\n" + + " -te TELEGRAM\n" + " -tw TWITTER\n" + " -e EMAIL"; + printDoubleLineMessage(message); + } + + public static void missingArgMessage() { + String message = "There seems to be missing parameters in your request.\n" + "Please specify your command."; + printDoubleLineMessage(message); + } + + public static void invalidNumMessage() { + String message = "That does not seem to be a number.\n" + "Please provide a number instead."; + printDoubleLineMessage(message); + } + + public static void invalidFormatMessage() { + String message = "ConTech is unable to understand your request.\n" + + "The request has not been formatted correctly. Please try again."; + printDoubleLineMessage(message); + } + + public static void missingNameMessage() { + String message = "There are missing details.\n" + + "Please specify a name when creating a contact with the flag -n"; + printDoubleLineMessage(message); + } + + public static void numOutOfRangeMessage(int listSize) { + String message; + int maxIndex = listSize - 1; + if (listSize == 0) { + message = "There are no contacts stored in ConTech."; + } else if (listSize == 1) { + message = "The number you have input is out of range.\n" + + "You only have 1 contact stored."; + } else { + message = "The number you have input is out of range.\n" + + "Please input a number between 0 and " + maxIndex + "."; + } + printDoubleLineMessage(message); + } + + public static void corruptLineMessage(String line) { + printBottomLineMessage("Line \"" + line + "\" is corrupted and not loaded."); + } + + public static void forbiddenInputCommaMessage(String newUserInput) { + String message = "Due to the storage nature of ConTech, we will remove\n" + + "commas (\",\"), and attempt to parse it as:\n" + + newUserInput; + printTopLineMessage(message); + } + + public static void forbiddenDetailMessage() { + String message = "As one of the details to be stored is \"null\", \n" + + "ConTech is unable to process it"; + printDoubleLineMessage(message); + } +} From 1f19f1ec4502803fdcdd57a921545e8dbaac5261 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Tue, 12 Oct 2021 12:09:11 +0800 Subject: [PATCH 161/756] Removal of exception messages from TextUi class and migrated to ExceptionTextUi class --- src/main/java/seedu/ui/TextUi.java | 87 +----------------------------- 1 file changed, 1 insertion(+), 86 deletions(-) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 7776913fe6..8c8eb3b286 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -11,7 +11,6 @@ public class TextUi { + " \\_____\\___/|_| |_|_|\\___|\\___|_| |_|\n" + " \n"; private static final String LINE = "____________________________________________________________\n"; - private final Scanner scanner; public TextUi() { @@ -23,7 +22,7 @@ public String getUserInput() { String userInput = scanner.nextLine().trim(); if (userInput.contains(",")) { String newUserInput = userInput.replace(",", ""); - forbiddenInputCommaMessage(newUserInput); + ExceptionTextUi.forbiddenInputCommaMessage(newUserInput); return newUserInput; } return userInput; @@ -100,88 +99,4 @@ public static void exitMessage() { printDoubleLineMessage(message); } - // Error Messages - public static void fileErrorMessage(String contactFilePath) { - String message = "ConTech is unfortunately unable to access / create a\n" + " save file at " + contactFilePath - + ".\n" + "Please relocate the file and try again."; - printBottomLineMessage(message); - } - - public static void invalidCommandMessage() { - String message = "ConTech is unable to understand your request.\n" + "Please try again with a valid command."; - printDoubleLineMessage(message); - } - - public static void invalidFlagMessage() { - String message = "There appears to be a flag that is not recognised.\n" - + "Please try again with a valid flag.\n" + " -n NAME\n" + " -g GITHUB\n" + " -l LINKEDIN\n" - + " -te TELEGRAM\n" + " -tw TWITTER\n" + " -e EMAIL"; - printDoubleLineMessage(message); - } - - public static void invalidIndexMessage() { - String message = "Please enter a valid contact index."; - printDoubleLineMessage(message); - } - - public static void missingDetailMessage() { - String message = "There are missing details.\n" + "Please remove any flags with no details, \n" - + "and ensure that your flags used are correct:\n" + " -n NAME\n" + " -g GITHUB\n" + " -l LINKEDIN\n" - + " -te TELEGRAM\n" + " -tw TWITTER\n" + " -e EMAIL"; - printDoubleLineMessage(message); - } - - public static void missingArgMessage() { - String message = "There seems to be missing parameters in your request.\n" + "Please specify your command."; - printDoubleLineMessage(message); - } - - public static void invalidNumMessage() { - String message = "That does not seem to be a number.\n" + "Please provide a number instead."; - printDoubleLineMessage(message); - } - - public static void invalidFormatMessage() { - String message = "ConTech is unable to understand your request.\n" - + "The request has not been formatted correctly. Please try again."; - printDoubleLineMessage(message); - } - - public static void missingNameMessage() { - String message = "There are missing details.\n" - + "Please specify a name when creating a contact with the flag -n"; - printDoubleLineMessage(message); - } - - public static void numOutOfRangeMessage(int listSize) { - String message; - int maxIndex = listSize - 1; - if (listSize == 0) { - message = "There are no contacts stored in ConTech."; - } else if (listSize == 1) { - message = "The number you have input is out of range.\n" - + "You only have 1 contact stored."; - } else { - message = "The number you have input is out of range.\n" - + "Please input a number between 0 and " + maxIndex + "."; - } - printDoubleLineMessage(message); - } - - public static void corruptLineMessage(String line) { - printBottomLineMessage("Line \"" + line + "\" is corrupted and not loaded."); - } - - private void forbiddenInputCommaMessage(String newUserInput) { - String message = "Due to the storage nature of ConTech, we will remove\n" - + "commas (\",\"), and attempt to parse it as:\n" - + newUserInput; - printTopLineMessage(message); - } - - public static void forbiddenDetailMessage() { - String message = "As one of the details to be stored is \"null\", \n" - + "ConTech is unable to process it"; - printDoubleLineMessage(message); - } } From 5c0af02db3276c1289a5a75c223a3e1ed94f2d6d Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Tue, 12 Oct 2021 12:11:18 +0800 Subject: [PATCH 162/756] Update ContactsDecoder to call ExceptionTextUi when catching exceptions --- src/main/java/seedu/storage/ContactsDecoder.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index ed6d096b98..b615e39042 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -4,7 +4,7 @@ import seedu.contact.ContactList; import seedu.contact.DetailType; import seedu.exception.FileErrorException; -import seedu.ui.TextUi; +import seedu.ui.ExceptionTextUi; import static seedu.storage.Storage.SEPARATOR; import static seedu.parser.ContactParser.NUMBER_OF_FIELDS; @@ -45,7 +45,7 @@ private static void decodeContact(ContactList contactList, String contactText) { contactTwitter, contactEmail); contactList.addContact(newContact); } catch (IndexOutOfBoundsException e) { - TextUi.corruptLineMessage(contactText); + ExceptionTextUi.corruptLineMessage(contactText); } } From d552b89d51dd3408c6a81195f101a5dda3bcd2b2 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Tue, 12 Oct 2021 12:11:38 +0800 Subject: [PATCH 163/756] Update Duke to call ExceptionTextUi when catching exceptions --- src/main/java/seedu/duke/Duke.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index ee618e7770..69e393c226 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -7,6 +7,7 @@ import seedu.storage.ContactsEncoder; import seedu.storage.Storage; import seedu.ui.TextUi; +import seedu.ui.ExceptionTextUi; public class Duke { private TextUi textUi; @@ -23,7 +24,7 @@ public Duke(String contactFilePath) { try { this.contactList = storage.loadExistingContacts(); } catch (FileErrorException e) { - TextUi.fileErrorMessage(this.contactFilePath); + ExceptionTextUi.fileErrorMessage(this.contactFilePath); } } @@ -42,7 +43,7 @@ private void runCommandProcedure(Command command) { command.execute(); ContactsEncoder.saveContacts(contactFilePath, contactList); } catch (FileErrorException e) { - TextUi.fileErrorMessage(contactFilePath); + ExceptionTextUi.fileErrorMessage(contactFilePath); } } From 697bcbe0c693131cf7bcc4a1d197b63e385ab538 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Tue, 12 Oct 2021 12:11:52 +0800 Subject: [PATCH 164/756] Update ViewCommand to call ExceptionTextUi when catching exceptions --- src/main/java/seedu/command/ViewCommand.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/command/ViewCommand.java b/src/main/java/seedu/command/ViewCommand.java index 7a391c7c8d..e21766e36c 100644 --- a/src/main/java/seedu/command/ViewCommand.java +++ b/src/main/java/seedu/command/ViewCommand.java @@ -2,6 +2,7 @@ import seedu.contact.Contact; import seedu.ui.TextUi; +import seedu.ui.ExceptionTextUi; public class ViewCommand extends Command { private final int index; @@ -19,7 +20,7 @@ public void execute() { Contact viewingContact = contactList.getContactAtIndex(index); TextUi.viewContactMessage(viewingContact, index); } catch (IndexOutOfBoundsException e) { - TextUi.numOutOfRangeMessage(contactList.getListSize()); + ExceptionTextUi.numOutOfRangeMessage(contactList.getListSize()); } } } From 290001c58fa9e3d6bb03a37dc30a936c7672041a Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Tue, 12 Oct 2021 12:12:13 +0800 Subject: [PATCH 165/756] Update FailedCommand to call ExceptionTextUi when catching exceptions --- .../java/seedu/command/FailedCommand.java | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/main/java/seedu/command/FailedCommand.java b/src/main/java/seedu/command/FailedCommand.java index 4a46a7c58c..525cc452fc 100644 --- a/src/main/java/seedu/command/FailedCommand.java +++ b/src/main/java/seedu/command/FailedCommand.java @@ -2,6 +2,7 @@ import seedu.parser.FailedCommandType; import seedu.ui.TextUi; +import seedu.ui.ExceptionTextUi; public class FailedCommand extends Command { private FailedCommandType type; @@ -17,34 +18,34 @@ public FailedCommandType getType() { public void execute() { switch (type) { case GENERAL: - TextUi.invalidCommandMessage(); + ExceptionTextUi.invalidCommandMessage(); break; case INVALID_FLAG: - TextUi.invalidFlagMessage(); + ExceptionTextUi.invalidFlagMessage(); break; case INVALID_INDEX: - TextUi.invalidIndexMessage(); + ExceptionTextUi.invalidIndexMessage(); break; case MISSING_ARG: - TextUi.missingArgMessage(); + ExceptionTextUi.missingArgMessage(); break; case MISSING_DETAIL: - TextUi.missingDetailMessage(); + ExceptionTextUi.missingDetailMessage(); break; case INVALID_NUM: - TextUi.invalidNumMessage(); + ExceptionTextUi.invalidNumMessage(); break; case INVALID_FORMAT: - TextUi.invalidFormatMessage(); + ExceptionTextUi.invalidFormatMessage(); break; case NUM_OUT_OF_BOUND: - TextUi.numOutOfRangeMessage(contactList.getListSize() - 1); + ExceptionTextUi.numOutOfRangeMessage(contactList.getListSize() - 1); break; case MISSING_NAME: - TextUi.missingNameMessage(); + ExceptionTextUi.missingNameMessage(); break; case FORBIDDEN_DETAIL: - TextUi.forbiddenDetailMessage(); + ExceptionTextUi.forbiddenDetailMessage(); break; default: return; From ed25a62fe8e591d502131d9119ec4e37ce472c77 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Tue, 12 Oct 2021 12:12:29 +0800 Subject: [PATCH 166/756] Update EditContactCommadn to call ExceptionTextUi when catching exceptions --- src/main/java/seedu/command/EditContactCommand.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index ffd7ef2187..d6709b8f0d 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -2,6 +2,7 @@ import seedu.contact.Contact; import seedu.ui.TextUi; +import seedu.ui.ExceptionTextUi; public class EditContactCommand extends Command { String[] contactDetails; @@ -17,7 +18,7 @@ public void execute() { contactList.editContact(contactDetails, contactIndex); TextUi.editContactMessage(contactList.getContactAtIndex(contactIndex).getName()); } catch (IndexOutOfBoundsException e) { - TextUi.invalidIndexMessage(); + ExceptionTextUi.invalidIndexMessage(); } } } From 320fa24fec39dd7b148e4d399386404ff2545c9a Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Tue, 12 Oct 2021 12:12:45 +0800 Subject: [PATCH 167/756] Update DeleteContactCommand to call ExceptionTextUi when catching exceptions --- src/main/java/seedu/command/DeleteContactCommand.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/command/DeleteContactCommand.java b/src/main/java/seedu/command/DeleteContactCommand.java index 1e378b92ba..7467df0aef 100644 --- a/src/main/java/seedu/command/DeleteContactCommand.java +++ b/src/main/java/seedu/command/DeleteContactCommand.java @@ -3,6 +3,7 @@ import seedu.contact.Contact; import seedu.parser.FailedCommandType; import seedu.ui.TextUi; +import seedu.ui.ExceptionTextUi; import seedu.command.FailedCommand; public class DeleteContactCommand extends Command { @@ -22,7 +23,7 @@ public void execute() { this.contactList.deleteContact(deletedIndex); TextUi.deleteContactMessage(deletedContact.getName(), contactList.getListSize()); } catch (IndexOutOfBoundsException e) { - TextUi.numOutOfRangeMessage(contactList.getListSize()); + ExceptionTextUi.numOutOfRangeMessage(contactList.getListSize()); } } } From ae9bd3e9fca5d7b59d38421d609d31bfa60dfb78 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 12 Oct 2021 13:23:32 +0800 Subject: [PATCH 168/756] Replace default case with InvalidFlagException --- src/main/java/seedu/contact/ContactList.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/seedu/contact/ContactList.java b/src/main/java/seedu/contact/ContactList.java index c0827c8837..dbbf59ea9a 100644 --- a/src/main/java/seedu/contact/ContactList.java +++ b/src/main/java/seedu/contact/ContactList.java @@ -1,5 +1,7 @@ package seedu.contact; +import seedu.exception.InvalidFlagException; + import java.util.ArrayList; public class ContactList { @@ -20,7 +22,7 @@ public void addContact(Contact contact) { contacts.add(contact); } - public void editContact(String[] contactDetails, int contactIndex) { + public void editContact(String[] contactDetails, int contactIndex) throws InvalidFlagException { for (int i = 0; i < contactDetails.length; i++) { if (contactDetails[i] != null) { switch (i) { @@ -39,12 +41,11 @@ public void editContact(String[] contactDetails, int contactIndex) { case TWITTER_INDEX: contacts.get(contactIndex).setTwitter(contactDetails[i]); break; - case EMAIL_INDEX:_INDEX: + case EMAIL_INDEX: contacts.get(contactIndex).setEmail(contactDetails[i]); break; default: - System.out.println("Index error has occurred."); - break; + throw new InvalidFlagException(); } } } From 42ff741fe4b3957039773495a3de50776576307d Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 12 Oct 2021 13:24:00 +0800 Subject: [PATCH 169/756] Handle InvalidFlagException in command method --- src/main/java/seedu/command/EditContactCommand.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index d6709b8f0d..0571ddeee3 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -1,6 +1,7 @@ package seedu.command; import seedu.contact.Contact; +import seedu.exception.InvalidFlagException; import seedu.ui.TextUi; import seedu.ui.ExceptionTextUi; @@ -17,7 +18,7 @@ public void execute() { try { contactList.editContact(contactDetails, contactIndex); TextUi.editContactMessage(contactList.getContactAtIndex(contactIndex).getName()); - } catch (IndexOutOfBoundsException e) { + } catch (IndexOutOfBoundsException | InvalidFlagException e) { ExceptionTextUi.invalidIndexMessage(); } } From 306a7aa1829a1a35d99bd3cc8e21f29c022f050f Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 12 Oct 2021 14:22:54 +0800 Subject: [PATCH 170/756] Add assertions for ContactList --- src/main/java/seedu/contact/ContactList.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/seedu/contact/ContactList.java b/src/main/java/seedu/contact/ContactList.java index dbbf59ea9a..1feb35fc5e 100644 --- a/src/main/java/seedu/contact/ContactList.java +++ b/src/main/java/seedu/contact/ContactList.java @@ -45,6 +45,8 @@ public void editContact(String[] contactDetails, int contactIndex) throws Invali contacts.get(contactIndex).setEmail(contactDetails[i]); break; default: + //control should never reach here + assert false; throw new InvalidFlagException(); } } From 5e531a9166c0f5c50b71e934f551163750c121c1 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 12 Oct 2021 14:23:18 +0800 Subject: [PATCH 171/756] Add assertions for EditContactParser --- src/main/java/seedu/parser/EditContactParser.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/seedu/parser/EditContactParser.java b/src/main/java/seedu/parser/EditContactParser.java index 17297bdbad..10765178ab 100644 --- a/src/main/java/seedu/parser/EditContactParser.java +++ b/src/main/java/seedu/parser/EditContactParser.java @@ -30,6 +30,7 @@ public int getIndex(String input) throws MissingArgException { //if arguments are missing e.g. edit 2 throw new MissingArgException(); } + assert (destructuredInputs.length == NUMBER_OF_EDIT_ARGS); return Integer.parseInt(destructuredInputs[EDIT_USER_INDEX]); } } From 7856f8afcd448511a9f39943d4133ac3f5b8b522 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 12 Oct 2021 14:23:35 +0800 Subject: [PATCH 172/756] Handle input with missing params --- src/main/java/seedu/parser/EditContactParser.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/seedu/parser/EditContactParser.java b/src/main/java/seedu/parser/EditContactParser.java index 10765178ab..e13f865bd2 100644 --- a/src/main/java/seedu/parser/EditContactParser.java +++ b/src/main/java/seedu/parser/EditContactParser.java @@ -15,9 +15,15 @@ public String[] parseContactDetails(String userInput) //if arguments are missing e.g. edit 2 throw new MissingArgException(); } + assert (inputDetails.length == NUMBER_OF_EDIT_ARGS); String[] contactDetails = new String[NUMBER_OF_FIELDS]; //initialise null array of strings //buffer is used to ensure first flag can be read String[] destructuredInputs = (BUFFER + inputDetails[USER_INFO_INDEX]).split(DETAIL_SEPARATOR); + //handles illegal input "edit 0 -" and "edit 0 [invalid string]" + //valid input will take the form of [, -flag input] so min length should be 2 + if (destructuredInputs.length < 2) { + throw new MissingArgException(); + } for (int i = CONTACT_PARAMS_START_INDEX; i < destructuredInputs.length; i++) { parseDetail(contactDetails, destructuredInputs[i]); } From 727758923e3a523f5b9c6d0e58368d887d7c8cbd Mon Sep 17 00:00:00 2001 From: lezong Date: Tue, 12 Oct 2021 14:58:16 +0800 Subject: [PATCH 173/756] abstracted parsing of index into IndexParser for DeleteContactCommand and parseDeleteContact method --- .../seedu/command/DeleteContactCommand.java | 20 +- src/main/java/seedu/parser/ContactParser.java | 2 + src/main/java/seedu/parser/IndexParser.java | 24 ++ src/main/java/seedu/parser/MainParser.java | 9 +- text-ui-test/ACTUAL.TXT | 45 ++- text-ui-test/EXPECTED-UNIX.TXT | 259 ------------------ text-ui-test/EXPECTED.TXT | 55 +++- 7 files changed, 136 insertions(+), 278 deletions(-) create mode 100644 src/main/java/seedu/parser/IndexParser.java diff --git a/src/main/java/seedu/command/DeleteContactCommand.java b/src/main/java/seedu/command/DeleteContactCommand.java index 49ce9dd161..f93cc60afa 100644 --- a/src/main/java/seedu/command/DeleteContactCommand.java +++ b/src/main/java/seedu/command/DeleteContactCommand.java @@ -2,6 +2,7 @@ import seedu.contact.Contact; import seedu.parser.FailedCommandType; +import seedu.parser.IndexParser; import seedu.ui.TextUi; import seedu.command.FailedCommand; @@ -17,7 +18,7 @@ public int getDeletedIndex() { return deletedIndex; } - public void deleteContact() { + public void checkContactIndex() { try { Contact deletedContact = contactList.getContactAtIndex(deletedIndex); this.contactList.deleteContact(deletedIndex); @@ -27,14 +28,25 @@ public void deleteContact() { } } - public void execute() { - Contact deletedContact = contactList.getContactAtIndex(deletedIndex); + private void deleteOnConfirmation(Contact deletedContact) { // ask for confirmation to delete from user String userDeleteConfirmation = TextUi.getUserDeleteConfirmation(deletedContact, deletedIndex); if (userDeleteConfirmation.equalsIgnoreCase("y")) { - deleteContact(); + this.contactList.deleteContact(deletedIndex); + TextUi.deleteContactMessage(deletedContact.getName(), contactList.getListSize()); } else { TextUi.cancelDeleteContactMessage(); } } + + public void execute() { + try { + // throws IndexOutOfBoundsException if index is outside of the range + Contact deletedContact = IndexParser.getContactFromIndex(deletedIndex, contactList); + // Index is within range, insert assert here + deleteOnConfirmation(deletedContact); + } catch (IndexOutOfBoundsException e) { + TextUi.numOutOfRangeMessage(contactList.getListSize()); + } + } } diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index 8ec4bcf5dd..35d9abc01d 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -57,6 +57,8 @@ public void parseDetail(String[] contactDetails, String detail) contactDetails[indexToStore] = detailToStore; } + + private int getIndexToStore(String flag) throws InvalidFlagException { int indexToStore; switch (flag) { diff --git a/src/main/java/seedu/parser/IndexParser.java b/src/main/java/seedu/parser/IndexParser.java new file mode 100644 index 0000000000..16707da11c --- /dev/null +++ b/src/main/java/seedu/parser/IndexParser.java @@ -0,0 +1,24 @@ +package seedu.parser; + +import seedu.contact.Contact; +import seedu.contact.ContactList; +import seedu.exception.MissingArgException; + + +public class IndexParser { + private static final int ISOLATE_COMD_WORD = 2; + + public static int getIndexFromInput(String userInput) throws NumberFormatException, MissingArgException { + String[] destructuredInputs = userInput.split(" ", ISOLATE_COMD_WORD); + if (destructuredInputs.length == 1) { + throw new MissingArgException(); + } + int index = Integer.parseInt(destructuredInputs[1].trim()); + return index; + } + + public static Contact getContactFromIndex(int index, ContactList contactList) throws IndexOutOfBoundsException { + Contact contact = contactList.getContactAtIndex(index); + return contact; + } +} diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 34a1bd827e..cb8e65c005 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -129,14 +129,11 @@ private Command parseViewContact(String userInput) { } private Command parseDeleteContact(String userInput) { - String[] destructuredInputs = userInput.split(" ", ISOLATE_COMD_WORD); - //check if there is only the command word and no arguments in input - if (destructuredInputs.length == 1) { - return new FailedCommand(FailedCommandType.MISSING_ARG); - } try { - int deletedIndex = Integer.parseInt(destructuredInputs[1].trim()); + int deletedIndex = IndexParser.getIndexFromInput(userInput); return new DeleteContactCommand(deletedIndex); + } catch (MissingArgException e) { + return new FailedCommand(FailedCommandType.MISSING_ARG); } catch (NumberFormatException e) { return new FailedCommand(FailedCommandType.INVALID_INDEX); } diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index 9b91a5873b..269110668d 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -17,6 +17,10 @@ As ConTech is unable to find your saved data, data/contacts.txt ____________________________________________________________ +____________________________________________________________ +There are no contacts stored in ConTech. +____________________________________________________________ + ____________________________________________________________ ConTech has added the specified contact: ng andre You now have 1 contact(s). @@ -37,8 +41,21 @@ You now have 2 contact(s). ____________________________________________________________ ____________________________________________________________ -The number you have input is out of range. -Please input a number between 0 and 1. +Delete this contact? (y/n) + 1. Name: ashraf GitHub: ashraf +____________________________________________________________ + +____________________________________________________________ +Delete has been cancelled. +____________________________________________________________ + +____________________________________________________________ +Delete this contact? (y/n) + 1. Name: ashraf GitHub: ashraf +____________________________________________________________ + +____________________________________________________________ +Delete has been cancelled. ____________________________________________________________ ____________________________________________________________ @@ -122,11 +139,21 @@ ____________________________________________________________ 3. Name: bory GitHub: marcus ____________________________________________________________ +____________________________________________________________ +Delete this contact? (y/n) + 0. Name: ng andre GitHub: ng-andre +____________________________________________________________ + ____________________________________________________________ ConTech has removed the specified contact: ng andre You now have 5 contact(s). ____________________________________________________________ +____________________________________________________________ +Delete this contact? (y/n) + 0. Name: ashraf GitHub: ashraf +____________________________________________________________ + ____________________________________________________________ ConTech has removed the specified contact: ashraf You now have 4 contact(s). @@ -179,6 +206,20 @@ ConTech has added the specified contact: lezongmun You now have 5 contact(s). ____________________________________________________________ +____________________________________________________________ +Delete this contact? (y/n) + 1. Name: bory GitHub: marcus +____________________________________________________________ + +____________________________________________________________ +Delete has been cancelled. +____________________________________________________________ + +____________________________________________________________ +Delete this contact? (y/n) + 1. Name: bory GitHub: marcus +____________________________________________________________ + ____________________________________________________________ ConTech has removed the specified contact: bory You now have 4 contact(s). diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index 9b91a5873b..6edcd0a28b 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -17,262 +17,3 @@ As ConTech is unable to find your saved data, data/contacts.txt ____________________________________________________________ -____________________________________________________________ -ConTech has added the specified contact: ng andre -You now have 1 contact(s). -____________________________________________________________ - -____________________________________________________________ -The number you have input is out of range. -You only have 1 contact stored. -____________________________________________________________ - -____________________________________________________________ -Please enter a valid contact index. -____________________________________________________________ - -____________________________________________________________ -ConTech has added the specified contact: ashraf -You now have 2 contact(s). -____________________________________________________________ - -____________________________________________________________ -The number you have input is out of range. -Please input a number between 0 and 1. -____________________________________________________________ - -____________________________________________________________ -ConTech has added the specified contact: mayank -You now have 3 contact(s). -____________________________________________________________ - -____________________________________________________________ -The number you have input is out of range. -Please input a number between 0 and 2. -____________________________________________________________ - -____________________________________________________________ -ConTech has added the specified contact: bory -You now have 4 contact(s). -____________________________________________________________ - -____________________________________________________________ -ConTech has added the specified contact: andre -You now have 5 contact(s). -____________________________________________________________ - -____________________________________________________________ -ConTech has 5 contacts stored. -Here's the list : -____________________________________________________________ - -0. ng andre -1. ashraf -2. mayank -3. bory -4. andre - -____________________________________________________________ - -____________________________________________________________ -1. Name: ashraf GitHub: ashraf -____________________________________________________________ - -____________________________________________________________ -There are missing details. -Please remove any flags with no details, -and ensure that your flags used are correct: - -n NAME - -g GITHUB - -l LINKEDIN - -te TELEGRAM - -tw TWITTER - -e EMAIL -____________________________________________________________ - -____________________________________________________________ -Please enter a valid contact index. -____________________________________________________________ - -____________________________________________________________ -ConTech has added the specified contact: lezong -You now have 6 contact(s). -____________________________________________________________ - -____________________________________________________________ -There are missing details. -Please specify a name when creating a contact with the flag -n -____________________________________________________________ - -____________________________________________________________ -ConTech has 6 contacts stored. -Here's the list : -____________________________________________________________ - -0. ng andre -1. ashraf -2. mayank -3. bory -4. andre -5. lezong - -____________________________________________________________ - -____________________________________________________________ -3. Name: bory GitHub: marcus -____________________________________________________________ - -____________________________________________________________ -ConTech has removed the specified contact: ng andre -You now have 5 contact(s). -____________________________________________________________ - -____________________________________________________________ -ConTech has removed the specified contact: ashraf -You now have 4 contact(s). -____________________________________________________________ - -____________________________________________________________ -There are missing details. -Please remove any flags with no details, -and ensure that your flags used are correct: - -n NAME - -g GITHUB - -l LINKEDIN - -te TELEGRAM - -tw TWITTER - -e EMAIL -____________________________________________________________ - -____________________________________________________________ -2. Name: andre GitHub: ng-andre -____________________________________________________________ - -____________________________________________________________ -ConTech is unable to understand your request. -Please try again with a valid command. -____________________________________________________________ - -____________________________________________________________ -ConTech is unable to understand your request. -Please try again with a valid command. -____________________________________________________________ - -____________________________________________________________ -ConTech is unable to understand your request. -Please try again with a valid command. -____________________________________________________________ - -____________________________________________________________ -There appears to be a flag that is not recognised. -Please try again with a valid flag. - -n NAME - -g GITHUB - -l LINKEDIN - -te TELEGRAM - -tw TWITTER - -e EMAIL -____________________________________________________________ - -____________________________________________________________ -ConTech has added the specified contact: lezongmun -You now have 5 contact(s). -____________________________________________________________ - -____________________________________________________________ -ConTech has removed the specified contact: bory -You now have 4 contact(s). -____________________________________________________________ - -____________________________________________________________ -ConTech has 4 contacts stored. -Here's the list : -____________________________________________________________ - -0. mayank -1. andre -2. lezong -3. lezongmun - -____________________________________________________________ - -____________________________________________________________ -Please enter a valid contact index. -____________________________________________________________ - -____________________________________________________________ -0. Name: mayank GitHub: mayankp123 -____________________________________________________________ - -____________________________________________________________ -There are missing details. -Please remove any flags with no details, -and ensure that your flags used are correct: - -n NAME - -g GITHUB - -l LINKEDIN - -te TELEGRAM - -tw TWITTER - -e EMAIL -____________________________________________________________ - -____________________________________________________________ - -Due to the storage nature of ConTech, we will remove -commas (","), and attempt to parse it as: -add -n lezong mun -g lezaimun -____________________________________________________________ -ConTech has added the specified contact: lezong mun -You now have 5 contact(s). -____________________________________________________________ - -____________________________________________________________ -As one of the details to be stored is "null", -ConTech is unable to process it -____________________________________________________________ - -____________________________________________________________ -As one of the details to be stored is "null", -ConTech is unable to process it -____________________________________________________________ - -____________________________________________________________ -ConTech has added the specified contact: dev -You now have 6 contact(s). -____________________________________________________________ - -____________________________________________________________ -ConTech has edited the specified contact: lezongmun -____________________________________________________________ - -____________________________________________________________ -ConTech has added the specified contact: name -You now have 7 contact(s). -____________________________________________________________ - -____________________________________________________________ -There appears to be a flag that is not recognised. -Please try again with a valid flag. - -n NAME - -g GITHUB - -l LINKEDIN - -te TELEGRAM - -tw TWITTER - -e EMAIL -____________________________________________________________ - -____________________________________________________________ -ConTech has added the specified contact: lezai3 -You now have 8 contact(s). -____________________________________________________________ - -____________________________________________________________ -ConTech has added the specified contact: lezongggg -You now have 9 contact(s). -____________________________________________________________ - -____________________________________________________________ -ConTech will now shutdown. -We hope you have enjoyed using it. -____________________________________________________________ - diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 9b91a5873b..f0d19ee2dd 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -17,6 +17,10 @@ As ConTech is unable to find your saved data, data/contacts.txt ____________________________________________________________ +____________________________________________________________ +There are no contacts stored in ConTech. +____________________________________________________________ + ____________________________________________________________ ConTech has added the specified contact: ng andre You now have 1 contact(s). @@ -37,8 +41,21 @@ You now have 2 contact(s). ____________________________________________________________ ____________________________________________________________ -The number you have input is out of range. -Please input a number between 0 and 1. +Delete this contact? (y/n) + 1. Name: ashraf GitHub: ashraf +____________________________________________________________ + +____________________________________________________________ +Delete has been cancelled. +____________________________________________________________ + +____________________________________________________________ +Delete this contact? (y/n) + 1. Name: ashraf GitHub: ashraf +____________________________________________________________ + +____________________________________________________________ +Delete has been cancelled. ____________________________________________________________ ____________________________________________________________ @@ -80,7 +97,7 @@ ____________________________________________________________ ____________________________________________________________ There are missing details. -Please remove any flags with no details, +Please remove any flags with no details, and ensure that your flags used are correct: -n NAME -g GITHUB @@ -122,11 +139,21 @@ ____________________________________________________________ 3. Name: bory GitHub: marcus ____________________________________________________________ +____________________________________________________________ +Delete this contact? (y/n) + 0. Name: ng andre GitHub: ng-andre +____________________________________________________________ + ____________________________________________________________ ConTech has removed the specified contact: ng andre You now have 5 contact(s). ____________________________________________________________ +____________________________________________________________ +Delete this contact? (y/n) + 0. Name: ashraf GitHub: ashraf +____________________________________________________________ + ____________________________________________________________ ConTech has removed the specified contact: ashraf You now have 4 contact(s). @@ -134,7 +161,7 @@ ____________________________________________________________ ____________________________________________________________ There are missing details. -Please remove any flags with no details, +Please remove any flags with no details, and ensure that your flags used are correct: -n NAME -g GITHUB @@ -179,6 +206,20 @@ ConTech has added the specified contact: lezongmun You now have 5 contact(s). ____________________________________________________________ +____________________________________________________________ +Delete this contact? (y/n) + 1. Name: bory GitHub: marcus +____________________________________________________________ + +____________________________________________________________ +Delete has been cancelled. +____________________________________________________________ + +____________________________________________________________ +Delete this contact? (y/n) + 1. Name: bory GitHub: marcus +____________________________________________________________ + ____________________________________________________________ ConTech has removed the specified contact: bory You now have 4 contact(s). @@ -206,7 +247,7 @@ ____________________________________________________________ ____________________________________________________________ There are missing details. -Please remove any flags with no details, +Please remove any flags with no details, and ensure that your flags used are correct: -n NAME -g GITHUB @@ -227,12 +268,12 @@ You now have 5 contact(s). ____________________________________________________________ ____________________________________________________________ -As one of the details to be stored is "null", +As one of the details to be stored is "null", ConTech is unable to process it ____________________________________________________________ ____________________________________________________________ -As one of the details to be stored is "null", +As one of the details to be stored is "null", ConTech is unable to process it ____________________________________________________________ From e12bdbbda51749803ca4c4937d4f57d002b3d140 Mon Sep 17 00:00:00 2001 From: lezong Date: Tue, 12 Oct 2021 15:29:32 +0800 Subject: [PATCH 174/756] Change input.txt --- src/main/java/seedu/command/DeleteContactCommand.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/main/java/seedu/command/DeleteContactCommand.java b/src/main/java/seedu/command/DeleteContactCommand.java index f93cc60afa..9e2c7e9884 100644 --- a/src/main/java/seedu/command/DeleteContactCommand.java +++ b/src/main/java/seedu/command/DeleteContactCommand.java @@ -18,16 +18,6 @@ public int getDeletedIndex() { return deletedIndex; } - public void checkContactIndex() { - try { - Contact deletedContact = contactList.getContactAtIndex(deletedIndex); - this.contactList.deleteContact(deletedIndex); - TextUi.deleteContactMessage(deletedContact.getName(), contactList.getListSize()); - } catch (IndexOutOfBoundsException e) { - TextUi.numOutOfRangeMessage(contactList.getListSize()); - } - } - private void deleteOnConfirmation(Contact deletedContact) { // ask for confirmation to delete from user String userDeleteConfirmation = TextUi.getUserDeleteConfirmation(deletedContact, deletedIndex); From 1e4cb62243155aa646d7364a31f0fa409f1a79f2 Mon Sep 17 00:00:00 2001 From: lezong Date: Tue, 12 Oct 2021 17:21:51 +0800 Subject: [PATCH 175/756] Refactor index parsing from edit command to ParseIndex --- src/main/java/seedu/parser/IndexParser.java | 16 +++++++++++----- src/main/java/seedu/parser/MainParser.java | 4 ++-- .../java/seedu/parser/EditContactParserTest.java | 7 ------- src/test/java/seedu/parser/MainParserTest.java | 15 ++++++++------- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/main/java/seedu/parser/IndexParser.java b/src/main/java/seedu/parser/IndexParser.java index 16707da11c..13f018ebbc 100644 --- a/src/main/java/seedu/parser/IndexParser.java +++ b/src/main/java/seedu/parser/IndexParser.java @@ -6,14 +6,20 @@ public class IndexParser { - private static final int ISOLATE_COMD_WORD = 2; + private static final int COMD_WORD_LENGTH = 1; + private static final int INDEX_POSITION = 1; - public static int getIndexFromInput(String userInput) throws NumberFormatException, MissingArgException { - String[] destructuredInputs = userInput.split(" ", ISOLATE_COMD_WORD); - if (destructuredInputs.length == 1) { + + public static int getIndexFromInput(String userInput, String command) + throws NumberFormatException, MissingArgException { + String inputWithoutDetails = userInput; + + String[] destructuredInputs = inputWithoutDetails.split(" "); + if (destructuredInputs.length == COMD_WORD_LENGTH) { throw new MissingArgException(); } - int index = Integer.parseInt(destructuredInputs[1].trim()); + // throws NumberFormatExcept if not integer + int index = Integer.parseInt(destructuredInputs[INDEX_POSITION].trim()); return index; } diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index cb8e65c005..c2be575e24 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -99,9 +99,9 @@ private Command parseAddContact(String userInput) { private Command parseEditContact(String userInput) { // userInput is raw user input contactParser = editContactParser; try { - int userIndex = editContactParser.getIndex(userInput); //throws MissingArgException String[] details = editContactParser.parseContactDetails(userInput); //throws InvalidFlagException, MissingDetailException, MissingArgException + int userIndex = IndexParser.getIndexFromInput(userInput, EDIT_CONTACT_COMD); //throws MissingArgException return new EditContactCommand(details, userIndex); } catch (InvalidFlagException e) { return new FailedCommand(FailedCommandType.INVALID_FLAG); @@ -130,7 +130,7 @@ private Command parseViewContact(String userInput) { private Command parseDeleteContact(String userInput) { try { - int deletedIndex = IndexParser.getIndexFromInput(userInput); + int deletedIndex = IndexParser.getIndexFromInput(userInput, DELETE_CONTACT_COMD); return new DeleteContactCommand(deletedIndex); } catch (MissingArgException e) { return new FailedCommand(FailedCommandType.MISSING_ARG); diff --git a/src/test/java/seedu/parser/EditContactParserTest.java b/src/test/java/seedu/parser/EditContactParserTest.java index 79970a3d1c..f698ccf3ac 100644 --- a/src/test/java/seedu/parser/EditContactParserTest.java +++ b/src/test/java/seedu/parser/EditContactParserTest.java @@ -25,11 +25,4 @@ void parseContactDetails() throws MissingDetailException, assertArrayEquals(expectedResult, actualResult); } - @Test - void getIndex() throws MissingArgException { - int expectedResult = 3; - String testInput = "edit 3 "; - int actualResult = editContactParser.getIndex(testInput); - assertEquals(expectedResult, actualResult); - } } diff --git a/src/test/java/seedu/parser/MainParserTest.java b/src/test/java/seedu/parser/MainParserTest.java index 25b625f5c0..a3e0b0c71d 100644 --- a/src/test/java/seedu/parser/MainParserTest.java +++ b/src/test/java/seedu/parser/MainParserTest.java @@ -51,6 +51,14 @@ public void parseDeleteCommand_validIndex_expectDeleteContactIndexMatch() { assertEquals(testIndex, testResultCommand.getDeletedIndex()); } + @Test + public void parseDeleteCommand_multipleIndexes_expectDeleteContactIndexMatch() { + testUserInput = "rm 1 2"; + testUserInput = "rm " + testIndex; + final DeleteContactCommand testResultCommand = getParsedCommand(testUserInput, DeleteContactCommand.class); + assertEquals(testIndex, testResultCommand.getDeletedIndex()); + } + @Test public void parseDeleteCommand_validIndexWithSpaces_expectDeleteContactIndexMatch() { testIndex = 1; @@ -75,13 +83,6 @@ public void parseDeleteCommand_invalidNumber_expectFailedCommandType() { assertEquals(expectedFailedCommandType, actualFailedCommand.getType()); } - @Test - public void parseDeleteCommand_invalidIndexFormatting_expectFailedCommandType() { - testUserInput = "rm 1 2"; - FailedCommandType expectedFailedCommandType = FailedCommandType.INVALID_INDEX; - final FailedCommand actualFailedCommand = getParsedCommand(testUserInput, FailedCommand.class); - assertEquals(expectedFailedCommandType, actualFailedCommand.getType()); - } @Test public void parseDeleteCommand_outOfRangeIndex_expectFailedCommandType() { From 26c4ba47e9513c35af9c4b004abcf014b9589c65 Mon Sep 17 00:00:00 2001 From: lezong Date: Tue, 12 Oct 2021 17:32:08 +0800 Subject: [PATCH 176/756] Fix delete command for corner cases --- src/main/java/seedu/parser/IndexParser.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/parser/IndexParser.java b/src/main/java/seedu/parser/IndexParser.java index 13f018ebbc..bc4aa90a2f 100644 --- a/src/main/java/seedu/parser/IndexParser.java +++ b/src/main/java/seedu/parser/IndexParser.java @@ -8,18 +8,19 @@ public class IndexParser { private static final int COMD_WORD_LENGTH = 1; private static final int INDEX_POSITION = 1; + private static final int SIGNIFICANT_INDEX_POSITION = 0; + private static final int COMD_INDEX_LENGTH = 2; public static int getIndexFromInput(String userInput, String command) throws NumberFormatException, MissingArgException { - String inputWithoutDetails = userInput; - - String[] destructuredInputs = inputWithoutDetails.split(" "); - if (destructuredInputs.length == COMD_WORD_LENGTH) { + String[] comdIndexSplit = userInput.split(" ", COMD_INDEX_LENGTH); + if (comdIndexSplit.length == COMD_WORD_LENGTH) { throw new MissingArgException(); } + String[] indexSplit = comdIndexSplit[INDEX_POSITION].trim().split(" "); // throws NumberFormatExcept if not integer - int index = Integer.parseInt(destructuredInputs[INDEX_POSITION].trim()); + int index = Integer.parseInt(indexSplit[SIGNIFICANT_INDEX_POSITION].trim()); return index; } From 2c59abf974bde0828ef6938140ef54e45e00dc78 Mon Sep 17 00:00:00 2001 From: lezong Date: Tue, 12 Oct 2021 17:39:22 +0800 Subject: [PATCH 177/756] Update input.txt --- .../seedu/command/DeleteContactCommand.java | 1 - text-ui-test/EXPECTED-UNIX.TXT | 300 ++++++++++++++++++ text-ui-test/EXPECTED.TXT | 10 +- 3 files changed, 305 insertions(+), 6 deletions(-) diff --git a/src/main/java/seedu/command/DeleteContactCommand.java b/src/main/java/seedu/command/DeleteContactCommand.java index 46773bfedc..ff35ccde59 100644 --- a/src/main/java/seedu/command/DeleteContactCommand.java +++ b/src/main/java/seedu/command/DeleteContactCommand.java @@ -34,7 +34,6 @@ public void execute() { try { // throws IndexOutOfBoundsException if index is outside of the range Contact deletedContact = IndexParser.getContactFromIndex(deletedIndex, contactList); - // Index is within range, insert assert here deleteOnConfirmation(deletedContact); } catch (IndexOutOfBoundsException e) { ExceptionTextUi.numOutOfRangeMessage(contactList.getListSize()); diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index 6edcd0a28b..269110668d 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -17,3 +17,303 @@ As ConTech is unable to find your saved data, data/contacts.txt ____________________________________________________________ +____________________________________________________________ +There are no contacts stored in ConTech. +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: ng andre +You now have 1 contact(s). +____________________________________________________________ + +____________________________________________________________ +The number you have input is out of range. +You only have 1 contact stored. +____________________________________________________________ + +____________________________________________________________ +Please enter a valid contact index. +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: ashraf +You now have 2 contact(s). +____________________________________________________________ + +____________________________________________________________ +Delete this contact? (y/n) + 1. Name: ashraf GitHub: ashraf +____________________________________________________________ + +____________________________________________________________ +Delete has been cancelled. +____________________________________________________________ + +____________________________________________________________ +Delete this contact? (y/n) + 1. Name: ashraf GitHub: ashraf +____________________________________________________________ + +____________________________________________________________ +Delete has been cancelled. +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: mayank +You now have 3 contact(s). +____________________________________________________________ + +____________________________________________________________ +The number you have input is out of range. +Please input a number between 0 and 2. +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: bory +You now have 4 contact(s). +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: andre +You now have 5 contact(s). +____________________________________________________________ + +____________________________________________________________ +ConTech has 5 contacts stored. +Here's the list : +____________________________________________________________ + +0. ng andre +1. ashraf +2. mayank +3. bory +4. andre + +____________________________________________________________ + +____________________________________________________________ +1. Name: ashraf GitHub: ashraf +____________________________________________________________ + +____________________________________________________________ +There are missing details. +Please remove any flags with no details, +and ensure that your flags used are correct: + -n NAME + -g GITHUB + -l LINKEDIN + -te TELEGRAM + -tw TWITTER + -e EMAIL +____________________________________________________________ + +____________________________________________________________ +Please enter a valid contact index. +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: lezong +You now have 6 contact(s). +____________________________________________________________ + +____________________________________________________________ +There are missing details. +Please specify a name when creating a contact with the flag -n +____________________________________________________________ + +____________________________________________________________ +ConTech has 6 contacts stored. +Here's the list : +____________________________________________________________ + +0. ng andre +1. ashraf +2. mayank +3. bory +4. andre +5. lezong + +____________________________________________________________ + +____________________________________________________________ +3. Name: bory GitHub: marcus +____________________________________________________________ + +____________________________________________________________ +Delete this contact? (y/n) + 0. Name: ng andre GitHub: ng-andre +____________________________________________________________ + +____________________________________________________________ +ConTech has removed the specified contact: ng andre +You now have 5 contact(s). +____________________________________________________________ + +____________________________________________________________ +Delete this contact? (y/n) + 0. Name: ashraf GitHub: ashraf +____________________________________________________________ + +____________________________________________________________ +ConTech has removed the specified contact: ashraf +You now have 4 contact(s). +____________________________________________________________ + +____________________________________________________________ +There are missing details. +Please remove any flags with no details, +and ensure that your flags used are correct: + -n NAME + -g GITHUB + -l LINKEDIN + -te TELEGRAM + -tw TWITTER + -e EMAIL +____________________________________________________________ + +____________________________________________________________ +2. Name: andre GitHub: ng-andre +____________________________________________________________ + +____________________________________________________________ +ConTech is unable to understand your request. +Please try again with a valid command. +____________________________________________________________ + +____________________________________________________________ +ConTech is unable to understand your request. +Please try again with a valid command. +____________________________________________________________ + +____________________________________________________________ +ConTech is unable to understand your request. +Please try again with a valid command. +____________________________________________________________ + +____________________________________________________________ +There appears to be a flag that is not recognised. +Please try again with a valid flag. + -n NAME + -g GITHUB + -l LINKEDIN + -te TELEGRAM + -tw TWITTER + -e EMAIL +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: lezongmun +You now have 5 contact(s). +____________________________________________________________ + +____________________________________________________________ +Delete this contact? (y/n) + 1. Name: bory GitHub: marcus +____________________________________________________________ + +____________________________________________________________ +Delete has been cancelled. +____________________________________________________________ + +____________________________________________________________ +Delete this contact? (y/n) + 1. Name: bory GitHub: marcus +____________________________________________________________ + +____________________________________________________________ +ConTech has removed the specified contact: bory +You now have 4 contact(s). +____________________________________________________________ + +____________________________________________________________ +ConTech has 4 contacts stored. +Here's the list : +____________________________________________________________ + +0. mayank +1. andre +2. lezong +3. lezongmun + +____________________________________________________________ + +____________________________________________________________ +Please enter a valid contact index. +____________________________________________________________ + +____________________________________________________________ +0. Name: mayank GitHub: mayankp123 +____________________________________________________________ + +____________________________________________________________ +There are missing details. +Please remove any flags with no details, +and ensure that your flags used are correct: + -n NAME + -g GITHUB + -l LINKEDIN + -te TELEGRAM + -tw TWITTER + -e EMAIL +____________________________________________________________ + +____________________________________________________________ + +Due to the storage nature of ConTech, we will remove +commas (","), and attempt to parse it as: +add -n lezong mun -g lezaimun +____________________________________________________________ +ConTech has added the specified contact: lezong mun +You now have 5 contact(s). +____________________________________________________________ + +____________________________________________________________ +As one of the details to be stored is "null", +ConTech is unable to process it +____________________________________________________________ + +____________________________________________________________ +As one of the details to be stored is "null", +ConTech is unable to process it +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: dev +You now have 6 contact(s). +____________________________________________________________ + +____________________________________________________________ +ConTech has edited the specified contact: lezongmun +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: name +You now have 7 contact(s). +____________________________________________________________ + +____________________________________________________________ +There appears to be a flag that is not recognised. +Please try again with a valid flag. + -n NAME + -g GITHUB + -l LINKEDIN + -te TELEGRAM + -tw TWITTER + -e EMAIL +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: lezai3 +You now have 8 contact(s). +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: lezongggg +You now have 9 contact(s). +____________________________________________________________ + +____________________________________________________________ +ConTech will now shutdown. +We hope you have enjoyed using it. +____________________________________________________________ + diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index f0d19ee2dd..269110668d 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -97,7 +97,7 @@ ____________________________________________________________ ____________________________________________________________ There are missing details. -Please remove any flags with no details, +Please remove any flags with no details, and ensure that your flags used are correct: -n NAME -g GITHUB @@ -161,7 +161,7 @@ ____________________________________________________________ ____________________________________________________________ There are missing details. -Please remove any flags with no details, +Please remove any flags with no details, and ensure that your flags used are correct: -n NAME -g GITHUB @@ -247,7 +247,7 @@ ____________________________________________________________ ____________________________________________________________ There are missing details. -Please remove any flags with no details, +Please remove any flags with no details, and ensure that your flags used are correct: -n NAME -g GITHUB @@ -268,12 +268,12 @@ You now have 5 contact(s). ____________________________________________________________ ____________________________________________________________ -As one of the details to be stored is "null", +As one of the details to be stored is "null", ConTech is unable to process it ____________________________________________________________ ____________________________________________________________ -As one of the details to be stored is "null", +As one of the details to be stored is "null", ConTech is unable to process it ____________________________________________________________ From 9e4ff235089a9bb1907cd7c57ec1bc9598aad1a7 Mon Sep 17 00:00:00 2001 From: lezong Date: Tue, 12 Oct 2021 18:31:46 +0800 Subject: [PATCH 178/756] Fix according to review by Andre --- src/main/java/seedu/parser/ContactParser.java | 2 -- src/main/java/seedu/parser/IndexParser.java | 13 ++++++------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index 35d9abc01d..8ec4bcf5dd 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -57,8 +57,6 @@ public void parseDetail(String[] contactDetails, String detail) contactDetails[indexToStore] = detailToStore; } - - private int getIndexToStore(String flag) throws InvalidFlagException { int indexToStore; switch (flag) { diff --git a/src/main/java/seedu/parser/IndexParser.java b/src/main/java/seedu/parser/IndexParser.java index bc4aa90a2f..28ab1dbd09 100644 --- a/src/main/java/seedu/parser/IndexParser.java +++ b/src/main/java/seedu/parser/IndexParser.java @@ -14,18 +14,17 @@ public class IndexParser { public static int getIndexFromInput(String userInput, String command) throws NumberFormatException, MissingArgException { - String[] comdIndexSplit = userInput.split(" ", COMD_INDEX_LENGTH); - if (comdIndexSplit.length == COMD_WORD_LENGTH) { + String[] destructuredInputs = userInput.split(" ", COMD_INDEX_LENGTH); + if (destructuredInputs.length <= COMD_WORD_LENGTH) { throw new MissingArgException(); } - String[] indexSplit = comdIndexSplit[INDEX_POSITION].trim().split(" "); + String[] indexSplit = destructuredInputs[INDEX_POSITION].trim().split(" "); // throws NumberFormatExcept if not integer - int index = Integer.parseInt(indexSplit[SIGNIFICANT_INDEX_POSITION].trim()); - return index; + return Integer.parseInt(indexSplit[SIGNIFICANT_INDEX_POSITION].trim()); + } public static Contact getContactFromIndex(int index, ContactList contactList) throws IndexOutOfBoundsException { - Contact contact = contactList.getContactAtIndex(index); - return contact; + return contactList.getContactAtIndex(index); } } From c430098d87ca476b0220b292b01fe062a01afe82 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 18:38:24 +0800 Subject: [PATCH 179/756] Add InvalidEmailExecption.java class --- src/main/java/seedu/exception/InvalidEmailException.java | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 src/main/java/seedu/exception/InvalidEmailException.java diff --git a/src/main/java/seedu/exception/InvalidEmailException.java b/src/main/java/seedu/exception/InvalidEmailException.java new file mode 100644 index 0000000000..0efbc72641 --- /dev/null +++ b/src/main/java/seedu/exception/InvalidEmailException.java @@ -0,0 +1,2 @@ +package seedu.exception;public class InvalidEmailException { +} From 16efacc5fdeb4c3c75ecffe2cc747d837eb2d7d0 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 18:39:10 +0800 Subject: [PATCH 180/756] Add InvalidGithubUsernameExecption.java class --- .../java/seedu/exception/InvalidGithubUsernameException.java | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/main/java/seedu/exception/InvalidGithubUsernameException.java diff --git a/src/main/java/seedu/exception/InvalidGithubUsernameException.java b/src/main/java/seedu/exception/InvalidGithubUsernameException.java new file mode 100644 index 0000000000..42fb180b02 --- /dev/null +++ b/src/main/java/seedu/exception/InvalidGithubUsernameException.java @@ -0,0 +1,4 @@ +package seedu.exception; + +public class InvalidGithubUsernameException extends Exception{ +} From 80e5b18c36d141796dfade5157ea0576b9cf071d Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 18:39:43 +0800 Subject: [PATCH 181/756] Add InvalidNameExecption.java class --- src/main/java/seedu/exception/InvalidNameException.java | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/main/java/seedu/exception/InvalidNameException.java diff --git a/src/main/java/seedu/exception/InvalidNameException.java b/src/main/java/seedu/exception/InvalidNameException.java new file mode 100644 index 0000000000..dccf326de6 --- /dev/null +++ b/src/main/java/seedu/exception/InvalidNameException.java @@ -0,0 +1,4 @@ +package seedu.exception; + +public class InvalidNameException extends Exception { +} From 1f902a05cfc666459c200d50bb96eab42c2bb95b Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 18:40:50 +0800 Subject: [PATCH 182/756] Add InvalidTwitterUsernameException.java class --- .../java/seedu/exception/InvalidTwitterUsernameException.java | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/main/java/seedu/exception/InvalidTwitterUsernameException.java diff --git a/src/main/java/seedu/exception/InvalidTwitterUsernameException.java b/src/main/java/seedu/exception/InvalidTwitterUsernameException.java new file mode 100644 index 0000000000..091bb77d22 --- /dev/null +++ b/src/main/java/seedu/exception/InvalidTwitterUsernameException.java @@ -0,0 +1,4 @@ +package seedu.exception; + +public class InvalidTwitterUsernameException extends Exception{ +} From 81ec455dccdc4d0a54405dc6935637ae78aae0e0 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 18:41:16 +0800 Subject: [PATCH 183/756] Add InvalidLinkedinUsernameException.java class --- .../seedu/exception/InvalidLinkedinUsernameException.java | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/main/java/seedu/exception/InvalidLinkedinUsernameException.java diff --git a/src/main/java/seedu/exception/InvalidLinkedinUsernameException.java b/src/main/java/seedu/exception/InvalidLinkedinUsernameException.java new file mode 100644 index 0000000000..982c30397a --- /dev/null +++ b/src/main/java/seedu/exception/InvalidLinkedinUsernameException.java @@ -0,0 +1,4 @@ +package seedu.exception; + +public class InvalidLinkedinUsernameException extends Exception{ +} From dda1c1102c80ed4adb3285bdb261fcb632d63f7f Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 18:41:44 +0800 Subject: [PATCH 184/756] Add InvalidTelegramUsernameException.java class --- .../seedu/exception/InvalidTelegramUsernameException.java | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/main/java/seedu/exception/InvalidTelegramUsernameException.java diff --git a/src/main/java/seedu/exception/InvalidTelegramUsernameException.java b/src/main/java/seedu/exception/InvalidTelegramUsernameException.java new file mode 100644 index 0000000000..27543793a5 --- /dev/null +++ b/src/main/java/seedu/exception/InvalidTelegramUsernameException.java @@ -0,0 +1,4 @@ +package seedu.exception; + +public class InvalidTelegramUsernameException extends Exception{ +} From 2f66525d4805c32e3a69ed9129acaf71477d4454 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Tue, 12 Oct 2021 19:21:13 +0800 Subject: [PATCH 185/756] Implement new ViewMessageFormatterUi class to format the fields into what is to be printed. --- .../java/seedu/ui/ViewMessageFormatterUi.java | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 src/main/java/seedu/ui/ViewMessageFormatterUi.java diff --git a/src/main/java/seedu/ui/ViewMessageFormatterUi.java b/src/main/java/seedu/ui/ViewMessageFormatterUi.java new file mode 100644 index 0000000000..d660878e6a --- /dev/null +++ b/src/main/java/seedu/ui/ViewMessageFormatterUi.java @@ -0,0 +1,84 @@ +package seedu.ui; + +import seedu.contact.Contact; + +public class ViewMessageFormatterUi { + public static String viewNameFormatter(Contact contact) { + try { + if (contact.getName() == null | contact.getName().equals("null")) { + return ""; + } else { + assert(!contact.getName().equals("null")); + return contact.getName(); + } + } catch (NullPointerException e) { + return ""; + } + } + + public static String viewGithubFormatter(Contact contact) { + try { + if (contact.getGithub() == null | contact.getGithub().equals("null")) { + return ""; + } else { + assert(!contact.getGithub().equals("null")); + return "\nGithub: github.com/" + contact.getGithub(); + } + } catch (NullPointerException e) { + return ""; + } + } + + public static String viewEmailFormatter(Contact contact) { + try { + if (contact.getEmail() == null | contact.getEmail().equals("null")) { + return ""; + } else { + assert(!contact.getEmail().equals("null")); + return "\nEmail: " + contact.getEmail(); + } + } catch (NullPointerException e) { + return ""; + } + } + + public static String viewTelegramFormatter(Contact contact) { + try { + if (contact.getTelegram() == null | contact.getTelegram().equals("null")) { + return ""; + } else { + assert(!contact.getTelegram().equals("null")); + return "\nTelegram: t.me/" + contact.getTelegram(); + } + } catch (NullPointerException e) { + return ""; + } + } + + public static String viewLinkedinFormatter(Contact contact) { + try { + if (contact.getLinkedin() == null | contact.getLinkedin().equals("null")) { + return ""; + } else { + assert(!contact.getLinkedin().equals("null")); + return "\nLinkedIn: linkedin.com/in/" + contact.getLinkedin(); + } + } catch (NullPointerException e) { + return ""; + } + } + + public static String viewTwitterFormatter(Contact contact) { + try { + if (contact.getTwitter() == null | contact.getTwitter().equals("null")) { + return ""; + } else { + assert(!contact.getTwitter().equals("null")); + return "\nTwitter: twitter.com/" + contact.getTwitter(); + } + } catch (NullPointerException e) { + return ""; + } + } + +} From 440a5b9f8cbaa3df934e6dcfeedd1c38963137f3 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Tue, 12 Oct 2021 19:22:39 +0800 Subject: [PATCH 186/756] Implement formatContactFields in TextUi to format all fields except name into what we want to print. --- src/main/java/seedu/ui/TextUi.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 8c8eb3b286..d2229ad9fe 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -69,6 +69,15 @@ public static void editContactMessage(String contactName) { printDoubleLineMessage(message); } + public static String formatContactFields(Contact addedContact) { + String viewGithub = ViewMessageFormatterUi.viewGithubFormatter(addedContact); + String viewEmail = ViewMessageFormatterUi.viewEmailFormatter(addedContact); + String viewTwitter = ViewMessageFormatterUi.viewTwitterFormatter(addedContact); + String viewTelegram = ViewMessageFormatterUi.viewTelegramFormatter(addedContact); + String viewLinkedin = ViewMessageFormatterUi.viewLinkedinFormatter(addedContact); + return viewGithub + viewEmail + viewTelegram + viewLinkedin + viewTwitter; + } + public static void viewContactMessage(Contact viewingContact, int index) { String message = index + ". " + "Name: " + viewingContact.getName() + " GitHub: " + viewingContact.getGithub(); printDoubleLineMessage(message); From 9408a42690fddcdfdaad9c0e14224b7d1cbbece8 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Tue, 12 Oct 2021 19:23:47 +0800 Subject: [PATCH 187/756] Refactor viewContactMessage to print all newly added fields in desired format. --- src/main/java/seedu/ui/TextUi.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index d2229ad9fe..ce965579fb 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -79,7 +79,8 @@ public static String formatContactFields(Contact addedContact) { } public static void viewContactMessage(Contact viewingContact, int index) { - String message = index + ". " + "Name: " + viewingContact.getName() + " GitHub: " + viewingContact.getGithub(); + String viewName = ViewMessageFormatterUi.viewNameFormatter(viewingContact); + String message = index + ". " + viewName + formatContactFields(viewingContact); printDoubleLineMessage(message); } From e58eec542c8d14384a8a7d451ef72d33d5e39e0a Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Tue, 12 Oct 2021 19:24:31 +0800 Subject: [PATCH 188/756] Refactor addContactMessage to print out all details of newly added contact. --- src/main/java/seedu/ui/TextUi.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index ce965579fb..e6c190b552 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -58,9 +58,11 @@ public static void createNewContactFileMessage(String contactFilePath) { printBottomLineMessage(message); } - public static void addContactMessage(String contactName, int listSize) { - String message = "ConTech has added the specified contact: " + contactName + "\n" + "You now have " + listSize - + " contact(s)."; + public static void addContactMessage(Contact addedContact, int listSize) { + String message = "ConTech has added the specified contact: \n" + + "Name: " + addedContact.getName() + + formatContactFields(addedContact) + + "\n\nYou now have " + listSize + " contact(s)."; printDoubleLineMessage(message); } From b7810fed977ba2c83ee0e83d34dbabbb17902c7e Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Tue, 12 Oct 2021 19:25:05 +0800 Subject: [PATCH 189/756] Refactor editContactMessage to print out all fields of recently edited contact. --- src/main/java/seedu/ui/TextUi.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index e6c190b552..dd1b679c48 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -66,8 +66,10 @@ public static void addContactMessage(Contact addedContact, int listSize) { printDoubleLineMessage(message); } - public static void editContactMessage(String contactName) { - String message = "ConTech has edited the specified contact: " + contactName; + public static void editContactMessage(Contact editedContact) { + String message = "ConTech has edited the specified contact: \n" + + "Name: " + editedContact.getName() + + formatContactFields(editedContact); printDoubleLineMessage(message); } From abb970e3551f7981022876758a0274b47cfb04c5 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Tue, 12 Oct 2021 19:26:34 +0800 Subject: [PATCH 190/756] Change addContactMessage to pass Contact type rather than just String for access to all fields in the contact. --- src/main/java/seedu/command/AddContactCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/command/AddContactCommand.java b/src/main/java/seedu/command/AddContactCommand.java index 2aa17be17a..2221cf6508 100644 --- a/src/main/java/seedu/command/AddContactCommand.java +++ b/src/main/java/seedu/command/AddContactCommand.java @@ -48,6 +48,6 @@ public AddContactCommand(String name, String github, String linkedin, String tel public void execute() { Contact addedContact = new Contact(name, github, linkedin, telegram, twitter, email); contactList.addContact(addedContact); - TextUi.addContactMessage(name, contactList.getListSize()); + TextUi.addContactMessage(addedContact, contactList.getListSize()); } } From 5248dee662657bb1bac1460cd5fc93761c092b33 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Tue, 12 Oct 2021 19:27:05 +0800 Subject: [PATCH 191/756] Change editContactMessage to pass Contact type for access to all fields in contact. --- src/main/java/seedu/command/EditContactCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index 0571ddeee3..7f0d837f16 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -17,7 +17,7 @@ public EditContactCommand(String[] contactDetails, int contactIndex) { public void execute() { try { contactList.editContact(contactDetails, contactIndex); - TextUi.editContactMessage(contactList.getContactAtIndex(contactIndex).getName()); + TextUi.editContactMessage(contactList.getContactAtIndex(contactIndex)); } catch (IndexOutOfBoundsException | InvalidFlagException e) { ExceptionTextUi.invalidIndexMessage(); } From 9960cd87d5b7f972d69675aeca6f492c0d40370c Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Tue, 12 Oct 2021 19:27:49 +0800 Subject: [PATCH 192/756] Add new JUnit test to test trim function for view command. --- src/test/java/seedu/parser/MainParserTest.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/test/java/seedu/parser/MainParserTest.java b/src/test/java/seedu/parser/MainParserTest.java index 25b625f5c0..3c014fd349 100644 --- a/src/test/java/seedu/parser/MainParserTest.java +++ b/src/test/java/seedu/parser/MainParserTest.java @@ -153,6 +153,13 @@ public void parseViewCommand_invalidIndex_expectException() { assertThrows(NullPointerException.class, testResultCommand::execute); } + @Test + public void parseViewCommand_validIndexWithSpaces_expectViewContactIndexMatch() { + testIndex = 1; + testUserInput = "view " + testIndex; + final ViewCommand testResultCommand = getParsedCommand(testUserInput, ViewCommand.class); + assertEquals(testIndex, testResultCommand.getIndex()); + } @Test public void parseAddCommand_missingName_expectFailedCommand() { testUserInput = " add -g github "; From 29ceebf91d500d9035fba440898bc5fe8c5bfe2b Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Tue, 12 Oct 2021 19:28:33 +0800 Subject: [PATCH 193/756] Add new JUnit test to test missing inputs for view command. --- src/test/java/seedu/parser/MainParserTest.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/test/java/seedu/parser/MainParserTest.java b/src/test/java/seedu/parser/MainParserTest.java index 3c014fd349..9d13911707 100644 --- a/src/test/java/seedu/parser/MainParserTest.java +++ b/src/test/java/seedu/parser/MainParserTest.java @@ -160,6 +160,15 @@ public void parseViewCommand_validIndexWithSpaces_expectViewContactIndexMatch() final ViewCommand testResultCommand = getParsedCommand(testUserInput, ViewCommand.class); assertEquals(testIndex, testResultCommand.getIndex()); } + + @Test + public void parseViewCommand_missingIndex_expectFailedCommandType() { + testUserInput = "view"; + FailedCommandType expectedFailedCommandType = FailedCommandType.MISSING_ARG; + final FailedCommand actualFailedCommand = getParsedCommand(testUserInput, FailedCommand.class); + assertEquals(expectedFailedCommandType, actualFailedCommand.getType()); + } + @Test public void parseAddCommand_missingName_expectFailedCommand() { testUserInput = " add -g github "; From 5ce2e7fe3de4e78f9eea50b0b4a13ae0aeee235d Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Tue, 12 Oct 2021 19:28:56 +0800 Subject: [PATCH 194/756] Add new JUnit test to test invalid inputs for view command. --- src/test/java/seedu/parser/MainParserTest.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/test/java/seedu/parser/MainParserTest.java b/src/test/java/seedu/parser/MainParserTest.java index 9d13911707..616535ab46 100644 --- a/src/test/java/seedu/parser/MainParserTest.java +++ b/src/test/java/seedu/parser/MainParserTest.java @@ -169,6 +169,14 @@ public void parseViewCommand_missingIndex_expectFailedCommandType() { assertEquals(expectedFailedCommandType, actualFailedCommand.getType()); } + @Test + public void parseViewCommand_invalidInput_expectFailedCommandType() { + testUserInput = "view abc"; + FailedCommandType expectedFailedCommandType = FailedCommandType.INVALID_INDEX; + final FailedCommand actualFailedCommand = getParsedCommand(testUserInput, FailedCommand.class); + assertEquals(expectedFailedCommandType, actualFailedCommand.getType()); + } + @Test public void parseAddCommand_missingName_expectFailedCommand() { testUserInput = " add -g github "; From dc2d1af6db4e57a211fb8dce086197f1d39d9deb Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Tue, 12 Oct 2021 19:29:22 +0800 Subject: [PATCH 195/756] Add new JUnit test to test invalid input format for view command. --- src/test/java/seedu/parser/MainParserTest.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/test/java/seedu/parser/MainParserTest.java b/src/test/java/seedu/parser/MainParserTest.java index 616535ab46..32ad9d3239 100644 --- a/src/test/java/seedu/parser/MainParserTest.java +++ b/src/test/java/seedu/parser/MainParserTest.java @@ -177,6 +177,14 @@ public void parseViewCommand_invalidInput_expectFailedCommandType() { assertEquals(expectedFailedCommandType, actualFailedCommand.getType()); } + @Test + public void parseViewCommand_invalidInputFormat_expectFailedCommandType() { + testUserInput = "view 1 2"; + FailedCommandType expectedFailedCommandType = FailedCommandType.INVALID_INDEX; + final FailedCommand actualFailedCommand = getParsedCommand(testUserInput, FailedCommand.class); + assertEquals(expectedFailedCommandType, actualFailedCommand.getType()); + } + @Test public void parseAddCommand_missingName_expectFailedCommand() { testUserInput = " add -g github "; From d08ecbe494198103f144413acb8db1f88be8b388 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Tue, 12 Oct 2021 19:35:31 +0800 Subject: [PATCH 196/756] Refactor ViewMessageFormatter for checkstyle. --- src/main/java/seedu/ui/ViewMessageFormatterUi.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/main/java/seedu/ui/ViewMessageFormatterUi.java b/src/main/java/seedu/ui/ViewMessageFormatterUi.java index d660878e6a..354ba0d5d4 100644 --- a/src/main/java/seedu/ui/ViewMessageFormatterUi.java +++ b/src/main/java/seedu/ui/ViewMessageFormatterUi.java @@ -8,7 +8,6 @@ public static String viewNameFormatter(Contact contact) { if (contact.getName() == null | contact.getName().equals("null")) { return ""; } else { - assert(!contact.getName().equals("null")); return contact.getName(); } } catch (NullPointerException e) { @@ -21,7 +20,6 @@ public static String viewGithubFormatter(Contact contact) { if (contact.getGithub() == null | contact.getGithub().equals("null")) { return ""; } else { - assert(!contact.getGithub().equals("null")); return "\nGithub: github.com/" + contact.getGithub(); } } catch (NullPointerException e) { @@ -34,7 +32,6 @@ public static String viewEmailFormatter(Contact contact) { if (contact.getEmail() == null | contact.getEmail().equals("null")) { return ""; } else { - assert(!contact.getEmail().equals("null")); return "\nEmail: " + contact.getEmail(); } } catch (NullPointerException e) { @@ -47,7 +44,6 @@ public static String viewTelegramFormatter(Contact contact) { if (contact.getTelegram() == null | contact.getTelegram().equals("null")) { return ""; } else { - assert(!contact.getTelegram().equals("null")); return "\nTelegram: t.me/" + contact.getTelegram(); } } catch (NullPointerException e) { @@ -60,7 +56,6 @@ public static String viewLinkedinFormatter(Contact contact) { if (contact.getLinkedin() == null | contact.getLinkedin().equals("null")) { return ""; } else { - assert(!contact.getLinkedin().equals("null")); return "\nLinkedIn: linkedin.com/in/" + contact.getLinkedin(); } } catch (NullPointerException e) { @@ -73,7 +68,6 @@ public static String viewTwitterFormatter(Contact contact) { if (contact.getTwitter() == null | contact.getTwitter().equals("null")) { return ""; } else { - assert(!contact.getTwitter().equals("null")); return "\nTwitter: twitter.com/" + contact.getTwitter(); } } catch (NullPointerException e) { From b8d3580edaf180c1430d7e034f17312663e287cc Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Tue, 12 Oct 2021 19:37:22 +0800 Subject: [PATCH 197/756] Add assertion in viewNameFormatter function. --- src/main/java/seedu/ui/ViewMessageFormatterUi.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/seedu/ui/ViewMessageFormatterUi.java b/src/main/java/seedu/ui/ViewMessageFormatterUi.java index 354ba0d5d4..d7ce69b272 100644 --- a/src/main/java/seedu/ui/ViewMessageFormatterUi.java +++ b/src/main/java/seedu/ui/ViewMessageFormatterUi.java @@ -8,6 +8,7 @@ public static String viewNameFormatter(Contact contact) { if (contact.getName() == null | contact.getName().equals("null")) { return ""; } else { + assert(!contact.getName().equals("null")); return contact.getName(); } } catch (NullPointerException e) { From 7dd3cc77254705c553e0769f675117e4836dfbe0 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Tue, 12 Oct 2021 19:37:37 +0800 Subject: [PATCH 198/756] Add assertion in viewGithubFormatter function. --- src/main/java/seedu/ui/ViewMessageFormatterUi.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/seedu/ui/ViewMessageFormatterUi.java b/src/main/java/seedu/ui/ViewMessageFormatterUi.java index d7ce69b272..9829afd94e 100644 --- a/src/main/java/seedu/ui/ViewMessageFormatterUi.java +++ b/src/main/java/seedu/ui/ViewMessageFormatterUi.java @@ -21,6 +21,7 @@ public static String viewGithubFormatter(Contact contact) { if (contact.getGithub() == null | contact.getGithub().equals("null")) { return ""; } else { + assert(!contact.getGithub().equals("null")); return "\nGithub: github.com/" + contact.getGithub(); } } catch (NullPointerException e) { From 393b896250d8e4ea8f705d55fe2b2b3afa4f56fb Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Tue, 12 Oct 2021 19:37:48 +0800 Subject: [PATCH 199/756] Add assertion in viewEmailFormatter function. --- src/main/java/seedu/ui/ViewMessageFormatterUi.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/seedu/ui/ViewMessageFormatterUi.java b/src/main/java/seedu/ui/ViewMessageFormatterUi.java index 9829afd94e..ab9f016c92 100644 --- a/src/main/java/seedu/ui/ViewMessageFormatterUi.java +++ b/src/main/java/seedu/ui/ViewMessageFormatterUi.java @@ -34,6 +34,7 @@ public static String viewEmailFormatter(Contact contact) { if (contact.getEmail() == null | contact.getEmail().equals("null")) { return ""; } else { + assert(!contact.getEmail().equals("null")); return "\nEmail: " + contact.getEmail(); } } catch (NullPointerException e) { From 4447096736cd4522983c0530c6365cc68f45e8f4 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Tue, 12 Oct 2021 19:38:04 +0800 Subject: [PATCH 200/756] Add assertion in viewTelegramFormatter function. --- src/main/java/seedu/ui/ViewMessageFormatterUi.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/seedu/ui/ViewMessageFormatterUi.java b/src/main/java/seedu/ui/ViewMessageFormatterUi.java index ab9f016c92..b2361ed572 100644 --- a/src/main/java/seedu/ui/ViewMessageFormatterUi.java +++ b/src/main/java/seedu/ui/ViewMessageFormatterUi.java @@ -47,6 +47,7 @@ public static String viewTelegramFormatter(Contact contact) { if (contact.getTelegram() == null | contact.getTelegram().equals("null")) { return ""; } else { + assert(!contact.getTelegram().equals("null")); return "\nTelegram: t.me/" + contact.getTelegram(); } } catch (NullPointerException e) { From 2ae3b75378a4fb10d4bbd71a421446d687ba192c Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Tue, 12 Oct 2021 19:38:18 +0800 Subject: [PATCH 201/756] Add assertion in viewLinkedinFormatter function. --- src/main/java/seedu/ui/ViewMessageFormatterUi.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/seedu/ui/ViewMessageFormatterUi.java b/src/main/java/seedu/ui/ViewMessageFormatterUi.java index b2361ed572..11be931a5f 100644 --- a/src/main/java/seedu/ui/ViewMessageFormatterUi.java +++ b/src/main/java/seedu/ui/ViewMessageFormatterUi.java @@ -60,6 +60,7 @@ public static String viewLinkedinFormatter(Contact contact) { if (contact.getLinkedin() == null | contact.getLinkedin().equals("null")) { return ""; } else { + assert(!contact.getLinkedin().equals("null")); return "\nLinkedIn: linkedin.com/in/" + contact.getLinkedin(); } } catch (NullPointerException e) { From 2e000040afa98e27abf1d4a6ace10e2e5a2da2d1 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Tue, 12 Oct 2021 19:38:29 +0800 Subject: [PATCH 202/756] Add assertion in viewTwitterFormatter function. --- src/main/java/seedu/ui/ViewMessageFormatterUi.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/seedu/ui/ViewMessageFormatterUi.java b/src/main/java/seedu/ui/ViewMessageFormatterUi.java index 11be931a5f..d660878e6a 100644 --- a/src/main/java/seedu/ui/ViewMessageFormatterUi.java +++ b/src/main/java/seedu/ui/ViewMessageFormatterUi.java @@ -73,6 +73,7 @@ public static String viewTwitterFormatter(Contact contact) { if (contact.getTwitter() == null | contact.getTwitter().equals("null")) { return ""; } else { + assert(!contact.getTwitter().equals("null")); return "\nTwitter: twitter.com/" + contact.getTwitter(); } } catch (NullPointerException e) { From b0f514fbac57ef83a278d6d8463004e8aeeeb48b Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Tue, 12 Oct 2021 19:57:45 +0800 Subject: [PATCH 203/756] Refactor assertions to comply with checkstyle. --- src/main/java/seedu/ui/ViewMessageFormatterUi.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/seedu/ui/ViewMessageFormatterUi.java b/src/main/java/seedu/ui/ViewMessageFormatterUi.java index d660878e6a..cc09859f90 100644 --- a/src/main/java/seedu/ui/ViewMessageFormatterUi.java +++ b/src/main/java/seedu/ui/ViewMessageFormatterUi.java @@ -8,7 +8,7 @@ public static String viewNameFormatter(Contact contact) { if (contact.getName() == null | contact.getName().equals("null")) { return ""; } else { - assert(!contact.getName().equals("null")); + assert (!contact.getName().equals("null")); return contact.getName(); } } catch (NullPointerException e) { @@ -21,7 +21,7 @@ public static String viewGithubFormatter(Contact contact) { if (contact.getGithub() == null | contact.getGithub().equals("null")) { return ""; } else { - assert(!contact.getGithub().equals("null")); + assert (!contact.getGithub().equals("null")); return "\nGithub: github.com/" + contact.getGithub(); } } catch (NullPointerException e) { @@ -34,7 +34,7 @@ public static String viewEmailFormatter(Contact contact) { if (contact.getEmail() == null | contact.getEmail().equals("null")) { return ""; } else { - assert(!contact.getEmail().equals("null")); + assert (!contact.getEmail().equals("null")); return "\nEmail: " + contact.getEmail(); } } catch (NullPointerException e) { @@ -47,7 +47,7 @@ public static String viewTelegramFormatter(Contact contact) { if (contact.getTelegram() == null | contact.getTelegram().equals("null")) { return ""; } else { - assert(!contact.getTelegram().equals("null")); + assert (!contact.getTelegram().equals("null")); return "\nTelegram: t.me/" + contact.getTelegram(); } } catch (NullPointerException e) { @@ -60,7 +60,7 @@ public static String viewLinkedinFormatter(Contact contact) { if (contact.getLinkedin() == null | contact.getLinkedin().equals("null")) { return ""; } else { - assert(!contact.getLinkedin().equals("null")); + assert (!contact.getLinkedin().equals("null")); return "\nLinkedIn: linkedin.com/in/" + contact.getLinkedin(); } } catch (NullPointerException e) { @@ -73,7 +73,7 @@ public static String viewTwitterFormatter(Contact contact) { if (contact.getTwitter() == null | contact.getTwitter().equals("null")) { return ""; } else { - assert(!contact.getTwitter().equals("null")); + assert (!contact.getTwitter().equals("null")); return "\nTwitter: twitter.com/" + contact.getTwitter(); } } catch (NullPointerException e) { From 23948a926dda77002904d2335decaa8f1fe7710f Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Tue, 12 Oct 2021 20:01:40 +0800 Subject: [PATCH 204/756] Edit EXPECTED and EXPECTED-UNIX txt files to reflect new ui changes. --- text-ui-test/ACTUAL.TXT | 82 +++++++++++++++++++++++++++------- text-ui-test/EXPECTED-UNIX.TXT | 82 +++++++++++++++++++++++++++------- text-ui-test/EXPECTED.TXT | 82 +++++++++++++++++++++++++++------- 3 files changed, 195 insertions(+), 51 deletions(-) diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index 9b91a5873b..aee4472890 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -18,7 +18,10 @@ data/contacts.txt ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: ng andre +ConTech has added the specified contact: +Name: ng andre +Github: github.com/ng-andre + You now have 1 contact(s). ____________________________________________________________ @@ -32,7 +35,10 @@ Please enter a valid contact index. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: ashraf +ConTech has added the specified contact: +Name: ashraf +Github: github.com/ashraf + You now have 2 contact(s). ____________________________________________________________ @@ -42,7 +48,10 @@ Please input a number between 0 and 1. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: mayank +ConTech has added the specified contact: +Name: mayank +Github: github.com/mayankp123 + You now have 3 contact(s). ____________________________________________________________ @@ -52,12 +61,18 @@ Please input a number between 0 and 2. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: bory +ConTech has added the specified contact: +Name: bory +Github: github.com/marcus + You now have 4 contact(s). ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: andre +ConTech has added the specified contact: +Name: andre +Github: github.com/ng-andre + You now have 5 contact(s). ____________________________________________________________ @@ -75,7 +90,8 @@ ____________________________________________________________ ____________________________________________________________ ____________________________________________________________ -1. Name: ashraf GitHub: ashraf +1. ashraf +Github: github.com/ashraf ____________________________________________________________ ____________________________________________________________ @@ -95,7 +111,10 @@ Please enter a valid contact index. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: lezong +ConTech has added the specified contact: +Name: lezong +Github: github.com/lezongmun + You now have 6 contact(s). ____________________________________________________________ @@ -119,7 +138,8 @@ ____________________________________________________________ ____________________________________________________________ ____________________________________________________________ -3. Name: bory GitHub: marcus +3. bory +Github: github.com/marcus ____________________________________________________________ ____________________________________________________________ @@ -145,7 +165,8 @@ and ensure that your flags used are correct: ____________________________________________________________ ____________________________________________________________ -2. Name: andre GitHub: ng-andre +2. andre +Github: github.com/ng-andre ____________________________________________________________ ____________________________________________________________ @@ -175,7 +196,10 @@ Please try again with a valid flag. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: lezongmun +ConTech has added the specified contact: +Name: lezongmun +Github: github.com/lezong + You now have 5 contact(s). ____________________________________________________________ @@ -201,7 +225,8 @@ Please enter a valid contact index. ____________________________________________________________ ____________________________________________________________ -0. Name: mayank GitHub: mayankp123 +0. mayank +Github: github.com/mayankp123 ____________________________________________________________ ____________________________________________________________ @@ -222,7 +247,10 @@ Due to the storage nature of ConTech, we will remove commas (","), and attempt to parse it as: add -n lezong mun -g lezaimun ____________________________________________________________ -ConTech has added the specified contact: lezong mun +ConTech has added the specified contact: +Name: lezong mun +Github: github.com/lezaimun + You now have 5 contact(s). ____________________________________________________________ @@ -237,16 +265,28 @@ ConTech is unable to process it ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: dev +ConTech has added the specified contact: +Name: dev +Github: github.com/nullptr + You now have 6 contact(s). ____________________________________________________________ ____________________________________________________________ -ConTech has edited the specified contact: lezongmun +ConTech has edited the specified contact: +Name: lezongmun +Github: github.com/new-git ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: name +ConTech has added the specified contact: +Name: name +Github: github.com/github +Email: email +Telegram: t.me/telegram +LinkedIn: linkedin.com/in/linkedin +Twitter: twitter.com/twitter + You now have 7 contact(s). ____________________________________________________________ @@ -262,12 +302,20 @@ Please try again with a valid flag. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: lezai3 +ConTech has added the specified contact: +Name: lezai3 +Github: github.com/lezongmun +Email: lezongmun@gmail.com +LinkedIn: linkedin.com/in/lezongmun + You now have 8 contact(s). ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: lezongggg +ConTech has added the specified contact: +Name: lezongggg +Telegram: t.me/testTelegram + You now have 9 contact(s). ____________________________________________________________ diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index 9b91a5873b..aee4472890 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -18,7 +18,10 @@ data/contacts.txt ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: ng andre +ConTech has added the specified contact: +Name: ng andre +Github: github.com/ng-andre + You now have 1 contact(s). ____________________________________________________________ @@ -32,7 +35,10 @@ Please enter a valid contact index. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: ashraf +ConTech has added the specified contact: +Name: ashraf +Github: github.com/ashraf + You now have 2 contact(s). ____________________________________________________________ @@ -42,7 +48,10 @@ Please input a number between 0 and 1. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: mayank +ConTech has added the specified contact: +Name: mayank +Github: github.com/mayankp123 + You now have 3 contact(s). ____________________________________________________________ @@ -52,12 +61,18 @@ Please input a number between 0 and 2. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: bory +ConTech has added the specified contact: +Name: bory +Github: github.com/marcus + You now have 4 contact(s). ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: andre +ConTech has added the specified contact: +Name: andre +Github: github.com/ng-andre + You now have 5 contact(s). ____________________________________________________________ @@ -75,7 +90,8 @@ ____________________________________________________________ ____________________________________________________________ ____________________________________________________________ -1. Name: ashraf GitHub: ashraf +1. ashraf +Github: github.com/ashraf ____________________________________________________________ ____________________________________________________________ @@ -95,7 +111,10 @@ Please enter a valid contact index. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: lezong +ConTech has added the specified contact: +Name: lezong +Github: github.com/lezongmun + You now have 6 contact(s). ____________________________________________________________ @@ -119,7 +138,8 @@ ____________________________________________________________ ____________________________________________________________ ____________________________________________________________ -3. Name: bory GitHub: marcus +3. bory +Github: github.com/marcus ____________________________________________________________ ____________________________________________________________ @@ -145,7 +165,8 @@ and ensure that your flags used are correct: ____________________________________________________________ ____________________________________________________________ -2. Name: andre GitHub: ng-andre +2. andre +Github: github.com/ng-andre ____________________________________________________________ ____________________________________________________________ @@ -175,7 +196,10 @@ Please try again with a valid flag. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: lezongmun +ConTech has added the specified contact: +Name: lezongmun +Github: github.com/lezong + You now have 5 contact(s). ____________________________________________________________ @@ -201,7 +225,8 @@ Please enter a valid contact index. ____________________________________________________________ ____________________________________________________________ -0. Name: mayank GitHub: mayankp123 +0. mayank +Github: github.com/mayankp123 ____________________________________________________________ ____________________________________________________________ @@ -222,7 +247,10 @@ Due to the storage nature of ConTech, we will remove commas (","), and attempt to parse it as: add -n lezong mun -g lezaimun ____________________________________________________________ -ConTech has added the specified contact: lezong mun +ConTech has added the specified contact: +Name: lezong mun +Github: github.com/lezaimun + You now have 5 contact(s). ____________________________________________________________ @@ -237,16 +265,28 @@ ConTech is unable to process it ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: dev +ConTech has added the specified contact: +Name: dev +Github: github.com/nullptr + You now have 6 contact(s). ____________________________________________________________ ____________________________________________________________ -ConTech has edited the specified contact: lezongmun +ConTech has edited the specified contact: +Name: lezongmun +Github: github.com/new-git ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: name +ConTech has added the specified contact: +Name: name +Github: github.com/github +Email: email +Telegram: t.me/telegram +LinkedIn: linkedin.com/in/linkedin +Twitter: twitter.com/twitter + You now have 7 contact(s). ____________________________________________________________ @@ -262,12 +302,20 @@ Please try again with a valid flag. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: lezai3 +ConTech has added the specified contact: +Name: lezai3 +Github: github.com/lezongmun +Email: lezongmun@gmail.com +LinkedIn: linkedin.com/in/lezongmun + You now have 8 contact(s). ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: lezongggg +ConTech has added the specified contact: +Name: lezongggg +Telegram: t.me/testTelegram + You now have 9 contact(s). ____________________________________________________________ diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 9b91a5873b..aee4472890 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -18,7 +18,10 @@ data/contacts.txt ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: ng andre +ConTech has added the specified contact: +Name: ng andre +Github: github.com/ng-andre + You now have 1 contact(s). ____________________________________________________________ @@ -32,7 +35,10 @@ Please enter a valid contact index. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: ashraf +ConTech has added the specified contact: +Name: ashraf +Github: github.com/ashraf + You now have 2 contact(s). ____________________________________________________________ @@ -42,7 +48,10 @@ Please input a number between 0 and 1. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: mayank +ConTech has added the specified contact: +Name: mayank +Github: github.com/mayankp123 + You now have 3 contact(s). ____________________________________________________________ @@ -52,12 +61,18 @@ Please input a number between 0 and 2. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: bory +ConTech has added the specified contact: +Name: bory +Github: github.com/marcus + You now have 4 contact(s). ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: andre +ConTech has added the specified contact: +Name: andre +Github: github.com/ng-andre + You now have 5 contact(s). ____________________________________________________________ @@ -75,7 +90,8 @@ ____________________________________________________________ ____________________________________________________________ ____________________________________________________________ -1. Name: ashraf GitHub: ashraf +1. ashraf +Github: github.com/ashraf ____________________________________________________________ ____________________________________________________________ @@ -95,7 +111,10 @@ Please enter a valid contact index. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: lezong +ConTech has added the specified contact: +Name: lezong +Github: github.com/lezongmun + You now have 6 contact(s). ____________________________________________________________ @@ -119,7 +138,8 @@ ____________________________________________________________ ____________________________________________________________ ____________________________________________________________ -3. Name: bory GitHub: marcus +3. bory +Github: github.com/marcus ____________________________________________________________ ____________________________________________________________ @@ -145,7 +165,8 @@ and ensure that your flags used are correct: ____________________________________________________________ ____________________________________________________________ -2. Name: andre GitHub: ng-andre +2. andre +Github: github.com/ng-andre ____________________________________________________________ ____________________________________________________________ @@ -175,7 +196,10 @@ Please try again with a valid flag. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: lezongmun +ConTech has added the specified contact: +Name: lezongmun +Github: github.com/lezong + You now have 5 contact(s). ____________________________________________________________ @@ -201,7 +225,8 @@ Please enter a valid contact index. ____________________________________________________________ ____________________________________________________________ -0. Name: mayank GitHub: mayankp123 +0. mayank +Github: github.com/mayankp123 ____________________________________________________________ ____________________________________________________________ @@ -222,7 +247,10 @@ Due to the storage nature of ConTech, we will remove commas (","), and attempt to parse it as: add -n lezong mun -g lezaimun ____________________________________________________________ -ConTech has added the specified contact: lezong mun +ConTech has added the specified contact: +Name: lezong mun +Github: github.com/lezaimun + You now have 5 contact(s). ____________________________________________________________ @@ -237,16 +265,28 @@ ConTech is unable to process it ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: dev +ConTech has added the specified contact: +Name: dev +Github: github.com/nullptr + You now have 6 contact(s). ____________________________________________________________ ____________________________________________________________ -ConTech has edited the specified contact: lezongmun +ConTech has edited the specified contact: +Name: lezongmun +Github: github.com/new-git ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: name +ConTech has added the specified contact: +Name: name +Github: github.com/github +Email: email +Telegram: t.me/telegram +LinkedIn: linkedin.com/in/linkedin +Twitter: twitter.com/twitter + You now have 7 contact(s). ____________________________________________________________ @@ -262,12 +302,20 @@ Please try again with a valid flag. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: lezai3 +ConTech has added the specified contact: +Name: lezai3 +Github: github.com/lezongmun +Email: lezongmun@gmail.com +LinkedIn: linkedin.com/in/lezongmun + You now have 8 contact(s). ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: lezongggg +ConTech has added the specified contact: +Name: lezongggg +Telegram: t.me/testTelegram + You now have 9 contact(s). ____________________________________________________________ From 4016e29968b84467a880e977f4e0f7b2eebf5787 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 20:09:17 +0800 Subject: [PATCH 205/756] Move variable to comply with checkstyle --- src/main/java/seedu/parser/ContactParser.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index f42df6185a..13ce353e2f 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -48,6 +48,7 @@ public void parseDetail(String[] contactDetails, String detail) if (detailToStore.equals("null")) { throw new ForbiddenDetailException(); } + int indexToStore; indexToStore = getIndexToStore(flag); contactDetails[indexToStore] = detailToStore; } From 163df17525d52f50800eb508fa83852b195c4dc6 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 20:11:28 +0800 Subject: [PATCH 206/756] Add checkRegex method for input validation --- src/main/java/seedu/parser/ContactParser.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index 13ce353e2f..7a34d27bf9 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -49,10 +49,39 @@ public void parseDetail(String[] contactDetails, String detail) throw new ForbiddenDetailException(); } int indexToStore; + checkRegex(flag, detailToStore); indexToStore = getIndexToStore(flag); contactDetails[indexToStore] = detailToStore; } + + public void checkRegex(String flag, String detailToParse) + throws InvalidGithubUsernameException, InvalidNameException, InvalidFlagException, + InvalidTelegramUsernameException, InvalidTwitterUsernameException, + InvalidLinkedinUsernameException, InvalidEmailException { + switch (flag) { + case "n": + checkNameRegex(detailToParse); + break; + case "g": + checkGithubUsernameRegex(detailToParse); + break; + case "tele": + checkTelegramUsernameRegex(detailToParse); + break; + case "twit": + checkTwitterUsernameRegex(detailToParse); + break; + case "link": + checkLinkedinUsernameRegex(detailToParse); + break; + case "email": + checkEmailRegex(detailToParse); + break; + default: + throw new InvalidFlagException(); + } + } private int getIndexToStore(String flag) throws InvalidFlagException { int indexToStore; switch (flag) { From 5a7b39c15158190262a048947d27d0f1074815fd Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 20:12:26 +0800 Subject: [PATCH 207/756] Add method to check email regex --- src/main/java/seedu/parser/ContactParser.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index 7a34d27bf9..851704f549 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -82,6 +82,14 @@ public void checkRegex(String flag, String detailToParse) throw new InvalidFlagException(); } } + + private void checkEmailRegex(String detailToParse) throws InvalidEmailException { + //allow lowercase email ids + String emailRegex = "^([\\w-\\.]+){1,64}@([\\w&&[^_]]+){2,255}.[a-z]{2,}$"; + if (!detailToParse.matches(emailRegex)) { + throw new InvalidEmailException(); + } + } private int getIndexToStore(String flag) throws InvalidFlagException { int indexToStore; switch (flag) { From 381a7707d434ca2cf712dfe5f5f3d15d9bb41bc5 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 20:13:08 +0800 Subject: [PATCH 208/756] Add method to check Linkedin username regex --- src/main/java/seedu/parser/ContactParser.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index 851704f549..9d96784f16 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -90,6 +90,15 @@ private void checkEmailRegex(String detailToParse) throws InvalidEmailException throw new InvalidEmailException(); } } + + private void checkLinkedinUsernameRegex(String detailToParse) throws InvalidLinkedinUsernameException { + //allows lowercase, numbers, underscore and hyphen. Length must be 3-100 characters + String linkedinRegex = "^[a-z0-9-_]{3,100}$"; + if (!detailToParse.matches(linkedinRegex)) { + throw new InvalidLinkedinUsernameException(); + } + } + private int getIndexToStore(String flag) throws InvalidFlagException { int indexToStore; switch (flag) { From 462859154704d6a199eda540de9976cc80b0ef14 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 20:13:30 +0800 Subject: [PATCH 209/756] Add method to check twitter username regex --- src/main/java/seedu/parser/ContactParser.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index 9d96784f16..0f9597c9bb 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -99,6 +99,14 @@ private void checkLinkedinUsernameRegex(String detailToParse) throws InvalidLink } } + private void checkTwitterUsernameRegex(String detailToParse) throws InvalidTwitterUsernameException { + //allows lowercase, numbers and underscore. Length must be max 15 characters + String twitterRegex = "^[a-z0-9_]{1,15}$"; + if (!detailToParse.matches(twitterRegex)) { + throw new InvalidTwitterUsernameException(); + } + } + private int getIndexToStore(String flag) throws InvalidFlagException { int indexToStore; switch (flag) { From fe83ba6627ce166289dbf73bedea2440c23e0c4b Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 20:14:00 +0800 Subject: [PATCH 210/756] Add method to check telegram username regex --- src/main/java/seedu/parser/ContactParser.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index 0f9597c9bb..5881bb24aa 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -107,6 +107,14 @@ private void checkTwitterUsernameRegex(String detailToParse) throws InvalidTwitt } } + private void checkTelegramUsernameRegex(String detailToParse) throws InvalidTelegramUsernameException { + //allows uppercase, lowercase, numbers and underscore. Length must be atleast 5 characters + String telegramRegex = "^[a-zA-Z0-9_]{5,}$"; + if (!detailToParse.matches(telegramRegex)) { + throw new InvalidTelegramUsernameException(); + } + } + private int getIndexToStore(String flag) throws InvalidFlagException { int indexToStore; switch (flag) { From eef55771eb1727d7e033b1861ba35ca3c615a51f Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 20:14:29 +0800 Subject: [PATCH 211/756] Add method to check github username regex --- src/main/java/seedu/parser/ContactParser.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index 5881bb24aa..85e9e7cef5 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -115,6 +115,16 @@ private void checkTelegramUsernameRegex(String detailToParse) throws InvalidTele } } + private void checkGithubUsernameRegex(String detailToParse) throws InvalidGithubUsernameException { + //Github username may only contain alphanumeric characters or hyphens. + //Github username cannot have multiple consecutive hyphens. + //Github username cannot begin or end with a hyphen. + //Maximum is 39 characters. + String githubUsernameRegex = "^[a-z\\d](?:[a-z\\d]|-(?=[a-z\\d])){0,38}$"; + if (!detailToParse.matches(githubUsernameRegex)) { + throw new InvalidGithubUsernameException(); + } + } private int getIndexToStore(String flag) throws InvalidFlagException { int indexToStore; switch (flag) { From ea9e1d94761eb8e523671e3e8cea2c9ee8cc91de Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 20:15:09 +0800 Subject: [PATCH 212/756] Add method to check name regex --- src/main/java/seedu/parser/ContactParser.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index 85e9e7cef5..7b8666c715 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -125,6 +125,16 @@ private void checkGithubUsernameRegex(String detailToParse) throws InvalidGithub throw new InvalidGithubUsernameException(); } } + + private void checkNameRegex(String detailToParse) throws InvalidNameException { + //only letters and spaces allowed + String nameRegex = "^[ A-Za-z]+$"; + if (!detailToParse.matches(nameRegex)) { + throw new InvalidNameException(); + } + } + + private int getIndexToStore(String flag) throws InvalidFlagException { int indexToStore; switch (flag) { From 0e5075722428f38e6ed6e03f58cbef3e40d13df8 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 20:16:47 +0800 Subject: [PATCH 213/756] Add regex check exception import statements --- src/main/java/seedu/parser/ContactParser.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index 7b8666c715..449165ada8 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -2,7 +2,13 @@ import seedu.contact.DetailType; import seedu.exception.ForbiddenDetailException; +import seedu.exception.InvalidEmailException; import seedu.exception.InvalidFlagException; +import seedu.exception.InvalidGithubUsernameException; +import seedu.exception.InvalidLinkedinUsernameException; +import seedu.exception.InvalidNameException; +import seedu.exception.InvalidTelegramUsernameException; +import seedu.exception.InvalidTwitterUsernameException; import seedu.exception.MissingArgException; import seedu.exception.MissingDetailException; From 9115c5cf9fd8cfb942c336fa72f9ec18af406e90 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 20:18:58 +0800 Subject: [PATCH 214/756] Add throw exceptions for parseDetail method --- src/main/java/seedu/parser/ContactParser.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index 449165ada8..1331ae7734 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -28,7 +28,9 @@ public abstract class ContactParser { public static final String GITHUB_FLAG = "g"; public abstract String[] parseContactDetails(String userInput) throws InvalidFlagException, - MissingArgException, MissingDetailException, ForbiddenDetailException; + MissingArgException, MissingDetailException, ForbiddenDetailException, + InvalidNameException, InvalidGithubUsernameException, InvalidTelegramUsernameException, + InvalidLinkedinUsernameException, InvalidTwitterUsernameException, InvalidEmailException; /** * This method takes in the contactDetails array and populates it with contact details. From cd13019162e400b3f8fa034bcff1214035ae9fbe Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 20:22:55 +0800 Subject: [PATCH 215/756] Add throw exceptions for parseContactDetails method --- src/main/java/seedu/parser/ContactParser.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index 1331ae7734..c825b684f2 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -42,14 +42,15 @@ public abstract String[] parseContactDetails(String userInput) throws InvalidFla * @throws InvalidFlagException If the flag given is not recognised */ public void parseDetail(String[] contactDetails, String detail) - throws InvalidFlagException, MissingDetailException, ForbiddenDetailException { + throws InvalidFlagException, MissingDetailException, ForbiddenDetailException, + InvalidNameException, InvalidGithubUsernameException, InvalidTelegramUsernameException, + InvalidLinkedinUsernameException, InvalidTwitterUsernameException, InvalidEmailException { String[] destructuredDetails = detail.split(" ", NUMBER_OF_DETAILS); //for commands that specify a flag, but do not specify any argument for that flag //IndexOutOfBoundsException should not be thrown as the first if case will be true if (destructuredDetails.length == 1 || destructuredDetails[1].isBlank()) { throw new MissingDetailException(); } - int indexToStore; assert destructuredDetails.length == NUMBER_OF_DETAILS; String flag = destructuredDetails[FLAG_INDEX_IN_DETAILS]; String detailToStore = destructuredDetails[DETAIL_INDEX_IN_DETAILS].trim(); From 46ace487dd56bf5df41af9510849c2f62a14a3e0 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 20:24:14 +0800 Subject: [PATCH 216/756] Add InvalidEmailException.java class --- src/main/java/seedu/exception/InvalidEmailException.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/exception/InvalidEmailException.java b/src/main/java/seedu/exception/InvalidEmailException.java index 0efbc72641..d7d82a67be 100644 --- a/src/main/java/seedu/exception/InvalidEmailException.java +++ b/src/main/java/seedu/exception/InvalidEmailException.java @@ -1,2 +1,4 @@ -package seedu.exception;public class InvalidEmailException { +package seedu.exception; + +public class InvalidEmailException extends Exception{ } From 1e1fa9f07396cc61bc916c0cef364a6d0d140ab0 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 20:24:53 +0800 Subject: [PATCH 217/756] Add import statements for regex exceptions in MainParser.java class --- src/main/java/seedu/parser/MainParser.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index b0d8a09583..8b4cf75543 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -11,7 +11,13 @@ import seedu.contact.DetailType; import seedu.exception.ForbiddenDetailException; +import seedu.exception.InvalidEmailException; import seedu.exception.InvalidFlagException; +import seedu.exception.InvalidGithubUsernameException; +import seedu.exception.InvalidLinkedinUsernameException; +import seedu.exception.InvalidNameException; +import seedu.exception.InvalidTelegramUsernameException; +import seedu.exception.InvalidTwitterUsernameException; import seedu.exception.MissingArgException; import seedu.exception.MissingDetailException; import seedu.exception.MissingNameException; From 3ad26f088018721ad0245fe7fa0683bb884e84e0 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 20:26:34 +0800 Subject: [PATCH 218/756] Update FailedCommandType to add commands for regex exceptions --- src/main/java/seedu/parser/FailedCommandType.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/FailedCommandType.java b/src/main/java/seedu/parser/FailedCommandType.java index 29beb0fab0..f2d868b5c7 100644 --- a/src/main/java/seedu/parser/FailedCommandType.java +++ b/src/main/java/seedu/parser/FailedCommandType.java @@ -3,5 +3,6 @@ public enum FailedCommandType { GENERAL, INVALID_FLAG, MISSING_ARG, MISSING_DETAIL, INVALID_NUM, INVALID_FORMAT, NUM_OUT_OF_BOUND, INVALID_INDEX, MISSING_NAME, - FORBIDDEN_DETAIL; + FORBIDDEN_DETAIL, INVALID_NAME, INVALID_GITHUB_USERNAME, + INVALID_LINKEDIN, INVALID_TELEGRAM, INVALID_MAIL, INVALID_TWITTER; } From d025adef6593f28b01a1dd8f57bdb4c374c5f441 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 20:29:50 +0800 Subject: [PATCH 219/756] Update import statements to include regex exceptions in AddContactParser.java class --- src/main/java/seedu/parser/AddContactParser.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/seedu/parser/AddContactParser.java b/src/main/java/seedu/parser/AddContactParser.java index 535f735a52..91f2962c69 100644 --- a/src/main/java/seedu/parser/AddContactParser.java +++ b/src/main/java/seedu/parser/AddContactParser.java @@ -1,7 +1,13 @@ package seedu.parser; import seedu.exception.ForbiddenDetailException; +import seedu.exception.InvalidEmailException; import seedu.exception.InvalidFlagException; +import seedu.exception.InvalidGithubUsernameException; +import seedu.exception.InvalidLinkedinUsernameException; +import seedu.exception.InvalidNameException; +import seedu.exception.InvalidTelegramUsernameException; +import seedu.exception.InvalidTwitterUsernameException; import seedu.exception.MissingArgException; import seedu.exception.MissingDetailException; From 1c712a1eba3a3a878fe98996cff78a70f9ce0dad Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 20:30:32 +0800 Subject: [PATCH 220/756] Update throw exceptions for parseContactDetails method --- src/main/java/seedu/parser/EditContactParser.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/seedu/parser/EditContactParser.java b/src/main/java/seedu/parser/EditContactParser.java index c2bc0afbc2..3eca5cf222 100644 --- a/src/main/java/seedu/parser/EditContactParser.java +++ b/src/main/java/seedu/parser/EditContactParser.java @@ -1,7 +1,13 @@ package seedu.parser; import seedu.exception.ForbiddenDetailException; +import seedu.exception.InvalidEmailException; import seedu.exception.InvalidFlagException; +import seedu.exception.InvalidGithubUsernameException; +import seedu.exception.InvalidLinkedinUsernameException; +import seedu.exception.InvalidNameException; +import seedu.exception.InvalidTelegramUsernameException; +import seedu.exception.InvalidTwitterUsernameException; import seedu.exception.MissingArgException; import seedu.exception.MissingDetailException; From 42aace78b1f6cddea28ac53f608977eb8ac66753 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 20:31:50 +0800 Subject: [PATCH 221/756] Update import statements to include regex exceptions in EditContactParser.java class --- src/test/java/seedu/parser/EditContactParserTest.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/test/java/seedu/parser/EditContactParserTest.java b/src/test/java/seedu/parser/EditContactParserTest.java index 851fb955a0..5f5839696e 100644 --- a/src/test/java/seedu/parser/EditContactParserTest.java +++ b/src/test/java/seedu/parser/EditContactParserTest.java @@ -3,7 +3,13 @@ import org.junit.jupiter.api.Test; import seedu.exception.ForbiddenDetailException; +import seedu.exception.InvalidEmailException; import seedu.exception.InvalidFlagException; +import seedu.exception.InvalidGithubUsernameException; +import seedu.exception.InvalidLinkedinUsernameException; +import seedu.exception.InvalidNameException; +import seedu.exception.InvalidTelegramUsernameException; +import seedu.exception.InvalidTwitterUsernameException; import seedu.exception.MissingArgException; import seedu.exception.MissingDetailException; import seedu.parser.EditContactParser; From f1a83fe71aecffa03da3abde978fd6641f6e4bb0 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 20:32:08 +0800 Subject: [PATCH 222/756] Update throw exceptions for parseContactDetails method --- src/test/java/seedu/parser/EditContactParserTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/test/java/seedu/parser/EditContactParserTest.java b/src/test/java/seedu/parser/EditContactParserTest.java index 5f5839696e..c436bb62af 100644 --- a/src/test/java/seedu/parser/EditContactParserTest.java +++ b/src/test/java/seedu/parser/EditContactParserTest.java @@ -24,7 +24,9 @@ class EditContactParserTest { @Test void parseContactDetails() throws MissingDetailException, - MissingArgException, InvalidFlagException, ForbiddenDetailException { + MissingArgException, InvalidFlagException, ForbiddenDetailException, InvalidTelegramUsernameException, + InvalidNameException, InvalidLinkedinUsernameException, InvalidGithubUsernameException, + InvalidTwitterUsernameException, InvalidEmailException { String[] expectedResult = {null, "github"}; String testInput = "edit 1 -g github"; String[] actualResult = editContactParser.parseContactDetails(testInput); From 3af098316174a3643ab98e85b437714d027b0064 Mon Sep 17 00:00:00 2001 From: lezong Date: Tue, 12 Oct 2021 20:34:31 +0800 Subject: [PATCH 223/756] make personalContactFile attirbutes for Storage --- src/main/java/seedu/duke/Duke.java | 1 + src/main/java/seedu/storage/Storage.java | 21 ++++++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 69e393c226..d9e58ae73d 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -15,6 +15,7 @@ public class Duke { private Storage storage; private MainParser parser; private ContactList contactList; + private String personalContactFilePath; public Duke(String contactFilePath) { this.textUi = new TextUi(); diff --git a/src/main/java/seedu/storage/Storage.java b/src/main/java/seedu/storage/Storage.java index f194550baf..d5331f0c6e 100644 --- a/src/main/java/seedu/storage/Storage.java +++ b/src/main/java/seedu/storage/Storage.java @@ -10,11 +10,30 @@ public class Storage { private final String contactFilePath; private final File contactFile; + private final String personalContactFilePath; + private final File personalContactFile; public static final String SEPARATOR = ","; - public Storage(String contactFilePath) { + public Storage(String contactFilePath, String personalContactFilePath) { this.contactFilePath = contactFilePath; this.contactFile = new File(contactFilePath); + this.personalContactFilePath = personalContactFilePath; + this.personalContactFile = new File(personalContactFilePath); + } + + private boolean hasExistingPersonalContactFile() throws FileErrorException { + try { + if (!contactFile.exists()) { + contactFile.getParentFile().mkdirs(); + } + if (contactFile.createNewFile()) { + TextUi.createNewContactFileMessage(contactFilePath); + return false; + } + } catch (IOException e) { + throw new FileErrorException(); + } + return true; } private boolean hasExistingContactFile() throws FileErrorException { From 35dd9199f1658bbb4e7672bb4d21a2423668c41c Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 20:35:12 +0800 Subject: [PATCH 224/756] Update catch statements for added regex exceptions --- src/main/java/seedu/parser/MainParser.java | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 8b4cf75543..f2881dd631 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -91,6 +91,18 @@ private Command parseAddContact(String userInput) { return new FailedCommand(FailedCommandType.MISSING_DETAIL); } catch (ForbiddenDetailException e) { return new FailedCommand(FailedCommandType.FORBIDDEN_DETAIL); + } catch (InvalidNameException e) { + return new FailedCommand(FailedCommandType.INVALID_NAME); + } catch (InvalidGithubUsernameException e) { + return new FailedCommand(FailedCommandType.INVALID_GITHUB_USERNAME); + } catch (InvalidEmailException e) { + return new FailedCommand(FailedCommandType.INVALID_MAIL); + } catch (InvalidTelegramUsernameException e) { + return new FailedCommand(FailedCommandType.INVALID_TELEGRAM); + } catch (InvalidTwitterUsernameException e) { + return new FailedCommand(FailedCommandType.INVALID_TWITTER); + } catch (InvalidLinkedinUsernameException e) { + return new FailedCommand(FailedCommandType.INVALID_LINKEDIN); } } @@ -111,6 +123,18 @@ private Command parseEditContact(String userInput) { // userInput is raw user in return new FailedCommand(FailedCommandType.MISSING_DETAIL); } catch (ForbiddenDetailException e) { return new FailedCommand(FailedCommandType.FORBIDDEN_DETAIL); + } catch (InvalidNameException e) { + return new FailedCommand(FailedCommandType.INVALID_NAME); + } catch (InvalidGithubUsernameException e) { + return new FailedCommand(FailedCommandType.INVALID_GITHUB_USERNAME); + } catch (InvalidEmailException e) { + return new FailedCommand(FailedCommandType.INVALID_MAIL); + } catch (InvalidTelegramUsernameException e) { + return new FailedCommand(FailedCommandType.INVALID_TELEGRAM); + } catch (InvalidTwitterUsernameException e) { + return new FailedCommand(FailedCommandType.INVALID_TWITTER); + } catch (InvalidLinkedinUsernameException e) { + return new FailedCommand(FailedCommandType.INVALID_LINKEDIN); } } From cf6650ffe9822a3312fdf1cb39eb6cd3e529afd9 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 20:39:19 +0800 Subject: [PATCH 225/756] Update failed commands to add regex exception handling --- src/main/java/seedu/command/FailedCommand.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/main/java/seedu/command/FailedCommand.java b/src/main/java/seedu/command/FailedCommand.java index 4a46a7c58c..65ab2349f7 100644 --- a/src/main/java/seedu/command/FailedCommand.java +++ b/src/main/java/seedu/command/FailedCommand.java @@ -37,6 +37,24 @@ public void execute() { case INVALID_FORMAT: TextUi.invalidFormatMessage(); break; + case INVALID_NAME: + TextUi.invalidNameInput(); + break; + case INVALID_GITHUB_USERNAME: + TextUi.invalidGithubUsernameInput(); + break; + case INVALID_TELEGRAM: + TextUi.invalidTelegramUsernameInput(); + break; + case INVALID_LINKEDIN: + TextUi.invalidLinkedinInput(); + break; + case INVALID_MAIL: + TextUi.invalidEmailInput(); + break; + case INVALID_TWITTER: + TextUi.invalidTwitterUsernameInput(); + break; case NUM_OUT_OF_BOUND: TextUi.numOutOfRangeMessage(contactList.getListSize() - 1); break; From 974a5ad87e0f30907b87f5e5cc9f8a8b9ad18510 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 20:40:49 +0800 Subject: [PATCH 226/756] Update throw exceptions for contact parser --- src/main/java/seedu/parser/AddContactParser.java | 4 +++- src/main/java/seedu/parser/EditContactParser.java | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/parser/AddContactParser.java b/src/main/java/seedu/parser/AddContactParser.java index 91f2962c69..2b5038b035 100644 --- a/src/main/java/seedu/parser/AddContactParser.java +++ b/src/main/java/seedu/parser/AddContactParser.java @@ -25,7 +25,9 @@ public class AddContactParser extends ContactParser { * @throws InvalidFlagException If the flag given is not recognised */ public String[] parseContactDetails(String userInput) throws InvalidFlagException, MissingArgException, - MissingDetailException, ForbiddenDetailException { + MissingDetailException, ForbiddenDetailException, InvalidNameException, InvalidGithubUsernameException, + InvalidTelegramUsernameException, InvalidLinkedinUsernameException, InvalidTwitterUsernameException, + InvalidEmailException { String[] contactDetails = new String[NUMBER_OF_DETAILS]; String[] destructuredInputs = userInput.split(DETAIL_SEPARATOR); if (destructuredInputs.length == 1) { diff --git a/src/main/java/seedu/parser/EditContactParser.java b/src/main/java/seedu/parser/EditContactParser.java index 3eca5cf222..22a34c18f1 100644 --- a/src/main/java/seedu/parser/EditContactParser.java +++ b/src/main/java/seedu/parser/EditContactParser.java @@ -15,7 +15,9 @@ public class EditContactParser extends ContactParser { public static final String BUFFER = " "; public String[] parseContactDetails(String userInput) - throws InvalidFlagException, MissingDetailException, MissingArgException, ForbiddenDetailException { + throws InvalidFlagException, MissingDetailException, MissingArgException, ForbiddenDetailException, + InvalidNameException, InvalidGithubUsernameException, InvalidTelegramUsernameException, + InvalidLinkedinUsernameException, InvalidTwitterUsernameException, InvalidEmailException { String[] inputDetails = userInput.split(" ", NUMBER_OF_EDIT_ARGS); if (inputDetails.length < 3) { //if arguments are missing e.g. edit 2 From c7c6984ee1c53ed82e8738e98b1fe4c218eae1c1 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 20:42:36 +0800 Subject: [PATCH 227/756] Update exceptions in test class --- .../seedu/parser/AddContactParserTest.java | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/test/java/seedu/parser/AddContactParserTest.java b/src/test/java/seedu/parser/AddContactParserTest.java index 86cc3f22c8..436bc016d8 100644 --- a/src/test/java/seedu/parser/AddContactParserTest.java +++ b/src/test/java/seedu/parser/AddContactParserTest.java @@ -4,7 +4,13 @@ import org.junit.jupiter.api.Test; import seedu.contact.DetailType; import seedu.exception.ForbiddenDetailException; +import seedu.exception.InvalidEmailException; import seedu.exception.InvalidFlagException; +import seedu.exception.InvalidGithubUsernameException; +import seedu.exception.InvalidLinkedinUsernameException; +import seedu.exception.InvalidNameException; +import seedu.exception.InvalidTelegramUsernameException; +import seedu.exception.InvalidTwitterUsernameException; import seedu.exception.MissingArgException; import seedu.exception.MissingDetailException; @@ -30,7 +36,9 @@ public void setUp() { @Test void parseContactDetails_inputsWithIrregularSpacing_expectCorrectDetails() throws InvalidFlagException, - MissingDetailException, MissingArgException, ForbiddenDetailException { + MissingDetailException, MissingArgException, ForbiddenDetailException, InvalidTelegramUsernameException, + InvalidNameException, InvalidLinkedinUsernameException, InvalidGithubUsernameException, + InvalidTwitterUsernameException, InvalidEmailException { inputUserInput = "add -n andre -g ng-andre "; actualOutput = addContactParser.parseContactDetails(inputUserInput); expectedOutput = new String[]{"andre", "ng-andre"}; @@ -78,7 +86,9 @@ void parseDetail_invalidFlagUsed_expectException() { @Test void parseDetail_inputsWithTrailingSpaces_expectNewContactDetail() throws InvalidFlagException, - MissingDetailException, ForbiddenDetailException { + MissingDetailException, ForbiddenDetailException, InvalidTelegramUsernameException, + InvalidNameException, InvalidLinkedinUsernameException, InvalidGithubUsernameException, + InvalidTwitterUsernameException, InvalidEmailException { inputDetail = "n andre"; addContactParser.parseDetail(inputContactDetails, inputDetail); assertEquals("andre", inputContactDetails[DetailType.NAME.getIndex()]); @@ -86,7 +96,9 @@ void parseDetail_inputsWithTrailingSpaces_expectNewContactDetail() throws Invali @Test void parseDetail_inputsWithSpaceInDetail_expectNewContactDetail() throws InvalidFlagException, - MissingDetailException, ForbiddenDetailException { + MissingDetailException, ForbiddenDetailException, InvalidTelegramUsernameException, + InvalidNameException, InvalidLinkedinUsernameException, InvalidGithubUsernameException, + InvalidTwitterUsernameException, InvalidEmailException { inputDetail = "n Marcus Bory"; addContactParser.parseDetail(inputContactDetails, inputDetail); assertEquals("Marcus Bory", inputContactDetails[DetailType.NAME.getIndex()]); From e5d20466e8feeee71ce52d08f787d982d6cfa35e Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 20:43:50 +0800 Subject: [PATCH 228/756] Add method for invalid name message --- src/main/java/seedu/ui/TextUi.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 297174c5d1..141323c2a3 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -145,6 +145,11 @@ public static void invalidFormatMessage() { printDoubleLineMessage(message); } + public static void invalidNameInput() { + String message = "The name is not correctly formatted"; + printDoubleLineMessage(message); + } + public static void missingNameMessage() { String message = "There are missing details.\n" + "Please specify a name when creating a contact with the flag -n"; From 30d5d62895717805ce4332a20eca39ab404b9356 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 20:44:06 +0800 Subject: [PATCH 229/756] Add method for invalid github username message --- src/main/java/seedu/ui/TextUi.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 141323c2a3..ef24cf9bac 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -150,6 +150,11 @@ public static void invalidNameInput() { printDoubleLineMessage(message); } + public static void invalidGithubUsernameInput() { + String message = "The github username is not correctly formatted"; + printDoubleLineMessage(message); + } + public static void missingNameMessage() { String message = "There are missing details.\n" + "Please specify a name when creating a contact with the flag -n"; From eb279679f3bde06fbe6862df2a2db0ae8bd07d0a Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 20:44:26 +0800 Subject: [PATCH 230/756] Add method for invalid telegram username message --- src/main/java/seedu/ui/TextUi.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index ef24cf9bac..fbac2c2d40 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -155,6 +155,11 @@ public static void invalidGithubUsernameInput() { printDoubleLineMessage(message); } + public static void invalidTelegramUsernameInput() { + String message = "The telegram username is not correctly formatted"; + printDoubleLineMessage(message); + } + public static void missingNameMessage() { String message = "There are missing details.\n" + "Please specify a name when creating a contact with the flag -n"; From 9f6ce2fc228e33742db361cb5df0b4c039fc17e8 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 20:44:44 +0800 Subject: [PATCH 231/756] Add method for invalid twitter username message --- src/main/java/seedu/ui/TextUi.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index fbac2c2d40..da8dcba12d 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -160,6 +160,11 @@ public static void invalidTelegramUsernameInput() { printDoubleLineMessage(message); } + public static void invalidTwitterUsernameInput() { + String message = "The twitter username is not correctly formatted"; + printDoubleLineMessage(message); + } + public static void missingNameMessage() { String message = "There are missing details.\n" + "Please specify a name when creating a contact with the flag -n"; From 54ac5433f86ec1beea0d4866b2322cb59f09ebf2 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 20:45:01 +0800 Subject: [PATCH 232/756] Add method for invalid email message --- src/main/java/seedu/ui/TextUi.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index da8dcba12d..74d2033453 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -165,6 +165,11 @@ public static void invalidTwitterUsernameInput() { printDoubleLineMessage(message); } + public static void invalidEmailInput() { + String message = "The email id is not correctly formatted"; + printDoubleLineMessage(message); + } + public static void missingNameMessage() { String message = "There are missing details.\n" + "Please specify a name when creating a contact with the flag -n"; From 19512fec3fe41161f4f161ecb78f105a0580ba5a Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 20:45:12 +0800 Subject: [PATCH 233/756] Add method for invalid linkedin username message --- src/main/java/seedu/ui/TextUi.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 74d2033453..11e0ea35c4 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -170,6 +170,11 @@ public static void invalidEmailInput() { printDoubleLineMessage(message); } + public static void invalidLinkedinInput() { + String message = "The linkedin username is not correctly formatted"; + printDoubleLineMessage(message); + } + public static void missingNameMessage() { String message = "There are missing details.\n" + "Please specify a name when creating a contact with the flag -n"; From f3e8ced415708507a81b1a1e4d9df2384da892dc Mon Sep 17 00:00:00 2001 From: lezong Date: Tue, 12 Oct 2021 20:53:52 +0800 Subject: [PATCH 234/756] abstracted parsing of indexes in View Command to ParseIndex --- .../seedu/command/DeleteContactCommand.java | 16 +++++++--------- src/main/java/seedu/command/ViewCommand.java | 13 +++++++------ .../java/seedu/parser/EditContactParser.java | 9 --------- src/main/java/seedu/parser/MainParser.java | 19 ++++++++++--------- 4 files changed, 24 insertions(+), 33 deletions(-) diff --git a/src/main/java/seedu/command/DeleteContactCommand.java b/src/main/java/seedu/command/DeleteContactCommand.java index ff35ccde59..93d7b4e9ab 100644 --- a/src/main/java/seedu/command/DeleteContactCommand.java +++ b/src/main/java/seedu/command/DeleteContactCommand.java @@ -1,29 +1,27 @@ package seedu.command; import seedu.contact.Contact; -import seedu.parser.FailedCommandType; import seedu.parser.IndexParser; import seedu.ui.TextUi; import seedu.ui.ExceptionTextUi; -import seedu.command.FailedCommand; + public class DeleteContactCommand extends Command { - private final int deletedIndex; - private final String confirmMessage = ""; + private final int contactIndex; public DeleteContactCommand(int deletedIndex) { - this.deletedIndex = deletedIndex; + this.contactIndex = deletedIndex; } public int getDeletedIndex() { - return deletedIndex; + return contactIndex; } private void deleteOnConfirmation(Contact deletedContact) { // ask for confirmation to delete from user - String userDeleteConfirmation = TextUi.getUserDeleteConfirmation(deletedContact, deletedIndex); + String userDeleteConfirmation = TextUi.getUserDeleteConfirmation(deletedContact, contactIndex); if (userDeleteConfirmation.equalsIgnoreCase("y")) { - this.contactList.deleteContact(deletedIndex); + this.contactList.deleteContact(contactIndex); TextUi.deleteContactMessage(deletedContact.getName(), contactList.getListSize()); } else { TextUi.cancelDeleteContactMessage(); @@ -33,7 +31,7 @@ private void deleteOnConfirmation(Contact deletedContact) { public void execute() { try { // throws IndexOutOfBoundsException if index is outside of the range - Contact deletedContact = IndexParser.getContactFromIndex(deletedIndex, contactList); + Contact deletedContact = IndexParser.getContactFromIndex(contactIndex, contactList); deleteOnConfirmation(deletedContact); } catch (IndexOutOfBoundsException e) { ExceptionTextUi.numOutOfRangeMessage(contactList.getListSize()); diff --git a/src/main/java/seedu/command/ViewCommand.java b/src/main/java/seedu/command/ViewCommand.java index e21766e36c..d88e736f6b 100644 --- a/src/main/java/seedu/command/ViewCommand.java +++ b/src/main/java/seedu/command/ViewCommand.java @@ -1,24 +1,25 @@ package seedu.command; import seedu.contact.Contact; +import seedu.parser.IndexParser; import seedu.ui.TextUi; import seedu.ui.ExceptionTextUi; public class ViewCommand extends Command { - private final int index; + private final int contactIndex; - public ViewCommand(int index) { - this.index = index; + public ViewCommand(int contactIndex) { + this.contactIndex = contactIndex; } public int getIndex() { - return index; + return contactIndex; } public void execute() { try { - Contact viewingContact = contactList.getContactAtIndex(index); - TextUi.viewContactMessage(viewingContact, index); + Contact viewingContact = IndexParser.getContactFromIndex(contactIndex, contactList); + TextUi.viewContactMessage(viewingContact, contactIndex); } catch (IndexOutOfBoundsException e) { ExceptionTextUi.numOutOfRangeMessage(contactList.getListSize()); } diff --git a/src/main/java/seedu/parser/EditContactParser.java b/src/main/java/seedu/parser/EditContactParser.java index e13f865bd2..440779ffed 100644 --- a/src/main/java/seedu/parser/EditContactParser.java +++ b/src/main/java/seedu/parser/EditContactParser.java @@ -30,13 +30,4 @@ public String[] parseContactDetails(String userInput) return contactDetails; } - public int getIndex(String input) throws MissingArgException { - String[] destructuredInputs = input.split(" ", NUMBER_OF_EDIT_ARGS); - if (destructuredInputs.length < NUMBER_OF_EDIT_ARGS) { - //if arguments are missing e.g. edit 2 - throw new MissingArgException(); - } - assert (destructuredInputs.length == NUMBER_OF_EDIT_ARGS); - return Integer.parseInt(destructuredInputs[EDIT_USER_INDEX]); - } } diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index c2be575e24..76683642df 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -16,14 +16,16 @@ import seedu.exception.MissingDetailException; import seedu.exception.MissingNameException; +import javax.swing.text.View; + import static seedu.parser.ContactParser.NUMBER_OF_FIELDS; public class MainParser { private static final String ADD_CONTACT_COMD = "add"; private static final String EDIT_CONTACT_COMD = "edit"; private static final String DELETE_CONTACT_COMD = "rm"; + private static final String VIEW_CONTACT_COMD = "view"; private static final String EXIT_COMD = "exit"; - private static final String VIEW_COMD = "view"; private static final String LIST_COMD = "list"; private static final int COMD_WORD_INDEX = 0; @@ -47,12 +49,12 @@ public Command parseCommand(String userInput) { case DELETE_CONTACT_COMD: command = parseDeleteContact(userInput); break; + case VIEW_CONTACT_COMD: + command = parseViewContact(userInput); + break; case EXIT_COMD: command = new ExitCommand(); break; - case VIEW_COMD: - command = parseViewContact(userInput); - break; case LIST_COMD: command = new ListContactsCommand(); break; @@ -117,12 +119,11 @@ private Command parseEditContact(String userInput) { // userInput is raw user in } private Command parseViewContact(String userInput) { - String[] destructuredInputs = userInput.split(" ", ISOLATE_COMD_WORD); - if (destructuredInputs.length == 1) { - return new FailedCommand(FailedCommandType.MISSING_ARG); - } try { - return new ViewCommand(Integer.parseInt(destructuredInputs[1].trim())); + int viewedIndex = IndexParser.getIndexFromInput(userInput, VIEW_CONTACT_COMD); + return new ViewCommand(viewedIndex); + } catch (MissingArgException e) { + return new FailedCommand(FailedCommandType.MISSING_ARG); } catch (NumberFormatException e) { return new FailedCommand(FailedCommandType.INVALID_INDEX); } From 1b479f13370623c8b5292f8adf5a67c63e57e300 Mon Sep 17 00:00:00 2001 From: lezong Date: Tue, 12 Oct 2021 20:58:46 +0800 Subject: [PATCH 235/756] Update JUnit tests to allow multiple indexes in View Command and Delete Command --- .../java/seedu/parser/MainParserTest.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/test/java/seedu/parser/MainParserTest.java b/src/test/java/seedu/parser/MainParserTest.java index 42ac463ca2..dfa1992803 100644 --- a/src/test/java/seedu/parser/MainParserTest.java +++ b/src/test/java/seedu/parser/MainParserTest.java @@ -53,8 +53,8 @@ public void parseDeleteCommand_validIndex_expectDeleteContactIndexMatch() { @Test public void parseDeleteCommand_multipleIndexes_expectDeleteContactIndexMatch() { - testUserInput = "rm 1 2"; - testUserInput = "rm " + testIndex; + int testIndex = 1; + testUserInput = String.format("rm %d %d", testIndex, 2); final DeleteContactCommand testResultCommand = getParsedCommand(testUserInput, DeleteContactCommand.class); assertEquals(testIndex, testResultCommand.getDeletedIndex()); } @@ -147,6 +147,14 @@ public void parseViewCommand_validIndex_expectViewContactIndexMatch() { assertEquals(testIndex,testResultCommand.getIndex()); } + @Test + public void parseViewCommand_multipleIndexes_expectViewContactIndexMatch() { + int testIndex = 1; + testUserInput = String.format("view %d %d", testIndex, 2); + final ViewCommand testResultCommand = getParsedCommand(testUserInput, ViewCommand.class); + assertEquals(testIndex,testResultCommand.getIndex()); + } + @Test public void parseViewCommand_invalidIndex_expectException() { testIndex = 99999; @@ -178,13 +186,6 @@ public void parseViewCommand_invalidInput_expectFailedCommandType() { assertEquals(expectedFailedCommandType, actualFailedCommand.getType()); } - @Test - public void parseViewCommand_invalidInputFormat_expectFailedCommandType() { - testUserInput = "view 1 2"; - FailedCommandType expectedFailedCommandType = FailedCommandType.INVALID_INDEX; - final FailedCommand actualFailedCommand = getParsedCommand(testUserInput, FailedCommand.class); - assertEquals(expectedFailedCommandType, actualFailedCommand.getType()); - } @Test public void parseAddCommand_missingName_expectFailedCommand() { From d1f8f7a22fc92bd0cfa03c77d1cb6cd3ce9249a3 Mon Sep 17 00:00:00 2001 From: lezong Date: Tue, 12 Oct 2021 21:01:57 +0800 Subject: [PATCH 236/756] Add a test input into input.txt --- .../{ViewCommand.java => ViewContactCommand.java} | 4 ++-- src/main/java/seedu/parser/MainParser.java | 6 ++---- src/test/java/seedu/parser/MainParserTest.java | 10 +++++----- text-ui-test/input.txt | 2 +- 4 files changed, 10 insertions(+), 12 deletions(-) rename src/main/java/seedu/command/{ViewCommand.java => ViewContactCommand.java} (86%) diff --git a/src/main/java/seedu/command/ViewCommand.java b/src/main/java/seedu/command/ViewContactCommand.java similarity index 86% rename from src/main/java/seedu/command/ViewCommand.java rename to src/main/java/seedu/command/ViewContactCommand.java index d88e736f6b..1ab2aae171 100644 --- a/src/main/java/seedu/command/ViewCommand.java +++ b/src/main/java/seedu/command/ViewContactCommand.java @@ -5,10 +5,10 @@ import seedu.ui.TextUi; import seedu.ui.ExceptionTextUi; -public class ViewCommand extends Command { +public class ViewContactCommand extends Command { private final int contactIndex; - public ViewCommand(int contactIndex) { + public ViewContactCommand(int contactIndex) { this.contactIndex = contactIndex; } diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 76683642df..a5d474e9c9 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -4,7 +4,7 @@ import seedu.command.EditContactCommand; import seedu.command.DeleteContactCommand; import seedu.command.Command; -import seedu.command.ViewCommand; +import seedu.command.ViewContactCommand; import seedu.command.FailedCommand; import seedu.command.ExitCommand; import seedu.command.ListContactsCommand; @@ -16,8 +16,6 @@ import seedu.exception.MissingDetailException; import seedu.exception.MissingNameException; -import javax.swing.text.View; - import static seedu.parser.ContactParser.NUMBER_OF_FIELDS; public class MainParser { @@ -121,7 +119,7 @@ private Command parseEditContact(String userInput) { // userInput is raw user in private Command parseViewContact(String userInput) { try { int viewedIndex = IndexParser.getIndexFromInput(userInput, VIEW_CONTACT_COMD); - return new ViewCommand(viewedIndex); + return new ViewContactCommand(viewedIndex); } catch (MissingArgException e) { return new FailedCommand(FailedCommandType.MISSING_ARG); } catch (NumberFormatException e) { diff --git a/src/test/java/seedu/parser/MainParserTest.java b/src/test/java/seedu/parser/MainParserTest.java index dfa1992803..d592b18f07 100644 --- a/src/test/java/seedu/parser/MainParserTest.java +++ b/src/test/java/seedu/parser/MainParserTest.java @@ -7,7 +7,7 @@ import seedu.command.Command; import seedu.command.DeleteContactCommand; import seedu.command.FailedCommand; -import seedu.command.ViewCommand; +import seedu.command.ViewContactCommand; import seedu.contact.ContactList; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -143,7 +143,7 @@ public void parseAddCommand_validInputs_expectAddContactCommand() { public void parseViewCommand_validIndex_expectViewContactIndexMatch() { final int testIndex = 1; final String testUserInput = "view " + testIndex; - final ViewCommand testResultCommand = getParsedCommand(testUserInput, ViewCommand.class); + final ViewContactCommand testResultCommand = getParsedCommand(testUserInput, ViewContactCommand.class); assertEquals(testIndex,testResultCommand.getIndex()); } @@ -151,14 +151,14 @@ public void parseViewCommand_validIndex_expectViewContactIndexMatch() { public void parseViewCommand_multipleIndexes_expectViewContactIndexMatch() { int testIndex = 1; testUserInput = String.format("view %d %d", testIndex, 2); - final ViewCommand testResultCommand = getParsedCommand(testUserInput, ViewCommand.class); + final ViewContactCommand testResultCommand = getParsedCommand(testUserInput, ViewContactCommand.class); assertEquals(testIndex,testResultCommand.getIndex()); } @Test public void parseViewCommand_invalidIndex_expectException() { testIndex = 99999; - final ViewCommand testResultCommand = new ViewCommand(testIndex); + final ViewContactCommand testResultCommand = new ViewContactCommand(testIndex); assertThrows(NullPointerException.class, testResultCommand::execute); } @@ -166,7 +166,7 @@ public void parseViewCommand_invalidIndex_expectException() { public void parseViewCommand_validIndexWithSpaces_expectViewContactIndexMatch() { testIndex = 1; testUserInput = "view " + testIndex; - final ViewCommand testResultCommand = getParsedCommand(testUserInput, ViewCommand.class); + final ViewContactCommand testResultCommand = getParsedCommand(testUserInput, ViewContactCommand.class); assertEquals(testIndex, testResultCommand.getIndex()); } diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index e875f47871..4648dac51a 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -24,7 +24,7 @@ y rm 0 y add -p -f -view 2 +view 2 1 n andre f facebook n From b1858b2f2028b47721e1e872273c6c4c0ec4f137 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 21:49:02 +0800 Subject: [PATCH 237/756] Move regex exception messages --- src/main/java/seedu/ui/ExceptionTextUi.java | 30 +++++++++++++++++++++ src/main/java/seedu/ui/TextUi.java | 30 --------------------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index 04becf3e3a..18de6e8d87 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -106,4 +106,34 @@ public static void forbiddenDetailMessage() { + "ConTech is unable to process it"; printDoubleLineMessage(message); } + + public static void invalidNameInput() { + String message = "The name is not correctly formatted"; + printDoubleLineMessage(message); + } + + public static void invalidGithubUsernameInput() { + String message = "The github username is not correctly formatted"; + printDoubleLineMessage(message); + } + + public static void invalidTelegramUsernameInput() { + String message = "The telegram username is not correctly formatted"; + printDoubleLineMessage(message); + } + + public static void invalidTwitterUsernameInput() { + String message = "The twitter username is not correctly formatted"; + printDoubleLineMessage(message); + } + + public static void invalidEmailInput() { + String message = "The email id is not correctly formatted"; + printDoubleLineMessage(message); + } + + public static void invalidLinkedinInput() { + String message = "The linkedin username is not correctly formatted"; + printDoubleLineMessage(message); + } } diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 8de3de9354..4220fcf15a 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -126,34 +126,4 @@ public static void exitMessage() { String message = "ConTech will now shutdown.\n" + "We hope you have enjoyed using it."; printDoubleLineMessage(message); } - - public static void invalidNameInput() { - String message = "The name is not correctly formatted"; - printDoubleLineMessage(message); - } - - public static void invalidGithubUsernameInput() { - String message = "The github username is not correctly formatted"; - printDoubleLineMessage(message); - } - - public static void invalidTelegramUsernameInput() { - String message = "The telegram username is not correctly formatted"; - printDoubleLineMessage(message); - } - - public static void invalidTwitterUsernameInput() { - String message = "The twitter username is not correctly formatted"; - printDoubleLineMessage(message); - } - - public static void invalidEmailInput() { - String message = "The email id is not correctly formatted"; - printDoubleLineMessage(message); - } - - public static void invalidLinkedinInput() { - String message = "The linkedin username is not correctly formatted"; - printDoubleLineMessage(message); - } } From 972871c7523953f8e20849a130cffdb0aaa78181 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 21:49:19 +0800 Subject: [PATCH 238/756] Update path for moved methods --- src/main/java/seedu/command/FailedCommand.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/main/java/seedu/command/FailedCommand.java b/src/main/java/seedu/command/FailedCommand.java index b9bf3bdf28..64e331a018 100644 --- a/src/main/java/seedu/command/FailedCommand.java +++ b/src/main/java/seedu/command/FailedCommand.java @@ -1,7 +1,6 @@ package seedu.command; import seedu.parser.FailedCommandType; -import seedu.ui.TextUi; import seedu.ui.ExceptionTextUi; public class FailedCommand extends Command { @@ -39,22 +38,22 @@ public void execute() { ExceptionTextUi.invalidFormatMessage(); break; case INVALID_NAME: - TextUi.invalidNameInput(); + ExceptionTextUi.invalidNameInput(); break; case INVALID_GITHUB_USERNAME: - TextUi.invalidGithubUsernameInput(); + ExceptionTextUi.invalidGithubUsernameInput(); break; case INVALID_TELEGRAM: - TextUi.invalidTelegramUsernameInput(); + ExceptionTextUi.invalidTelegramUsernameInput(); break; case INVALID_LINKEDIN: - TextUi.invalidLinkedinInput(); + ExceptionTextUi.invalidLinkedinInput(); break; case INVALID_MAIL: - TextUi.invalidEmailInput(); + ExceptionTextUi.invalidEmailInput(); break; case INVALID_TWITTER: - TextUi.invalidTwitterUsernameInput(); + ExceptionTextUi.invalidTwitterUsernameInput(); break; case NUM_OUT_OF_BOUND: ExceptionTextUi.numOutOfRangeMessage(contactList.getListSize() - 1); From 2cc8d2fc5be1702e03c5083a61b6b970afba4267 Mon Sep 17 00:00:00 2001 From: lezong Date: Tue, 12 Oct 2021 22:11:31 +0800 Subject: [PATCH 239/756] add personal contact file --- src/main/java/seedu/duke/Duke.java | 7 ++-- .../java/seedu/storage/ContactsDecoder.java | 33 +++++++++++++++++++ src/main/java/seedu/storage/Storage.java | 16 ++++++--- 3 files changed, 49 insertions(+), 7 deletions(-) diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index d9e58ae73d..0a35d0e30c 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -16,11 +16,12 @@ public class Duke { private MainParser parser; private ContactList contactList; private String personalContactFilePath; + private - public Duke(String contactFilePath) { + public Duke(String contactFilePath, String personalContactFilePath) { this.textUi = new TextUi(); this.contactFilePath = contactFilePath; - this.storage = new Storage(contactFilePath); + this.storage = new Storage(contactFilePath, personalContactFilePath); this.parser = new MainParser(); try { this.contactList = storage.loadExistingContacts(); @@ -52,6 +53,6 @@ private void runCommandProcedure(Command command) { * Main entry-point for the java.duke.Duke application. */ public static void main(String[] args) { - new Duke("data/contacts.txt").runConTech(); + new Duke("data/contacts.txt", "data/me.txt").runConTech(); } } diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index b615e39042..82be53229c 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -28,6 +28,39 @@ public static ContactList readContacts(File contactFile) throws FileErrorExcepti return updatedContactList; } + public static Contact readPersonalContact(File contactFile) throws FileErrorException { + Contact personalContact = new Contact(null,null,null,null,null,null); + try { + Scanner fileScanner = new Scanner(contactFile); + if (fileScanner.hasNext()) { + String contactText = fileScanner.nextLine(); + personalContact = decodePersonalContact(contactText, personalContact); + } + } catch (FileNotFoundException e) { + throw new FileErrorException(); + } + return personalContact; + } + + private static Contact decodePersonalContact(String contactText, Contact contact) { + Contact personalContact = contact; + String[] destructuredInputs = contactText.split(SEPARATOR); + assert destructuredInputs.length > 0; + try { + String contactName = destructuredInputs[DetailType.NAME.getIndex()]; + String contactGithub = destructuredInputs[DetailType.GITHUB.getIndex()]; + String contactLinkedin = destructuredInputs[DetailType.LINKEDIN.getIndex()]; + String contactTelegram = destructuredInputs[DetailType.TELEGRAM.getIndex()]; + String contactTwitter = destructuredInputs[DetailType.TWITTER.getIndex()]; + String contactEmail = destructuredInputs[DetailType.EMAIL.getIndex()]; + personalContact = new Contact(contactName, contactGithub, contactLinkedin, contactTelegram, + contactTwitter, contactEmail); + } catch (IndexOutOfBoundsException e) { + ExceptionTextUi.corruptLineMessage(contactText); + } + return personalContact; + } + private static void decodeContact(ContactList contactList, String contactText) { String[] destructuredInputs = contactText.split(SEPARATOR); String[] compiledDetails = new String[NUMBER_OF_FIELDS]; diff --git a/src/main/java/seedu/storage/Storage.java b/src/main/java/seedu/storage/Storage.java index d5331f0c6e..6be7511cd2 100644 --- a/src/main/java/seedu/storage/Storage.java +++ b/src/main/java/seedu/storage/Storage.java @@ -1,5 +1,6 @@ package seedu.storage; +import seedu.contact.Contact; import seedu.contact.ContactList; import seedu.exception.FileErrorException; import seedu.ui.TextUi; @@ -23,11 +24,11 @@ public Storage(String contactFilePath, String personalContactFilePath) { private boolean hasExistingPersonalContactFile() throws FileErrorException { try { - if (!contactFile.exists()) { - contactFile.getParentFile().mkdirs(); + if (!personalContactFile.exists()) { + personalContactFile.getParentFile().mkdirs(); } - if (contactFile.createNewFile()) { - TextUi.createNewContactFileMessage(contactFilePath); + if (personalContactFile.createNewFile()) { + TextUi.createNewContactFileMessage(personalContactFilePath); return false; } } catch (IOException e) { @@ -57,4 +58,11 @@ public ContactList loadExistingContacts() throws FileErrorException { } return ContactsDecoder.readContacts(contactFile); } + + public Contact loadExistingPersonalContact() throws FileErrorException { + if (!hasExistingPersonalContactFile()) { + return new Contact; + } + + } } From 18c93fe2676d264d5dd2d54b25a644a2d77afe79 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 22:17:36 +0800 Subject: [PATCH 240/756] Update ContactParser.java --- src/main/java/seedu/parser/ContactParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index 7457f26432..2bad1cb1bc 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -134,7 +134,7 @@ private void checkGithubUsernameRegex(String detailToParse) throws InvalidGithub //Github username cannot have multiple consecutive hyphens. //Github username cannot begin or end with a hyphen. //Maximum is 39 characters. - String githubUsernameRegex = "^[a-z\\d](?:[a-z\\d]|-(?=[a-z\\d])){0,38}$"; + String githubUsernameRegex = "^[a-z\\d](?:[a-z\\d]|-(?=[a-z\\d])){0,39}$"; if (!detailToParse.matches(githubUsernameRegex)) { throw new InvalidGithubUsernameException(); } From d9cb810c6135156025a89ac66f2ee7ae5d562694 Mon Sep 17 00:00:00 2001 From: lezong Date: Tue, 12 Oct 2021 22:18:32 +0800 Subject: [PATCH 241/756] Use shared contactDecoder --- src/main/java/seedu/duke/Duke.java | 4 ++- .../java/seedu/storage/ContactsDecoder.java | 32 ------------------- src/main/java/seedu/storage/Storage.java | 6 ++-- 3 files changed, 7 insertions(+), 35 deletions(-) diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 0a35d0e30c..f779ed6b76 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -1,6 +1,7 @@ package seedu.duke; import seedu.command.Command; +import seedu.contact.Contact; import seedu.contact.ContactList; import seedu.exception.FileErrorException; import seedu.parser.MainParser; @@ -16,7 +17,7 @@ public class Duke { private MainParser parser; private ContactList contactList; private String personalContactFilePath; - private + private Contact personalContact; public Duke(String contactFilePath, String personalContactFilePath) { this.textUi = new TextUi(); @@ -25,6 +26,7 @@ public Duke(String contactFilePath, String personalContactFilePath) { this.parser = new MainParser(); try { this.contactList = storage.loadExistingContacts(); + this.personalContact = storage.loadExistingPersonalContact(); } catch (FileErrorException e) { ExceptionTextUi.fileErrorMessage(this.contactFilePath); } diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index 82be53229c..dd99bc1a77 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -28,38 +28,6 @@ public static ContactList readContacts(File contactFile) throws FileErrorExcepti return updatedContactList; } - public static Contact readPersonalContact(File contactFile) throws FileErrorException { - Contact personalContact = new Contact(null,null,null,null,null,null); - try { - Scanner fileScanner = new Scanner(contactFile); - if (fileScanner.hasNext()) { - String contactText = fileScanner.nextLine(); - personalContact = decodePersonalContact(contactText, personalContact); - } - } catch (FileNotFoundException e) { - throw new FileErrorException(); - } - return personalContact; - } - - private static Contact decodePersonalContact(String contactText, Contact contact) { - Contact personalContact = contact; - String[] destructuredInputs = contactText.split(SEPARATOR); - assert destructuredInputs.length > 0; - try { - String contactName = destructuredInputs[DetailType.NAME.getIndex()]; - String contactGithub = destructuredInputs[DetailType.GITHUB.getIndex()]; - String contactLinkedin = destructuredInputs[DetailType.LINKEDIN.getIndex()]; - String contactTelegram = destructuredInputs[DetailType.TELEGRAM.getIndex()]; - String contactTwitter = destructuredInputs[DetailType.TWITTER.getIndex()]; - String contactEmail = destructuredInputs[DetailType.EMAIL.getIndex()]; - personalContact = new Contact(contactName, contactGithub, contactLinkedin, contactTelegram, - contactTwitter, contactEmail); - } catch (IndexOutOfBoundsException e) { - ExceptionTextUi.corruptLineMessage(contactText); - } - return personalContact; - } private static void decodeContact(ContactList contactList, String contactText) { String[] destructuredInputs = contactText.split(SEPARATOR); diff --git a/src/main/java/seedu/storage/Storage.java b/src/main/java/seedu/storage/Storage.java index 6be7511cd2..4459fa119c 100644 --- a/src/main/java/seedu/storage/Storage.java +++ b/src/main/java/seedu/storage/Storage.java @@ -61,8 +61,10 @@ public ContactList loadExistingContacts() throws FileErrorException { public Contact loadExistingPersonalContact() throws FileErrorException { if (!hasExistingPersonalContactFile()) { - return new Contact; + // get new contact } - + ContactList contactList = ContactsDecoder.readContacts(personalContactFile); + assert contactList.getListSize() == 1; + return contactList.getContactAtIndex(0); } } From f3caca66348cc0505df4203195bfc50d932f5472 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 22:20:04 +0800 Subject: [PATCH 242/756] Update message for invalidNameInput --- src/main/java/seedu/ui/ExceptionTextUi.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index 18de6e8d87..10529704b0 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -108,7 +108,12 @@ public static void forbiddenDetailMessage() { } public static void invalidNameInput() { - String message = "The name is not correctly formatted"; + String message = "The name is not correctly formatted,\n" + + "Rules for name :\n" + + " * Uppercase and lowercase letters\n" + + " * Spaces\n" + + " * No numbers or special characters\n" + + " * Cannot be \"null\""; printDoubleLineMessage(message); } From 366ad6259f29ce2335d7ebbd7de7fe8680d1b5dc Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 22:20:50 +0800 Subject: [PATCH 243/756] Update invalidGithubUsernameInput method --- src/main/java/seedu/ui/ExceptionTextUi.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index 10529704b0..b372677b15 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -118,7 +118,13 @@ public static void invalidNameInput() { } public static void invalidGithubUsernameInput() { - String message = "The github username is not correctly formatted"; + String message = "The github username is not correctly formatted,\n" + + "Rules for Github username :\n" + + " * Only contain alphanumeric characters or hyphens\n" + + " * Only lowercase allowed\n" + + " * Maximum 39 characters allowed\n" + + " * Cannot have multiple consecutive hyphens\n" + + " * Cannot begin or end with a hyphen\n"; printDoubleLineMessage(message); } From 6f2fd327cf78a1cb0e7aff771e5d90a274cdd6f3 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 22:21:14 +0800 Subject: [PATCH 244/756] Update message for invalidTelegramUsernameInput --- src/main/java/seedu/ui/ExceptionTextUi.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index b372677b15..801832b9dd 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -129,7 +129,11 @@ public static void invalidGithubUsernameInput() { } public static void invalidTelegramUsernameInput() { - String message = "The telegram username is not correctly formatted"; + String message = "The telegram username is not correctly formatted,\n" + + "Rules for Telegram username :\n" + + " * Uppercase and lowercase letters allowed\n" + + " * Numbers and underscore allowed\n" + + " * Length at-least 5 characters"; printDoubleLineMessage(message); } From 82c2e14c48bc9637694e13161f7d79e1b1f2692c Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 22:21:57 +0800 Subject: [PATCH 245/756] Update invalidTwitterUsernameInput method --- src/main/java/seedu/ui/ExceptionTextUi.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index 801832b9dd..724e0cfbcc 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -138,7 +138,11 @@ public static void invalidTelegramUsernameInput() { } public static void invalidTwitterUsernameInput() { - String message = "The twitter username is not correctly formatted"; + String message = "The twitter username is not correctly formatted,\n" + + "Rules for Twitter username :\n" + + " * Lowercase letters only\n" + + " * Numbers and underscore allowed\n" + + " * Maximum 15 characters allowed"; printDoubleLineMessage(message); } From 1ff2e40813574043e5f6def561f252e2846b4d6f Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 22:22:41 +0800 Subject: [PATCH 246/756] Update invalidEmailInput method --- src/main/java/seedu/ui/ExceptionTextUi.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index 724e0cfbcc..d7d0eea07d 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -146,8 +146,13 @@ public static void invalidTwitterUsernameInput() { printDoubleLineMessage(message); } + //not full, need to update public static void invalidEmailInput() { - String message = "The email id is not correctly formatted"; + String message = "The email id is not correctly formatted,\n" + + "Rules for email id :\n" + + " * Lowercase letters only\n" + + " * Numbers, underscore, hyphen and dot allowed\n" + + " * @ cannot be at the start or end"; printDoubleLineMessage(message); } From 2f3c4bbd50d7dc53a2d9c9905e2f7f92a841fd2f Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 22:23:25 +0800 Subject: [PATCH 247/756] Update invalidLinkedinUsernameInput method --- src/main/java/seedu/ui/ExceptionTextUi.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index d7d0eea07d..0e8c04f079 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -157,7 +157,11 @@ public static void invalidEmailInput() { } public static void invalidLinkedinInput() { - String message = "The linkedin username is not correctly formatted"; + String message = "The linkedin username is not correctly formatted,\n" + + "Rules for Linkedin username :\n" + + " * Lowercase letters only\n" + + " * Numbers, underscore and hyphen allowed\n" + + " * Length between 3 to 100 characters"; printDoubleLineMessage(message); } } From 3ab8ffaa8e1ade53897c8745d390aaf6d3c88433 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 22:49:03 +0800 Subject: [PATCH 248/756] Fix merge conflict --- .../java/seedu/parser/MainParserTest.java | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/test/java/seedu/parser/MainParserTest.java b/src/test/java/seedu/parser/MainParserTest.java index da5ec902bb..4401c9e5f6 100644 --- a/src/test/java/seedu/parser/MainParserTest.java +++ b/src/test/java/seedu/parser/MainParserTest.java @@ -7,7 +7,7 @@ import seedu.command.Command; import seedu.command.DeleteContactCommand; import seedu.command.FailedCommand; -import seedu.command.ViewCommand; +import seedu.command.ViewContactCommand; import seedu.contact.ContactList; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -54,8 +54,8 @@ public void parseDeleteCommand_validIndex_expectDeleteContactIndexMatch() { @Test public void parseDeleteCommand_multipleIndexes_expectDeleteContactIndexMatch() { - testUserInput = "rm 1 2"; - testUserInput = "rm " + testIndex; + int testIndex = 1; + testUserInput = String.format("rm %d %d", testIndex, 2); final DeleteContactCommand testResultCommand = getParsedCommand(testUserInput, DeleteContactCommand.class); assertEquals(testIndex, testResultCommand.getDeletedIndex()); } @@ -144,14 +144,22 @@ public void parseAddCommand_validInputs_expectAddContactCommand() { public void parseViewCommand_validIndex_expectViewContactIndexMatch() { final int testIndex = 1; final String testUserInput = "view " + testIndex; - final ViewCommand testResultCommand = getParsedCommand(testUserInput, ViewCommand.class); - assertEquals(testIndex, testResultCommand.getIndex()); + final ViewContactCommand testResultCommand = getParsedCommand(testUserInput, ViewContactCommand.class); + assertEquals(testIndex,testResultCommand.getIndex()); + } + + @Test + public void parseViewCommand_multipleIndexes_expectViewContactIndexMatch() { + int testIndex = 1; + testUserInput = String.format("view %d %d", testIndex, 2); + final ViewContactCommand testResultCommand = getParsedCommand(testUserInput, ViewContactCommand.class); + assertEquals(testIndex,testResultCommand.getIndex()); } @Test public void parseViewCommand_invalidIndex_expectException() { testIndex = 99999; - final ViewCommand testResultCommand = new ViewCommand(testIndex); + final ViewContactCommand testResultCommand = new ViewContactCommand(testIndex); assertThrows(NullPointerException.class, testResultCommand::execute); } @@ -159,7 +167,7 @@ public void parseViewCommand_invalidIndex_expectException() { public void parseViewCommand_validIndexWithSpaces_expectViewContactIndexMatch() { testIndex = 1; testUserInput = "view " + testIndex; - final ViewCommand testResultCommand = getParsedCommand(testUserInput, ViewCommand.class); + final ViewContactCommand testResultCommand = getParsedCommand(testUserInput, ViewContactCommand.class); assertEquals(testIndex, testResultCommand.getIndex()); } @@ -179,13 +187,6 @@ public void parseViewCommand_invalidInput_expectFailedCommandType() { assertEquals(expectedFailedCommandType, actualFailedCommand.getType()); } - @Test - public void parseViewCommand_invalidInputFormat_expectFailedCommandType() { - testUserInput = "view 1 2"; - FailedCommandType expectedFailedCommandType = FailedCommandType.INVALID_INDEX; - final FailedCommand actualFailedCommand = getParsedCommand(testUserInput, FailedCommand.class); - assertEquals(expectedFailedCommandType, actualFailedCommand.getType()); - } @Test public void parseAddCommand_missingName_expectFailedCommand() { From 1a9218ea103b06fd2f7713f5dfd5a761207895c7 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 23:10:43 +0800 Subject: [PATCH 249/756] Remove extra whitespaces --- src/main/java/seedu/ui/ExceptionTextUi.java | 4 ++-- src/main/java/seedu/ui/TextUi.java | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index 0e8c04f079..efc19b7de4 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -47,7 +47,7 @@ public static void invalidIndexMessage() { } public static void missingDetailMessage() { - String message = "There are missing details.\n" + "Please remove any flags with no details, \n" + String message = "There are missing details.\n" + "Please remove any flags with no details,\n" + "and ensure that your flags used are correct:\n" + " -n NAME\n" + " -g GITHUB\n" + " -l LINKEDIN\n" + " -te TELEGRAM\n" + " -tw TWITTER\n" + " -e EMAIL"; printDoubleLineMessage(message); @@ -102,7 +102,7 @@ public static void forbiddenInputCommaMessage(String newUserInput) { } public static void forbiddenDetailMessage() { - String message = "As one of the details to be stored is \"null\", \n" + String message = "As one of the details to be stored is \"null\",\n" + "ConTech is unable to process it"; printDoubleLineMessage(message); } diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 4220fcf15a..24b9754937 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -62,13 +62,13 @@ private static void initMessage() { } public static void createNewContactFileMessage(String contactFilePath) { - String message = "As ConTech is unable to find your saved data, \n" + " it has created a new one for you at: \n" + String message = "As ConTech is unable to find your saved data,\n" + " it has created a new one for you at:\n" + contactFilePath; printBottomLineMessage(message); } public static void addContactMessage(Contact addedContact, int listSize) { - String message = "ConTech has added the specified contact: \n" + String message = "ConTech has added the specified contact:\n" + "Name: " + addedContact.getName() + formatContactFields(addedContact) + "\n\nYou now have " + listSize + " contact(s)."; @@ -76,7 +76,7 @@ public static void addContactMessage(Contact addedContact, int listSize) { } public static void editContactMessage(Contact editedContact) { - String message = "ConTech has edited the specified contact: \n" + String message = "ConTech has edited the specified contact:\n" + "Name: " + editedContact.getName() + formatContactFields(editedContact); printDoubleLineMessage(message); From a3e69e136abcdf890ad902e83bf1ab3b07eb3aa9 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 23:11:51 +0800 Subject: [PATCH 250/756] Fix IO redirection tests --- text-ui-test/ACTUAL.TXT | 150 +++++++++++++++++++++++++++++--------- text-ui-test/EXPECTED.TXT | 150 +++++++++++++++++++++++++++++--------- text-ui-test/input.txt | 11 ++- 3 files changed, 238 insertions(+), 73 deletions(-) diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index cb90196229..afac34bc00 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -12,8 +12,8 @@ ____________________________________________________________ Welcome to ConTech, your personal contact tracker. ____________________________________________________________ -As ConTech is unable to find your saved data, - it has created a new one for you at: +As ConTech is unable to find your saved data, + it has created a new one for you at: data/contacts.txt ____________________________________________________________ @@ -22,7 +22,7 @@ There are no contacts stored in ConTech. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: ng andre Github: github.com/ng-andre @@ -39,7 +39,7 @@ Please enter a valid contact index. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: ashraf Github: github.com/ashraf @@ -67,7 +67,7 @@ Delete has been cancelled. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: mayank Github: github.com/mayankp123 @@ -80,7 +80,7 @@ Please input a number between 0 and 2. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: bory Github: github.com/marcus @@ -88,7 +88,7 @@ You now have 4 contact(s). ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: andre Github: github.com/ng-andre @@ -115,7 +115,7 @@ ____________________________________________________________ ____________________________________________________________ There are missing details. -Please remove any flags with no details, +Please remove any flags with no details, and ensure that your flags used are correct: -n NAME -g GITHUB @@ -130,7 +130,7 @@ Please enter a valid contact index. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: lezong Github: github.com/lezongmun @@ -185,7 +185,7 @@ ____________________________________________________________ ____________________________________________________________ There are missing details. -Please remove any flags with no details, +Please remove any flags with no details, and ensure that your flags used are correct: -n NAME -g GITHUB @@ -227,7 +227,7 @@ Please try again with a valid flag. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: lezongmun Github: github.com/lezong @@ -271,6 +271,65 @@ ____________________________________________________________ Please enter a valid contact index. ____________________________________________________________ +____________________________________________________________ +There are missing details. +Please remove any flags with no details, +and ensure that your flags used are correct: + -n NAME + -g GITHUB + -l LINKEDIN + -te TELEGRAM + -tw TWITTER + -e EMAIL +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: +Name: yusdhsdsd +Github: github.com/sdj0-11222 + +You now have 5 contact(s). +____________________________________________________________ + +____________________________________________________________ +The github username is not correctly formatted, +Rules for Github username : + * Only contain alphanumeric characters or hyphens + * Only lowercase allowed + * Maximum 39 characters allowed + * Cannot have multiple consecutive hyphens + * Cannot begin or end with a hyphen + +____________________________________________________________ + +____________________________________________________________ +The github username is not correctly formatted, +Rules for Github username : + * Only contain alphanumeric characters or hyphens + * Only lowercase allowed + * Maximum 39 characters allowed + * Cannot have multiple consecutive hyphens + * Cannot begin or end with a hyphen + +____________________________________________________________ + +____________________________________________________________ +The name is not correctly formatted, +Rules for name : + * Uppercase and lowercase letters + * Spaces + * No numbers or special characters + * Cannot be "null" +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: +Name: asjoda sadfsd +Telegram: t.me/_123adad + +You now have 6 contact(s). +____________________________________________________________ + ____________________________________________________________ 0. mayank Github: github.com/mayankp123 @@ -278,7 +337,7 @@ ____________________________________________________________ ____________________________________________________________ There are missing details. -Please remove any flags with no details, +Please remove any flags with no details, and ensure that your flags used are correct: -n NAME -g GITHUB @@ -294,47 +353,67 @@ Due to the storage nature of ConTech, we will remove commas (","), and attempt to parse it as: add -n lezong mun -g lezaimun ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: lezong mun Github: github.com/lezaimun -You now have 5 contact(s). +You now have 7 contact(s). ____________________________________________________________ ____________________________________________________________ -As one of the details to be stored is "null", +As one of the details to be stored is "null", ConTech is unable to process it ____________________________________________________________ ____________________________________________________________ -As one of the details to be stored is "null", +As one of the details to be stored is "null", ConTech is unable to process it ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: dev Github: github.com/nullptr -You now have 6 contact(s). +You now have 8 contact(s). ____________________________________________________________ ____________________________________________________________ -ConTech has edited the specified contact: +ConTech has edited the specified contact: Name: lezongmun Github: github.com/new-git ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: -Name: name -Github: github.com/github -Email: email -Telegram: t.me/telegram -LinkedIn: linkedin.com/in/linkedin -Twitter: twitter.com/twitter +The twitter username is not correctly formatted, +Rules for Twitter username : + * Lowercase letters only + * Numbers and underscore allowed + * Maximum 15 characters allowed +____________________________________________________________ -You now have 7 contact(s). +____________________________________________________________ +ConTech has added the specified contact: +Name: asjoda sadfsd +Twitter: twitter.com/123_adad + +You now have 9 contact(s). +____________________________________________________________ + +____________________________________________________________ +The email id is not correctly formatted, +Rules for email id : + * Lowercase letters only + * Numbers, underscore, hyphen and dot allowed + * @ cannot be at the start or end +____________________________________________________________ + +____________________________________________________________ +The email id is not correctly formatted, +Rules for email id : + * Lowercase letters only + * Numbers, underscore, hyphen and dot allowed + * @ cannot be at the start or end ____________________________________________________________ ____________________________________________________________ @@ -349,21 +428,20 @@ Please try again with a valid flag. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: -Name: lezai3 -Github: github.com/lezongmun -Email: lezongmun@gmail.com -LinkedIn: linkedin.com/in/lezongmun - -You now have 8 contact(s). +The name is not correctly formatted, +Rules for name : + * Uppercase and lowercase letters + * Spaces + * No numbers or special characters + * Cannot be "null" ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: lezongggg Telegram: t.me/testTelegram -You now have 9 contact(s). +You now have 10 contact(s). ____________________________________________________________ ____________________________________________________________ diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index cb90196229..afac34bc00 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -12,8 +12,8 @@ ____________________________________________________________ Welcome to ConTech, your personal contact tracker. ____________________________________________________________ -As ConTech is unable to find your saved data, - it has created a new one for you at: +As ConTech is unable to find your saved data, + it has created a new one for you at: data/contacts.txt ____________________________________________________________ @@ -22,7 +22,7 @@ There are no contacts stored in ConTech. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: ng andre Github: github.com/ng-andre @@ -39,7 +39,7 @@ Please enter a valid contact index. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: ashraf Github: github.com/ashraf @@ -67,7 +67,7 @@ Delete has been cancelled. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: mayank Github: github.com/mayankp123 @@ -80,7 +80,7 @@ Please input a number between 0 and 2. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: bory Github: github.com/marcus @@ -88,7 +88,7 @@ You now have 4 contact(s). ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: andre Github: github.com/ng-andre @@ -115,7 +115,7 @@ ____________________________________________________________ ____________________________________________________________ There are missing details. -Please remove any flags with no details, +Please remove any flags with no details, and ensure that your flags used are correct: -n NAME -g GITHUB @@ -130,7 +130,7 @@ Please enter a valid contact index. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: lezong Github: github.com/lezongmun @@ -185,7 +185,7 @@ ____________________________________________________________ ____________________________________________________________ There are missing details. -Please remove any flags with no details, +Please remove any flags with no details, and ensure that your flags used are correct: -n NAME -g GITHUB @@ -227,7 +227,7 @@ Please try again with a valid flag. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: lezongmun Github: github.com/lezong @@ -271,6 +271,65 @@ ____________________________________________________________ Please enter a valid contact index. ____________________________________________________________ +____________________________________________________________ +There are missing details. +Please remove any flags with no details, +and ensure that your flags used are correct: + -n NAME + -g GITHUB + -l LINKEDIN + -te TELEGRAM + -tw TWITTER + -e EMAIL +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: +Name: yusdhsdsd +Github: github.com/sdj0-11222 + +You now have 5 contact(s). +____________________________________________________________ + +____________________________________________________________ +The github username is not correctly formatted, +Rules for Github username : + * Only contain alphanumeric characters or hyphens + * Only lowercase allowed + * Maximum 39 characters allowed + * Cannot have multiple consecutive hyphens + * Cannot begin or end with a hyphen + +____________________________________________________________ + +____________________________________________________________ +The github username is not correctly formatted, +Rules for Github username : + * Only contain alphanumeric characters or hyphens + * Only lowercase allowed + * Maximum 39 characters allowed + * Cannot have multiple consecutive hyphens + * Cannot begin or end with a hyphen + +____________________________________________________________ + +____________________________________________________________ +The name is not correctly formatted, +Rules for name : + * Uppercase and lowercase letters + * Spaces + * No numbers or special characters + * Cannot be "null" +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: +Name: asjoda sadfsd +Telegram: t.me/_123adad + +You now have 6 contact(s). +____________________________________________________________ + ____________________________________________________________ 0. mayank Github: github.com/mayankp123 @@ -278,7 +337,7 @@ ____________________________________________________________ ____________________________________________________________ There are missing details. -Please remove any flags with no details, +Please remove any flags with no details, and ensure that your flags used are correct: -n NAME -g GITHUB @@ -294,47 +353,67 @@ Due to the storage nature of ConTech, we will remove commas (","), and attempt to parse it as: add -n lezong mun -g lezaimun ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: lezong mun Github: github.com/lezaimun -You now have 5 contact(s). +You now have 7 contact(s). ____________________________________________________________ ____________________________________________________________ -As one of the details to be stored is "null", +As one of the details to be stored is "null", ConTech is unable to process it ____________________________________________________________ ____________________________________________________________ -As one of the details to be stored is "null", +As one of the details to be stored is "null", ConTech is unable to process it ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: dev Github: github.com/nullptr -You now have 6 contact(s). +You now have 8 contact(s). ____________________________________________________________ ____________________________________________________________ -ConTech has edited the specified contact: +ConTech has edited the specified contact: Name: lezongmun Github: github.com/new-git ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: -Name: name -Github: github.com/github -Email: email -Telegram: t.me/telegram -LinkedIn: linkedin.com/in/linkedin -Twitter: twitter.com/twitter +The twitter username is not correctly formatted, +Rules for Twitter username : + * Lowercase letters only + * Numbers and underscore allowed + * Maximum 15 characters allowed +____________________________________________________________ -You now have 7 contact(s). +____________________________________________________________ +ConTech has added the specified contact: +Name: asjoda sadfsd +Twitter: twitter.com/123_adad + +You now have 9 contact(s). +____________________________________________________________ + +____________________________________________________________ +The email id is not correctly formatted, +Rules for email id : + * Lowercase letters only + * Numbers, underscore, hyphen and dot allowed + * @ cannot be at the start or end +____________________________________________________________ + +____________________________________________________________ +The email id is not correctly formatted, +Rules for email id : + * Lowercase letters only + * Numbers, underscore, hyphen and dot allowed + * @ cannot be at the start or end ____________________________________________________________ ____________________________________________________________ @@ -349,21 +428,20 @@ Please try again with a valid flag. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: -Name: lezai3 -Github: github.com/lezongmun -Email: lezongmun@gmail.com -LinkedIn: linkedin.com/in/lezongmun - -You now have 8 contact(s). +The name is not correctly formatted, +Rules for name : + * Uppercase and lowercase letters + * Spaces + * No numbers or special characters + * Cannot be "null" ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: lezongggg Telegram: t.me/testTelegram -You now have 9 contact(s). +You now have 10 contact(s). ____________________________________________________________ ____________________________________________________________ diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index 4648dac51a..bbcf82359e 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -36,6 +36,12 @@ n y list view abc +add -n yusdhsdsd -g -sdj11222 +add -n yusdhsdsd -g sdj0-11222 +add -n yusdhfgsd -g sdj11222- +add -n yusdhsd -g sdj11--222 +add -n asbsd123123 +add -n asjoda sadfsd -te _123adad view 0 add -n -g add -n le,zong, mun -g lezaimun @@ -43,7 +49,10 @@ view 0 add -n name -g null add -n dev -g nullptr edit 3 -g new-git -add -n name -l linkedin -g github -e email -tw twitter -te telegram + add -n asjoda sadfsd -tw _123 adad + add -n asjoda sadfsd -tw 123_adad +add -n name -l linkedin -g github -e lasdas@ -tw twitter -te telegram +add -n asdasd -l kusdd__ -g adasdas -e .adadas@com add -n lezai -g lezongmun -e lezongmun@gmail.com -linkedin lezongmun add -n lezai3 -g lezongmun -e lezongmun@gmail.com -l lezongmun add -n lezongggg -te testTelegram From 417e46aaecf9d94bc9541ae26f83a79d508100bb Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 12 Oct 2021 23:41:39 +0800 Subject: [PATCH 251/756] Add JUnit test to check regex --- src/test/java/seedu/parser/MainParserTest.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/test/java/seedu/parser/MainParserTest.java b/src/test/java/seedu/parser/MainParserTest.java index 4401c9e5f6..3676cb7573 100644 --- a/src/test/java/seedu/parser/MainParserTest.java +++ b/src/test/java/seedu/parser/MainParserTest.java @@ -140,6 +140,18 @@ public void parseAddCommand_validInputs_expectAddContactCommand() { assertEquals(expectedCommand.getEmail(), actualCommand.getEmail()); } + @Test + public void parseAddCommand_validInputsWithFlags_expectAddContactCommand() { + testUserInput = " add -n ashraf -g fdada-121 -tw 66123ada -e ash@yahoo.com "; + AddContactCommand actualCommand = getParsedCommand(testUserInput, AddContactCommand.class); + AddContactCommand expectedCommand = new AddContactCommand("ashraf", "fdada-121", + null, null, "66123ada", "ash@yahoo.com"); + assertEquals(expectedCommand.getName(), actualCommand.getName()); + assertEquals(expectedCommand.getGithub(), actualCommand.getGithub()); + assertEquals(expectedCommand.getTwitter(), actualCommand.getTwitter()); + assertEquals(expectedCommand.getEmail(), actualCommand.getEmail()); + } + @Test public void parseViewCommand_validIndex_expectViewContactIndexMatch() { final int testIndex = 1; From 33e1ef55080212ab1529d8c8e0e462944ce31342 Mon Sep 17 00:00:00 2001 From: lezong Date: Wed, 13 Oct 2021 00:07:07 +0800 Subject: [PATCH 252/756] Save personal details in a simple way sharing same encoder and decoder --- src/main/java/seedu/duke/Duke.java | 11 ++++- src/main/java/seedu/storage/Storage.java | 24 +++++++++-- src/main/java/seedu/ui/TextUi.java | 54 ++++++++++++++++++++---- 3 files changed, 75 insertions(+), 14 deletions(-) diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index f779ed6b76..9b37712559 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -18,18 +18,25 @@ public class Duke { private ContactList contactList; private String personalContactFilePath; private Contact personalContact; +// private boolean isFirstRun; + + public Duke(String contactFilePath, String personalContactFilePath) { - this.textUi = new TextUi(); this.contactFilePath = contactFilePath; - this.storage = new Storage(contactFilePath, personalContactFilePath); + this.personalContactFilePath = personalContactFilePath; this.parser = new MainParser(); + this.storage = new Storage(contactFilePath, personalContactFilePath); +// this.isFirstRun = storage.getIsFirstRun(); try { this.contactList = storage.loadExistingContacts(); this.personalContact = storage.loadExistingPersonalContact(); } catch (FileErrorException e) { ExceptionTextUi.fileErrorMessage(this.contactFilePath); } + +// this.textUi = new TextUi(isFirstRun, personalContact); + } private void runConTech() { diff --git a/src/main/java/seedu/storage/Storage.java b/src/main/java/seedu/storage/Storage.java index 4459fa119c..ca090832df 100644 --- a/src/main/java/seedu/storage/Storage.java +++ b/src/main/java/seedu/storage/Storage.java @@ -1,5 +1,6 @@ package seedu.storage; +import org.w3c.dom.Text; import seedu.contact.Contact; import seedu.contact.ContactList; import seedu.exception.FileErrorException; @@ -14,6 +15,7 @@ public class Storage { private final String personalContactFilePath; private final File personalContactFile; public static final String SEPARATOR = ","; + private static boolean isFirstRun = false; public Storage(String contactFilePath, String personalContactFilePath) { this.contactFilePath = contactFilePath; @@ -22,13 +24,17 @@ public Storage(String contactFilePath, String personalContactFilePath) { this.personalContactFile = new File(personalContactFilePath); } + public static boolean getIsFirstRun() { + return isFirstRun; + } + private boolean hasExistingPersonalContactFile() throws FileErrorException { try { if (!personalContactFile.exists()) { personalContactFile.getParentFile().mkdirs(); } if (personalContactFile.createNewFile()) { - TextUi.createNewContactFileMessage(personalContactFilePath); + TextUi.createNewPersonalContactFileMessage(personalContactFilePath); return false; } } catch (IOException e) { @@ -59,12 +65,24 @@ public ContactList loadExistingContacts() throws FileErrorException { return ContactsDecoder.readContacts(contactFile); } + + public Contact loadExistingPersonalContact() throws FileErrorException { if (!hasExistingPersonalContactFile()) { - // get new contact + isFirstRun = true; + // get new contact + String personalName = TextUi.getNameMessage(); + Contact personalContact = new Contact(personalName, null,null,null,null,null); + ContactList contactList = new ContactList(); + contactList.addContact(personalContact); + ContactsEncoder.saveContacts(personalContactFilePath, contactList); + TextUi.greetingMessage(personalContact); + return personalContact; } ContactList contactList = ContactsDecoder.readContacts(personalContactFile); assert contactList.getListSize() == 1; - return contactList.getContactAtIndex(0); + Contact personalContact = contactList.getContactAtIndex(0); + TextUi.welcomeBackMessage(personalContact); + return personalContact; } } diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 3cbbee5b29..f446895354 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -4,7 +4,7 @@ import java.util.Scanner; -public class TextUi { +public abstract class TextUi { private static final String LOGO = " _____ _______ _ \n" + " / ____| |__ __| | | \n" + " | | ___ _ __ | | ___ ___| |__ \n" + " | | / _ \\| '_ \\| |/ _ \\/ __| '_ \\ \n" + " | |___| (_) | | | | | __/ (__| | | |\n" @@ -14,9 +14,9 @@ public class TextUi { private static final Scanner scanner = new Scanner(System.in); - public TextUi() { - initMessage(); - } +// public TextUi(boolean isFirstRun, Contact personalContact) { +// initMessage(isFirstRun, personalContact); +// } public static String getUserInput() { String userInput = scanner.nextLine().trim(); @@ -37,6 +37,31 @@ public static String getUserDeleteConfirmation(Contact deletedContact, int delet return userDeleteConfirmation; } + public static String getUserPersonalContact() { + String message = "Whats you name?"; + System.out.println(message); + System.out.println(LINE); + return scanner.nextLine().trim(); + } + + public static String getNameMessage() { + printDoubleLineMessage(LOGO); + System.out.println("Welcome to ConTech, your personal contact tracker.\n"); + String personalContact = getUserPersonalContact(); + return personalContact; + } + + public static void welcomeBackMessage(Contact personalContact) { + printDoubleLineMessage(LOGO); + System.out.println(personalContact.getName() + ", welcome back to ConTech, your personal contact tracker.\n"); + System.out.println(LINE); + } + + public static void greetingMessage(Contact personalContact) { + String message = "Hello there " + personalContact.getName(); + printDoubleLineMessage(message); + } + // Used for print messages after user inputs private static void printDoubleLineMessage(String message) { System.out.println(LINE + message + "\n" + LINE); @@ -56,10 +81,15 @@ public static void printBottomLine() { System.out.println("\n" + LINE); } - private static void initMessage() { - printDoubleLineMessage(LOGO); - System.out.println("Welcome to ConTech, your personal contact tracker.\n" + LINE); - } +// private static void initMessage(boolean isFirstRun, Contact personalContact) { +// printDoubleLineMessage(LOGO); +// if (isFirstRun) { +// welcomeBackMessage(); +// } else { +// System.out.println("Welcome back " + personalContact.getName()); +// } +// +// } public static void createNewContactFileMessage(String contactFilePath) { String message = "As ConTech is unable to find your saved data, \n" + " it has created a new one for you at: \n" @@ -67,6 +97,13 @@ public static void createNewContactFileMessage(String contactFilePath) { printBottomLineMessage(message); } + public static void createNewPersonalContactFileMessage(String personalContactFilePath) { + String message = "As ConTech is unable to find any saved personal data, \n" + + " it has created a new one for you at: \n" + + personalContactFilePath; + printBottomLineMessage(message); + } + public static void addContactMessage(Contact addedContact, int listSize) { String message = "ConTech has added the specified contact: \n" + "Name: " + addedContact.getName() @@ -126,5 +163,4 @@ public static void exitMessage() { String message = "ConTech will now shutdown.\n" + "We hope you have enjoyed using it."; printDoubleLineMessage(message); } - } From 1577ca2997f8f59844a07227579e471799f73c1d Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 13 Oct 2021 00:07:31 +0800 Subject: [PATCH 253/756] Update code to adhere to checkstyle --- src/main/java/seedu/exception/InvalidEmailException.java | 2 +- .../java/seedu/exception/InvalidGithubUsernameException.java | 2 +- .../java/seedu/exception/InvalidLinkedinUsernameException.java | 2 +- .../java/seedu/exception/InvalidTelegramUsernameException.java | 2 +- .../java/seedu/exception/InvalidTwitterUsernameException.java | 2 +- src/main/java/seedu/exception/MissingArgException.java | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/seedu/exception/InvalidEmailException.java b/src/main/java/seedu/exception/InvalidEmailException.java index d7d82a67be..bcc7261120 100644 --- a/src/main/java/seedu/exception/InvalidEmailException.java +++ b/src/main/java/seedu/exception/InvalidEmailException.java @@ -1,4 +1,4 @@ package seedu.exception; -public class InvalidEmailException extends Exception{ +public class InvalidEmailException extends Exception { } diff --git a/src/main/java/seedu/exception/InvalidGithubUsernameException.java b/src/main/java/seedu/exception/InvalidGithubUsernameException.java index 42fb180b02..f6149b525c 100644 --- a/src/main/java/seedu/exception/InvalidGithubUsernameException.java +++ b/src/main/java/seedu/exception/InvalidGithubUsernameException.java @@ -1,4 +1,4 @@ package seedu.exception; -public class InvalidGithubUsernameException extends Exception{ +public class InvalidGithubUsernameException extends Exception { } diff --git a/src/main/java/seedu/exception/InvalidLinkedinUsernameException.java b/src/main/java/seedu/exception/InvalidLinkedinUsernameException.java index 982c30397a..bb14510600 100644 --- a/src/main/java/seedu/exception/InvalidLinkedinUsernameException.java +++ b/src/main/java/seedu/exception/InvalidLinkedinUsernameException.java @@ -1,4 +1,4 @@ package seedu.exception; -public class InvalidLinkedinUsernameException extends Exception{ +public class InvalidLinkedinUsernameException extends Exception { } diff --git a/src/main/java/seedu/exception/InvalidTelegramUsernameException.java b/src/main/java/seedu/exception/InvalidTelegramUsernameException.java index 27543793a5..99c04bd7f8 100644 --- a/src/main/java/seedu/exception/InvalidTelegramUsernameException.java +++ b/src/main/java/seedu/exception/InvalidTelegramUsernameException.java @@ -1,4 +1,4 @@ package seedu.exception; -public class InvalidTelegramUsernameException extends Exception{ +public class InvalidTelegramUsernameException extends Exception { } diff --git a/src/main/java/seedu/exception/InvalidTwitterUsernameException.java b/src/main/java/seedu/exception/InvalidTwitterUsernameException.java index 091bb77d22..5a0f05a196 100644 --- a/src/main/java/seedu/exception/InvalidTwitterUsernameException.java +++ b/src/main/java/seedu/exception/InvalidTwitterUsernameException.java @@ -1,4 +1,4 @@ package seedu.exception; -public class InvalidTwitterUsernameException extends Exception{ +public class InvalidTwitterUsernameException extends Exception { } diff --git a/src/main/java/seedu/exception/MissingArgException.java b/src/main/java/seedu/exception/MissingArgException.java index a4b92a65e1..61d61b3107 100644 --- a/src/main/java/seedu/exception/MissingArgException.java +++ b/src/main/java/seedu/exception/MissingArgException.java @@ -1,4 +1,4 @@ package seedu.exception; -public class MissingArgException extends Exception{ +public class MissingArgException extends Exception { } From 081290cf201359af8a564070cc4b0382e78f4a0a Mon Sep 17 00:00:00 2001 From: lezong Date: Wed, 13 Oct 2021 01:27:27 +0800 Subject: [PATCH 254/756] Change to separate decoding and encoding for personal contact --- src/main/java/seedu/duke/Duke.java | 8 +--- .../java/seedu/storage/ContactsDecoder.java | 44 +++++++++++++------ .../java/seedu/storage/ContactsEncoder.java | 11 +++++ src/main/java/seedu/storage/Storage.java | 23 +++++----- src/main/java/seedu/ui/TextUi.java | 20 +++------ 5 files changed, 63 insertions(+), 43 deletions(-) diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 9b37712559..b4878da7f8 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -18,25 +18,19 @@ public class Duke { private ContactList contactList; private String personalContactFilePath; private Contact personalContact; -// private boolean isFirstRun; - - public Duke(String contactFilePath, String personalContactFilePath) { this.contactFilePath = contactFilePath; this.personalContactFilePath = personalContactFilePath; this.parser = new MainParser(); this.storage = new Storage(contactFilePath, personalContactFilePath); -// this.isFirstRun = storage.getIsFirstRun(); + try { this.contactList = storage.loadExistingContacts(); this.personalContact = storage.loadExistingPersonalContact(); } catch (FileErrorException e) { ExceptionTextUi.fileErrorMessage(this.contactFilePath); } - -// this.textUi = new TextUi(isFirstRun, personalContact); - } private void runConTech() { diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index dd99bc1a77..21738f03f3 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -28,12 +28,40 @@ public static ContactList readContacts(File contactFile) throws FileErrorExcepti return updatedContactList; } + public static Contact readPersonalContact(File personalContactFile) throws FileErrorException { + Contact personalContact = new Contact(null, null, null, null, null, null); + try { + Scanner fileScanner = new Scanner(personalContactFile); + if (fileScanner.hasNext()) { + String contactText = fileScanner.nextLine(); + personalContact = decodePersonalContact(contactText, personalContact); + } + } catch (FileNotFoundException e) { + throw new FileErrorException(); + } + return personalContact; + } + + private static Contact decodePersonalContact(String contactText, Contact contact) { + String[] destructuredInputs = contactText.split(SEPARATOR); + Contact personalContact = contact; + try { + String contactName = destructuredInputs[DetailType.NAME.getIndex()]; + String contactGithub = destructuredInputs[DetailType.GITHUB.getIndex()]; + String contactLinkedin = destructuredInputs[DetailType.LINKEDIN.getIndex()]; + String contactTelegram = destructuredInputs[DetailType.TELEGRAM.getIndex()]; + String contactTwitter = destructuredInputs[DetailType.TWITTER.getIndex()]; + String contactEmail = destructuredInputs[DetailType.EMAIL.getIndex()]; + personalContact = new Contact(contactName, contactGithub, contactLinkedin, contactTelegram, + contactTwitter, contactEmail); + } catch (IndexOutOfBoundsException e) { + ExceptionTextUi.corruptLineMessage(contactText); + } + return personalContact; + } private static void decodeContact(ContactList contactList, String contactText) { String[] destructuredInputs = contactText.split(SEPARATOR); - String[] compiledDetails = new String[NUMBER_OF_FIELDS]; - assert destructuredInputs.length > 0; - decodeDetails(compiledDetails, destructuredInputs); // Add the decoded details into the contact list try { String contactName = destructuredInputs[DetailType.NAME.getIndex()]; @@ -49,14 +77,4 @@ private static void decodeContact(ContactList contactList, String contactText) { ExceptionTextUi.corruptLineMessage(contactText); } } - - private static void decodeDetails(String[] compiledDetails, String[] destructuredInputs) { - if (compiledDetails.length != destructuredInputs.length) { - return; - } - assert compiledDetails.length == NUMBER_OF_FIELDS; - for (int i = 0; i < NUMBER_OF_FIELDS; i++) { - compiledDetails[i] = destructuredInputs[i]; - } - } } diff --git a/src/main/java/seedu/storage/ContactsEncoder.java b/src/main/java/seedu/storage/ContactsEncoder.java index d86e5b7a04..9e0c707973 100644 --- a/src/main/java/seedu/storage/ContactsEncoder.java +++ b/src/main/java/seedu/storage/ContactsEncoder.java @@ -10,6 +10,17 @@ import static seedu.storage.Storage.SEPARATOR; public class ContactsEncoder { + public static void savePersonalContact(String contactFilePath, Contact personalContact) throws FileErrorException { + try { + FileWriter fileWriter = new FileWriter(contactFilePath); + String encodedContact = encodeContact(personalContact); + fileWriter.write(encodedContact); + fileWriter.close(); + } catch (IOException e) { + throw new FileErrorException(); + } + } + public static void saveContacts(String contactFilePath, ContactList contactList) throws FileErrorException { try { FileWriter fileWriter = new FileWriter(contactFilePath); diff --git a/src/main/java/seedu/storage/Storage.java b/src/main/java/seedu/storage/Storage.java index ca090832df..bdc8291a11 100644 --- a/src/main/java/seedu/storage/Storage.java +++ b/src/main/java/seedu/storage/Storage.java @@ -43,6 +43,14 @@ private boolean hasExistingPersonalContactFile() throws FileErrorException { return true; } + private boolean hasEmptyExistingPersonalContactFile() { + if (personalContactFile.exists() && personalContactFile.length() == 0) { + return true; + } + return false; + } + + private boolean hasExistingContactFile() throws FileErrorException { try { if (!contactFile.exists()) { @@ -65,23 +73,18 @@ public ContactList loadExistingContacts() throws FileErrorException { return ContactsDecoder.readContacts(contactFile); } - - public Contact loadExistingPersonalContact() throws FileErrorException { - if (!hasExistingPersonalContactFile()) { + if (!hasExistingPersonalContactFile() || hasEmptyExistingPersonalContactFile()) { isFirstRun = true; // get new contact String personalName = TextUi.getNameMessage(); - Contact personalContact = new Contact(personalName, null,null,null,null,null); - ContactList contactList = new ContactList(); - contactList.addContact(personalContact); - ContactsEncoder.saveContacts(personalContactFilePath, contactList); + Contact personalContact = new Contact(personalName, null,null,null, + null,null); + ContactsEncoder.savePersonalContact(personalContactFilePath, personalContact); TextUi.greetingMessage(personalContact); return personalContact; } - ContactList contactList = ContactsDecoder.readContacts(personalContactFile); - assert contactList.getListSize() == 1; - Contact personalContact = contactList.getContactAtIndex(0); + Contact personalContact = ContactsDecoder.readPersonalContact(personalContactFile); TextUi.welcomeBackMessage(personalContact); return personalContact; } diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index f446895354..1b7f71fae1 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -38,7 +38,7 @@ public static String getUserDeleteConfirmation(Contact deletedContact, int delet } public static String getUserPersonalContact() { - String message = "Whats you name?"; + String message = "Can I get your name?"; System.out.println(message); System.out.println(LINE); return scanner.nextLine().trim(); @@ -53,12 +53,16 @@ public static String getNameMessage() { public static void welcomeBackMessage(Contact personalContact) { printDoubleLineMessage(LOGO); - System.out.println(personalContact.getName() + ", welcome back to ConTech, your personal contact tracker.\n"); + System.out.println("Hello, " + personalContact.getName() + "." + " Welcome back to ConTech.\n"); System.out.println(LINE); } public static void greetingMessage(Contact personalContact) { - String message = "Hello there " + personalContact.getName(); + String message = "Hello there, " + personalContact.getName() + ".\n\n" + + "This is ConTech, your very own contact tracking application\n" + + "to manage computing-related contacts, like GitHub Accounts\n" + + "or even Emails.\n\n" + + "Enter \"help\" to see what you can do with ConTech."; printDoubleLineMessage(message); } @@ -81,16 +85,6 @@ public static void printBottomLine() { System.out.println("\n" + LINE); } -// private static void initMessage(boolean isFirstRun, Contact personalContact) { -// printDoubleLineMessage(LOGO); -// if (isFirstRun) { -// welcomeBackMessage(); -// } else { -// System.out.println("Welcome back " + personalContact.getName()); -// } -// -// } - public static void createNewContactFileMessage(String contactFilePath) { String message = "As ConTech is unable to find your saved data, \n" + " it has created a new one for you at: \n" + contactFilePath; From 6cb4985bc6ed671741207d48d4e517388535dfa4 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Wed, 13 Oct 2021 10:58:00 +0800 Subject: [PATCH 255/756] Add help command as a constant string. --- src/main/java/seedu/parser/MainParser.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index d044645cca..4bfd80a12a 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -4,6 +4,7 @@ import seedu.command.EditContactCommand; import seedu.command.DeleteContactCommand; import seedu.command.Command; +import seedu.command.HelpCommand; import seedu.command.ViewContactCommand; import seedu.command.FailedCommand; import seedu.command.ExitCommand; @@ -31,6 +32,7 @@ public class MainParser { private static final String VIEW_CONTACT_COMD = "view"; private static final String EXIT_COMD = "exit"; private static final String LIST_COMD = "list"; + private static final String HELP_COMD = "help"; private static final int COMD_WORD_INDEX = 0; private static final int ISOLATE_COMD_WORD = 2; From bf428eae4f661333ada6d2165a401a3b720df09d Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Wed, 13 Oct 2021 10:58:23 +0800 Subject: [PATCH 256/756] Add help command to command switch case. --- src/main/java/seedu/parser/MainParser.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 4bfd80a12a..ad1e3cfe95 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -64,6 +64,9 @@ public Command parseCommand(String userInput) { case LIST_COMD: command = new ListContactsCommand(); break; + case HELP_COMD: + command = new HelpCommand(); + break; default: command = new FailedCommand(FailedCommandType.GENERAL); } From 245bd8e895ea1fb19058d216afc9a61a3f977292 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Wed, 13 Oct 2021 10:59:18 +0800 Subject: [PATCH 257/756] Add new HelpCommand class to execute command. --- src/main/java/seedu/command/HelpCommand.java | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/main/java/seedu/command/HelpCommand.java diff --git a/src/main/java/seedu/command/HelpCommand.java b/src/main/java/seedu/command/HelpCommand.java new file mode 100644 index 0000000000..0d337cd234 --- /dev/null +++ b/src/main/java/seedu/command/HelpCommand.java @@ -0,0 +1,9 @@ +package seedu.command; + +import seedu.ui.TextUi; + +public class HelpCommand extends Command { + public void execute() { + TextUi.helpMessage(); + } +} From eb387467bda8224054a61b2c547685760a1701fa Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Wed, 13 Oct 2021 10:59:41 +0800 Subject: [PATCH 258/756] Add helpMessage to TextUi for help command. --- src/main/java/seedu/ui/TextUi.java | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 24b9754937..d5e9b1ced2 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -126,4 +126,28 @@ public static void exitMessage() { String message = "ConTech will now shutdown.\n" + "We hope you have enjoyed using it."; printDoubleLineMessage(message); } + + public static void helpMessage() { + String message = "add: ConTech adds the specified contact with provided parameters.\n" + + " Parameters: -n NAME -g GITHUB -e EMAIL -te TELEGRAM -l LINKEDIN -tw TWITTER\n" + + " Note: Parameters need not be in order and are optional except for NAME.\n" + + " Example: add -n John Doe -g johndoecoder -e john@email.com -te johndoe\n\n" + + "list: Displays the name of all saved contacts.\n" + + " Example: list\n\n" + + "edit: Edit any parameter in an existing contact.\n" + + " Parameters: INDEX -n NAME -g GITHUB -e EMAIL -te TELEGRAM -l LINKEDIN -tw TWITTER\n" + + " Note: Parameters need not be in order and are optional except for INDEX.\n" + + " Example: edit 1 -e john.doe@email.com\n\n" + + "view: Displays all details for index specified contact.\n" + + " Parameter: INDEX\n" + + " Note: Index starts from 0.\n" + + " Example: view 2\n\n" + + "rm: Deletes the index specified contact.\n" + + " Parameter: INDEX\n" + + " Note: Index starts from 0.\n" + + " Example: rm 0\n\n" + + "help: Displays application usage instructions.\n" + + " Example: help"; + printDoubleLineMessage(message); + } } From 6ce4eb1f3f94893ee2d4ca5959d84050b9d05d41 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Wed, 13 Oct 2021 13:51:42 +0800 Subject: [PATCH 259/756] Refactor helpMessage to comply with checkstyle. --- src/main/java/seedu/ui/TextUi.java | 40 +++++++++++++++--------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index d5e9b1ced2..f93a03634c 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -128,26 +128,26 @@ public static void exitMessage() { } public static void helpMessage() { - String message = "add: ConTech adds the specified contact with provided parameters.\n" + - " Parameters: -n NAME -g GITHUB -e EMAIL -te TELEGRAM -l LINKEDIN -tw TWITTER\n" + - " Note: Parameters need not be in order and are optional except for NAME.\n" + - " Example: add -n John Doe -g johndoecoder -e john@email.com -te johndoe\n\n" + - "list: Displays the name of all saved contacts.\n" + - " Example: list\n\n" + - "edit: Edit any parameter in an existing contact.\n" + - " Parameters: INDEX -n NAME -g GITHUB -e EMAIL -te TELEGRAM -l LINKEDIN -tw TWITTER\n" + - " Note: Parameters need not be in order and are optional except for INDEX.\n" + - " Example: edit 1 -e john.doe@email.com\n\n" + - "view: Displays all details for index specified contact.\n" + - " Parameter: INDEX\n" + - " Note: Index starts from 0.\n" + - " Example: view 2\n\n" + - "rm: Deletes the index specified contact.\n" + - " Parameter: INDEX\n" + - " Note: Index starts from 0.\n" + - " Example: rm 0\n\n" + - "help: Displays application usage instructions.\n" + - " Example: help"; + String message = "add: ConTech adds the specified contact with provided parameters.\n" + + " Parameters: -n NAME -g GITHUB -e EMAIL -te TELEGRAM -l LINKEDIN -tw TWITTER\n" + + " Note: Parameters need not be in order and are optional except for NAME.\n" + + " Example: add -n John Doe -g johndoecoder -e john@email.com -te johndoe\n\n" + + "list: Displays the name of all saved contacts.\n" + + " Example: list\n\n" + + "edit: Edit any parameter in an existing contact.\n" + + " Parameters: INDEX -n NAME -g GITHUB -e EMAIL -te TELEGRAM -l LINKEDIN -tw TWITTER\n" + + " Note: Parameters need not be in order and are optional except for INDEX.\n" + + " Example: edit 1 -e john.doe@email.com\n\n" + + "view: Displays all details for index specified contact.\n" + + " Parameter: INDEX\n" + + " Note: Index starts from 0.\n" + + " Example: view 2\n\n" + + "rm: Deletes the index specified contact.\n" + + " Parameter: INDEX\n" + + " Note: Index starts from 0.\n" + + " Example: rm 0\n\n" + + "help: Displays application usage instructions.\n" + + " Example: help"; printDoubleLineMessage(message); } } From 7d2f9dbbe3266e039dc49af6fc2de0acbacc8cf4 Mon Sep 17 00:00:00 2001 From: lezong Date: Wed, 13 Oct 2021 14:23:13 +0800 Subject: [PATCH 260/756] Add assertions --- .../java/seedu/command/DeleteContactCommand.java | 6 ++++-- src/main/java/seedu/command/ViewContactCommand.java | 1 + src/main/java/seedu/parser/IndexParser.java | 5 ++++- src/main/java/seedu/storage/ContactsDecoder.java | 13 ------------- 4 files changed, 9 insertions(+), 16 deletions(-) diff --git a/src/main/java/seedu/command/DeleteContactCommand.java b/src/main/java/seedu/command/DeleteContactCommand.java index 93d7b4e9ab..5142a78be0 100644 --- a/src/main/java/seedu/command/DeleteContactCommand.java +++ b/src/main/java/seedu/command/DeleteContactCommand.java @@ -9,8 +9,8 @@ public class DeleteContactCommand extends Command { private final int contactIndex; - public DeleteContactCommand(int deletedIndex) { - this.contactIndex = deletedIndex; + public DeleteContactCommand(int contactIndex) { + this.contactIndex = contactIndex; } public int getDeletedIndex() { @@ -24,6 +24,7 @@ private void deleteOnConfirmation(Contact deletedContact) { this.contactList.deleteContact(contactIndex); TextUi.deleteContactMessage(deletedContact.getName(), contactList.getListSize()); } else { + assert !userDeleteConfirmation.equalsIgnoreCase("y"); TextUi.cancelDeleteContactMessage(); } } @@ -32,6 +33,7 @@ public void execute() { try { // throws IndexOutOfBoundsException if index is outside of the range Contact deletedContact = IndexParser.getContactFromIndex(contactIndex, contactList); + assert contactIndex >= 0 && contactIndex < contactList.getListSize(); deleteOnConfirmation(deletedContact); } catch (IndexOutOfBoundsException e) { ExceptionTextUi.numOutOfRangeMessage(contactList.getListSize()); diff --git a/src/main/java/seedu/command/ViewContactCommand.java b/src/main/java/seedu/command/ViewContactCommand.java index 1ab2aae171..b1717287a2 100644 --- a/src/main/java/seedu/command/ViewContactCommand.java +++ b/src/main/java/seedu/command/ViewContactCommand.java @@ -19,6 +19,7 @@ public int getIndex() { public void execute() { try { Contact viewingContact = IndexParser.getContactFromIndex(contactIndex, contactList); + assert contactIndex >= 0 && contactIndex < contactList.getListSize(); TextUi.viewContactMessage(viewingContact, contactIndex); } catch (IndexOutOfBoundsException e) { ExceptionTextUi.numOutOfRangeMessage(contactList.getListSize()); diff --git a/src/main/java/seedu/parser/IndexParser.java b/src/main/java/seedu/parser/IndexParser.java index 28ab1dbd09..866f09ae57 100644 --- a/src/main/java/seedu/parser/IndexParser.java +++ b/src/main/java/seedu/parser/IndexParser.java @@ -14,12 +14,15 @@ public class IndexParser { public static int getIndexFromInput(String userInput, String command) throws NumberFormatException, MissingArgException { + //split user input into 2 strings: command word string and index string String[] destructuredInputs = userInput.split(" ", COMD_INDEX_LENGTH); if (destructuredInputs.length <= COMD_WORD_LENGTH) { throw new MissingArgException(); } + assert destructuredInputs.length == 2; + // split index string into words String[] indexSplit = destructuredInputs[INDEX_POSITION].trim().split(" "); - // throws NumberFormatExcept if not integer + // takes only the first word/ element as given user input, and throws NumberFormatExcept if it is not integer return Integer.parseInt(indexSplit[SIGNIFICANT_INDEX_POSITION].trim()); } diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index b615e39042..00998d6560 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -30,9 +30,6 @@ public static ContactList readContacts(File contactFile) throws FileErrorExcepti private static void decodeContact(ContactList contactList, String contactText) { String[] destructuredInputs = contactText.split(SEPARATOR); - String[] compiledDetails = new String[NUMBER_OF_FIELDS]; - assert destructuredInputs.length > 0; - decodeDetails(compiledDetails, destructuredInputs); // Add the decoded details into the contact list try { String contactName = destructuredInputs[DetailType.NAME.getIndex()]; @@ -48,14 +45,4 @@ private static void decodeContact(ContactList contactList, String contactText) { ExceptionTextUi.corruptLineMessage(contactText); } } - - private static void decodeDetails(String[] compiledDetails, String[] destructuredInputs) { - if (compiledDetails.length != destructuredInputs.length) { - return; - } - assert compiledDetails.length == NUMBER_OF_FIELDS; - for (int i = 0; i < NUMBER_OF_FIELDS; i++) { - compiledDetails[i] = destructuredInputs[i]; - } - } } From d0b86ff0ff5475a5ef98a319369e3d4ad5c4d771 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 13 Oct 2021 15:19:12 +0800 Subject: [PATCH 261/756] Add logging for regex checks --- src/main/java/seedu/parser/ContactParser.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index 2bad1cb1bc..b3df3f7381 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -12,6 +12,9 @@ import seedu.exception.MissingArgException; import seedu.exception.MissingDetailException; +import java.util.logging.Level; +import java.util.logging.Logger; + public abstract class ContactParser { public static final int CONTACT_PARAMS_START_INDEX = 1; public static final int NUMBER_OF_DETAILS = 2; @@ -32,6 +35,8 @@ public abstract class ContactParser { public static final String EMAIL_FLAG = "e"; public static final String LINKEDIN_FLAG = "l"; + private static final Logger LOGGER = Logger.getLogger(ContactParser.class.getName()); + public abstract String[] parseContactDetails(String userInput) throws InvalidFlagException, MissingArgException, MissingDetailException, ForbiddenDetailException, InvalidNameException, InvalidGithubUsernameException, InvalidTelegramUsernameException, @@ -101,6 +106,7 @@ private void checkEmailRegex(String detailToParse) throws InvalidEmailException //allow lowercase email ids String emailRegex = "^([\\w-\\.]+){1,64}@([\\w&&[^_]]+){2,255}.[a-z]{2,}$"; if (!detailToParse.matches(emailRegex)) { + LOGGER.log(Level.INFO, "Regex check for Email id failed"); throw new InvalidEmailException(); } } @@ -109,6 +115,7 @@ private void checkLinkedinUsernameRegex(String detailToParse) throws InvalidLink //allows lowercase, numbers, underscore and hyphen. Length must be 3-100 characters String linkedinRegex = "^[a-z0-9-_]{3,100}$"; if (!detailToParse.matches(linkedinRegex)) { + LOGGER.log(Level.INFO, "Regex check for Linkedin failed"); throw new InvalidLinkedinUsernameException(); } } @@ -117,6 +124,7 @@ private void checkTwitterUsernameRegex(String detailToParse) throws InvalidTwitt //allows lowercase, numbers and underscore. Length must be max 15 characters String twitterRegex = "^[a-z0-9_]{1,15}$"; if (!detailToParse.matches(twitterRegex)) { + LOGGER.log(Level.INFO, "Regex check for Name failed"); throw new InvalidTwitterUsernameException(); } } @@ -125,6 +133,7 @@ private void checkTelegramUsernameRegex(String detailToParse) throws InvalidTele //allows uppercase, lowercase, numbers and underscore. Length must be atleast 5 characters String telegramRegex = "^[a-zA-Z0-9_]{5,}$"; if (!detailToParse.matches(telegramRegex)) { + LOGGER.log(Level.INFO, "Regex check for Telegram username failed"); throw new InvalidTelegramUsernameException(); } } @@ -136,6 +145,7 @@ private void checkGithubUsernameRegex(String detailToParse) throws InvalidGithub //Maximum is 39 characters. String githubUsernameRegex = "^[a-z\\d](?:[a-z\\d]|-(?=[a-z\\d])){0,39}$"; if (!detailToParse.matches(githubUsernameRegex)) { + LOGGER.log(Level.INFO, "Regex check for Github username failed"); throw new InvalidGithubUsernameException(); } } @@ -144,6 +154,7 @@ private void checkNameRegex(String detailToParse) throws InvalidNameException { //only letters and spaces allowed String nameRegex = "^[ A-Za-z]+$"; if (!detailToParse.matches(nameRegex)) { + LOGGER.log(Level.INFO, "Regex check for name failed"); throw new InvalidNameException(); } } From 975eb830670db1da64bca72f10812ddc9c533c08 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 13 Oct 2021 15:32:27 +0800 Subject: [PATCH 262/756] Add assertions --- src/main/java/seedu/parser/ContactParser.java | 2 ++ src/main/java/seedu/parser/IndexParser.java | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index b3df3f7381..8cf88c0dd2 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -78,6 +78,8 @@ public void checkRegex(String flag, String detailToParse) throws InvalidGithubUsernameException, InvalidNameException, InvalidFlagException, InvalidTelegramUsernameException, InvalidTwitterUsernameException, InvalidLinkedinUsernameException, InvalidEmailException { + assert flag != null; + assert detailToParse != null; switch (flag) { case NAME_FLAG: checkNameRegex(detailToParse); diff --git a/src/main/java/seedu/parser/IndexParser.java b/src/main/java/seedu/parser/IndexParser.java index 866f09ae57..724a003a22 100644 --- a/src/main/java/seedu/parser/IndexParser.java +++ b/src/main/java/seedu/parser/IndexParser.java @@ -24,7 +24,6 @@ public static int getIndexFromInput(String userInput, String command) String[] indexSplit = destructuredInputs[INDEX_POSITION].trim().split(" "); // takes only the first word/ element as given user input, and throws NumberFormatExcept if it is not integer return Integer.parseInt(indexSplit[SIGNIFICANT_INDEX_POSITION].trim()); - } public static Contact getContactFromIndex(int index, ContactList contactList) throws IndexOutOfBoundsException { From e7d3836650a24f9d5b15fb31c5aa00a1aeef7549 Mon Sep 17 00:00:00 2001 From: ng-andre Date: Wed, 13 Oct 2021 22:27:07 +0800 Subject: [PATCH 263/756] Update dependencies and manifest file --- META-INF/MANIFEST.MF | 3 +++ build.gradle | 16 ++++++++++++++++ src/main/java/META-INF/MANIFEST.MF | 3 +++ 3 files changed, 22 insertions(+) create mode 100644 META-INF/MANIFEST.MF create mode 100644 src/main/java/META-INF/MANIFEST.MF diff --git a/META-INF/MANIFEST.MF b/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..19e86fe56e --- /dev/null +++ b/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: seedu.duke.Duke + diff --git a/build.gradle b/build.gradle index b0c5528fb5..d8641cf35d 100644 --- a/build.gradle +++ b/build.gradle @@ -12,6 +12,21 @@ repositories { dependencies { testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.5.0' testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.5.0' + + String javaFxVersion = '11' + + implementation group: 'org.openjfx', name: 'javafx-base', version: javaFxVersion, classifier: 'win' + implementation group: 'org.openjfx', name: 'javafx-base', version: javaFxVersion, classifier: 'mac' + implementation group: 'org.openjfx', name: 'javafx-base', version: javaFxVersion, classifier: 'linux' + implementation group: 'org.openjfx', name: 'javafx-controls', version: javaFxVersion, classifier: 'win' + implementation group: 'org.openjfx', name: 'javafx-controls', version: javaFxVersion, classifier: 'mac' + implementation group: 'org.openjfx', name: 'javafx-controls', version: javaFxVersion, classifier: 'linux' + implementation group: 'org.openjfx', name: 'javafx-fxml', version: javaFxVersion, classifier: 'win' + implementation group: 'org.openjfx', name: 'javafx-fxml', version: javaFxVersion, classifier: 'mac' + implementation group: 'org.openjfx', name: 'javafx-fxml', version: javaFxVersion, classifier: 'linux' + implementation group: 'org.openjfx', name: 'javafx-graphics', version: javaFxVersion, classifier: 'win' + implementation group: 'org.openjfx', name: 'javafx-graphics', version: javaFxVersion, classifier: 'mac' + implementation group: 'org.openjfx', name: 'javafx-graphics', version: javaFxVersion, classifier: 'linux' } test { @@ -44,3 +59,4 @@ checkstyle { run{ standardInput = System.in } + diff --git a/src/main/java/META-INF/MANIFEST.MF b/src/main/java/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..19e86fe56e --- /dev/null +++ b/src/main/java/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: seedu.duke.Duke + From 6fab9156a228f2e25b9354e1ea65215fbd91b260 Mon Sep 17 00:00:00 2001 From: ng-andre Date: Wed, 13 Oct 2021 22:30:22 +0800 Subject: [PATCH 264/756] Remove unused imports --- src/main/java/seedu/command/EditContactCommand.java | 1 - src/main/java/seedu/storage/ContactsDecoder.java | 1 - 2 files changed, 2 deletions(-) diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index 7f0d837f16..6e74cf19bd 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -1,6 +1,5 @@ package seedu.command; -import seedu.contact.Contact; import seedu.exception.InvalidFlagException; import seedu.ui.TextUi; import seedu.ui.ExceptionTextUi; diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index 00998d6560..d2c807b6a3 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -7,7 +7,6 @@ import seedu.ui.ExceptionTextUi; import static seedu.storage.Storage.SEPARATOR; -import static seedu.parser.ContactParser.NUMBER_OF_FIELDS; import java.io.File; import java.io.FileNotFoundException; From 5ef6cac4088db95bbd99faaccd4b90315dd4e33a Mon Sep 17 00:00:00 2001 From: ng-andre Date: Wed, 13 Oct 2021 22:30:34 +0800 Subject: [PATCH 265/756] Remove unused constant --- src/main/java/seedu/parser/ContactParser.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index 8cf88c0dd2..a1e5aea813 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -25,7 +25,6 @@ public abstract class ContactParser { public static final String DETAIL_SEPARATOR = " -"; public static final int FLAG_INDEX_IN_DETAILS = 0; public static final int DETAIL_INDEX_IN_DETAILS = 1; - public static final int EDIT_USER_INDEX = 1; public static final int USER_INFO_INDEX = 2; public static final String NAME_FLAG = "n"; From 57876b0d41cbd9520856f38a1ef3146d3754cb7e Mon Sep 17 00:00:00 2001 From: ng-andre Date: Wed, 13 Oct 2021 22:31:00 +0800 Subject: [PATCH 266/756] Remove unused parameter --- src/main/java/seedu/parser/IndexParser.java | 2 +- src/main/java/seedu/parser/MainParser.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/seedu/parser/IndexParser.java b/src/main/java/seedu/parser/IndexParser.java index 724a003a22..660576cab9 100644 --- a/src/main/java/seedu/parser/IndexParser.java +++ b/src/main/java/seedu/parser/IndexParser.java @@ -12,7 +12,7 @@ public class IndexParser { private static final int COMD_INDEX_LENGTH = 2; - public static int getIndexFromInput(String userInput, String command) + public static int getIndexFromInput(String userInput) throws NumberFormatException, MissingArgException { //split user input into 2 strings: command word string and index string String[] destructuredInputs = userInput.split(" ", COMD_INDEX_LENGTH); diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index ad1e3cfe95..0279ab7e56 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -124,7 +124,7 @@ private Command parseEditContact(String userInput) { // userInput is raw user in try { String[] details = editContactParser.parseContactDetails(userInput); //throws InvalidFlagException, MissingDetailException, MissingArgException - int userIndex = IndexParser.getIndexFromInput(userInput, EDIT_CONTACT_COMD); //throws MissingArgException + int userIndex = IndexParser.getIndexFromInput(userInput); //throws MissingArgException return new EditContactCommand(details, userIndex); } catch (InvalidFlagException e) { return new FailedCommand(FailedCommandType.INVALID_FLAG); @@ -153,7 +153,7 @@ private Command parseEditContact(String userInput) { // userInput is raw user in private Command parseViewContact(String userInput) { try { - int viewedIndex = IndexParser.getIndexFromInput(userInput, VIEW_CONTACT_COMD); + int viewedIndex = IndexParser.getIndexFromInput(userInput); return new ViewContactCommand(viewedIndex); } catch (MissingArgException e) { return new FailedCommand(FailedCommandType.MISSING_ARG); @@ -164,7 +164,7 @@ private Command parseViewContact(String userInput) { private Command parseDeleteContact(String userInput) { try { - int deletedIndex = IndexParser.getIndexFromInput(userInput, DELETE_CONTACT_COMD); + int deletedIndex = IndexParser.getIndexFromInput(userInput); return new DeleteContactCommand(deletedIndex); } catch (MissingArgException e) { return new FailedCommand(FailedCommandType.MISSING_ARG); From 0667f6037ca881f36b9191a8d9f0321031abd79e Mon Sep 17 00:00:00 2001 From: ng-andre Date: Wed, 13 Oct 2021 22:31:19 +0800 Subject: [PATCH 267/756] Remove unused code --- src/main/java/seedu/parser/FailedCommandType.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/FailedCommandType.java b/src/main/java/seedu/parser/FailedCommandType.java index f2d868b5c7..a2121c4748 100644 --- a/src/main/java/seedu/parser/FailedCommandType.java +++ b/src/main/java/seedu/parser/FailedCommandType.java @@ -4,5 +4,5 @@ public enum FailedCommandType { GENERAL, INVALID_FLAG, MISSING_ARG, MISSING_DETAIL, INVALID_NUM, INVALID_FORMAT, NUM_OUT_OF_BOUND, INVALID_INDEX, MISSING_NAME, FORBIDDEN_DETAIL, INVALID_NAME, INVALID_GITHUB_USERNAME, - INVALID_LINKEDIN, INVALID_TELEGRAM, INVALID_MAIL, INVALID_TWITTER; + INVALID_LINKEDIN, INVALID_TELEGRAM, INVALID_MAIL, INVALID_TWITTER } From d6300874bbe0683b461ae3bc6e2c5c1c86fb6589 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 13 Oct 2021 23:54:54 +0800 Subject: [PATCH 268/756] Refactor AddContactCommand to accept a String array and decipher details from there --- .../java/seedu/command/AddContactCommand.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/seedu/command/AddContactCommand.java b/src/main/java/seedu/command/AddContactCommand.java index 2221cf6508..3d6de7f4b6 100644 --- a/src/main/java/seedu/command/AddContactCommand.java +++ b/src/main/java/seedu/command/AddContactCommand.java @@ -1,6 +1,7 @@ package seedu.command; import seedu.contact.Contact; +import seedu.contact.DetailType; import seedu.ui.TextUi; public class AddContactCommand extends Command { @@ -35,14 +36,13 @@ public String getGithub() { return github; } - public AddContactCommand(String name, String github, String linkedin, String telegram, String twitter, - String email) { - this.name = name; - this.github = github; - this.linkedin = linkedin; - this.telegram = telegram; - this.twitter = twitter; - this.email = email; + public AddContactCommand(String[] details) { + this.name = details[DetailType.NAME.getIndex()]; + this.github = details[DetailType.GITHUB.getIndex()]; + this.linkedin = details[DetailType.LINKEDIN.getIndex()]; + this.telegram = details[DetailType.TELEGRAM.getIndex()]; + this.twitter = details[DetailType.TWITTER.getIndex()]; + this.email = details[DetailType.EMAIL.getIndex()]; } public void execute() { From 3f6e38c9ba4c2b081ffc88a82433059c1d1987b2 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 13 Oct 2021 23:57:42 +0800 Subject: [PATCH 269/756] Refactor parseAddContact in MainParser due to changes to AddContactCommand --- src/main/java/seedu/parser/MainParser.java | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index ad1e3cfe95..414c1a0a96 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -10,7 +10,6 @@ import seedu.command.ExitCommand; import seedu.command.ListContactsCommand; -import seedu.contact.DetailType; import seedu.exception.ForbiddenDetailException; import seedu.exception.InvalidEmailException; import seedu.exception.InvalidFlagException; @@ -87,13 +86,7 @@ private Command parseAddContact(String userInput) { throw new MissingNameException(); } assert details.length == NUMBER_OF_FIELDS; - String name = details[DetailType.NAME.getIndex()]; - String github = details[DetailType.GITHUB.getIndex()]; - String linkedin = details[DetailType.LINKEDIN.getIndex()]; - String telegram = details[DetailType.TELEGRAM.getIndex()]; - String twitter = details[DetailType.TWITTER.getIndex()]; - String email = details[DetailType.EMAIL.getIndex()]; - return new AddContactCommand(name, github, linkedin, telegram, twitter, email); + return new AddContactCommand(details); } catch (InvalidFlagException e) { return new FailedCommand(FailedCommandType.INVALID_FLAG); } catch (MissingArgException e) { From 08c53f6344e521f95df8c19fcf12519f1150ffca Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 13 Oct 2021 23:58:43 +0800 Subject: [PATCH 270/756] Update JUnit tests in MainParserTest due to refactored AddContactCommand --- src/test/java/seedu/parser/MainParserTest.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/test/java/seedu/parser/MainParserTest.java b/src/test/java/seedu/parser/MainParserTest.java index 3676cb7573..8545b30102 100644 --- a/src/test/java/seedu/parser/MainParserTest.java +++ b/src/test/java/seedu/parser/MainParserTest.java @@ -107,8 +107,8 @@ public void parseDeleteCommand_outOfRangeIndex_expectFailedCommandType() { public void parseAddCommand_validInputsWithIrregularSpaces_expectAddContactCommand() { testUserInput = " add -n andre -g ng-andre -l linkedin -tw twit -te teles123 -e andre@twix.com"; AddContactCommand actualCommand = getParsedCommand(testUserInput, AddContactCommand.class); - AddContactCommand expectedCommand = new AddContactCommand("andre", "ng-andre", - "linkedin", "teles123", "twit", "andre@twix.com"); + String[] details = {"andre", "ng-andre", "linkedin", "teles123", "twit", "andre@twix.com"}; + AddContactCommand expectedCommand = new AddContactCommand(details); assertEquals(expectedCommand.getName(), actualCommand.getName()); assertEquals(expectedCommand.getGithub(), actualCommand.getGithub()); assertEquals(expectedCommand.getLinkedin(), actualCommand.getLinkedin()); @@ -121,7 +121,8 @@ public void parseAddCommand_validInputsWithIrregularSpaces_expectAddContactComma public void parseAddCommand_validInputsWithExtraCharacters_expectAddContactCommand() { testUserInput = " add 1231267azldasd -n marcus -g marcus-bory "; AddContactCommand actualCommand = getParsedCommand(testUserInput, AddContactCommand.class); - AddContactCommand expectedCommand = new AddContactCommand("marcus", "marcus-bory", null, null, null, null); + String[] details = {"marcus", "marcus-bory", null, null, null, null}; + AddContactCommand expectedCommand = new AddContactCommand(details); assertEquals(expectedCommand.getName(), actualCommand.getName()); assertEquals(expectedCommand.getGithub(), actualCommand.getGithub()); } @@ -130,8 +131,8 @@ public void parseAddCommand_validInputsWithExtraCharacters_expectAddContactComma public void parseAddCommand_validInputs_expectAddContactCommand() { testUserInput = "add -n andre -g ng-andre -l linkedin -tw twit -te teles123 -e andre@twix.com"; final AddContactCommand actualCommand = getParsedCommand(testUserInput, AddContactCommand.class); - final AddContactCommand expectedCommand = new AddContactCommand("andre", "ng-andre", - "linkedin", "teles123", "twit", "andre@twix.com"); + String[] details = {"andre", "ng-andre", "linkedin", "teles123", "twit", "andre@twix.com"}; + final AddContactCommand expectedCommand = new AddContactCommand(details); assertEquals(expectedCommand.getName(), actualCommand.getName()); assertEquals(expectedCommand.getGithub(), actualCommand.getGithub()); assertEquals(expectedCommand.getLinkedin(), actualCommand.getLinkedin()); @@ -141,11 +142,11 @@ public void parseAddCommand_validInputs_expectAddContactCommand() { } @Test - public void parseAddCommand_validInputsWithFlags_expectAddContactCommand() { + public void parseAddCommand_validInputsWithPartialFlags_expectAddContactCommand() { testUserInput = " add -n ashraf -g fdada-121 -tw 66123ada -e ash@yahoo.com "; AddContactCommand actualCommand = getParsedCommand(testUserInput, AddContactCommand.class); - AddContactCommand expectedCommand = new AddContactCommand("ashraf", "fdada-121", - null, null, "66123ada", "ash@yahoo.com"); + String[] details = {"ashraf", "fdada-121", null, null, "66123ada", "ash@yahoo.com"}; + AddContactCommand expectedCommand = new AddContactCommand(details); assertEquals(expectedCommand.getName(), actualCommand.getName()); assertEquals(expectedCommand.getGithub(), actualCommand.getGithub()); assertEquals(expectedCommand.getTwitter(), actualCommand.getTwitter()); From 91e63a23540d7469c20970c9c856332613b4c811 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 14 Oct 2021 00:00:11 +0800 Subject: [PATCH 271/756] Refactor MainParser to abstract out InvalidDetailCommand parsing --- src/main/java/seedu/parser/MainParser.java | 61 ++++++++++++---------- 1 file changed, 33 insertions(+), 28 deletions(-) diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 414c1a0a96..126c78215e 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -5,6 +5,7 @@ import seedu.command.DeleteContactCommand; import seedu.command.Command; import seedu.command.HelpCommand; +import seedu.command.InvalidDetailCommand; import seedu.command.ViewContactCommand; import seedu.command.FailedCommand; import seedu.command.ExitCommand; @@ -95,20 +96,9 @@ private Command parseAddContact(String userInput) { return new FailedCommand(FailedCommandType.MISSING_NAME); } catch (MissingDetailException e) { return new FailedCommand(FailedCommandType.MISSING_DETAIL); - } catch (ForbiddenDetailException e) { - return new FailedCommand(FailedCommandType.FORBIDDEN_DETAIL); - } catch (InvalidNameException e) { - return new FailedCommand(FailedCommandType.INVALID_NAME); - } catch (InvalidGithubUsernameException e) { - return new FailedCommand(FailedCommandType.INVALID_GITHUB_USERNAME); - } catch (InvalidEmailException e) { - return new FailedCommand(FailedCommandType.INVALID_MAIL); - } catch (InvalidTelegramUsernameException e) { - return new FailedCommand(FailedCommandType.INVALID_TELEGRAM); - } catch (InvalidTwitterUsernameException e) { - return new FailedCommand(FailedCommandType.INVALID_TWITTER); - } catch (InvalidLinkedinUsernameException e) { - return new FailedCommand(FailedCommandType.INVALID_LINKEDIN); + } catch (InvalidNameException | InvalidGithubUsernameException | InvalidEmailException | InvalidLinkedinUsernameException + | InvalidTelegramUsernameException | InvalidTwitterUsernameException | ForbiddenDetailException e) { + return parseInvalidDetailCommand(e); } } @@ -127,23 +117,38 @@ private Command parseEditContact(String userInput) { // userInput is raw user in return new FailedCommand(FailedCommandType.INVALID_INDEX); } catch (MissingDetailException e) { return new FailedCommand(FailedCommandType.MISSING_DETAIL); - } catch (ForbiddenDetailException e) { - return new FailedCommand(FailedCommandType.FORBIDDEN_DETAIL); - } catch (InvalidNameException e) { - return new FailedCommand(FailedCommandType.INVALID_NAME); - } catch (InvalidGithubUsernameException e) { - return new FailedCommand(FailedCommandType.INVALID_GITHUB_USERNAME); - } catch (InvalidEmailException e) { - return new FailedCommand(FailedCommandType.INVALID_MAIL); - } catch (InvalidTelegramUsernameException e) { - return new FailedCommand(FailedCommandType.INVALID_TELEGRAM); - } catch (InvalidTwitterUsernameException e) { - return new FailedCommand(FailedCommandType.INVALID_TWITTER); - } catch (InvalidLinkedinUsernameException e) { - return new FailedCommand(FailedCommandType.INVALID_LINKEDIN); + } catch (InvalidNameException | InvalidGithubUsernameException | InvalidEmailException | InvalidLinkedinUsernameException + | InvalidTelegramUsernameException | InvalidTwitterUsernameException | ForbiddenDetailException e) { + return parseInvalidDetailCommand(e); } } + private Command parseInvalidDetailCommand(Exception e) { + if (e instanceof InvalidNameException) { + return new InvalidDetailCommand(FailedCommandType.INVALID_NAME); + } + if (e instanceof InvalidGithubUsernameException) { + return new InvalidDetailCommand(FailedCommandType.INVALID_GITHUB_USERNAME); + } + if (e instanceof InvalidEmailException) { + return new InvalidDetailCommand(FailedCommandType.INVALID_MAIL); + } + if (e instanceof InvalidTelegramUsernameException) { + return new InvalidDetailCommand(FailedCommandType.INVALID_TELEGRAM); + } + if (e instanceof InvalidTwitterUsernameException) { + return new InvalidDetailCommand(FailedCommandType.INVALID_TWITTER); + } + if (e instanceof InvalidLinkedinUsernameException) { + return new InvalidDetailCommand(FailedCommandType.INVALID_LINKEDIN); + } + if (e instanceof ForbiddenDetailException) { + return new InvalidDetailCommand(FailedCommandType.FORBIDDEN_DETAIL); + } + assert false; // Exception should be caught before this + return new FailedCommand(FailedCommandType.GENERAL); + } + private Command parseViewContact(String userInput) { try { int viewedIndex = IndexParser.getIndexFromInput(userInput, VIEW_CONTACT_COMD); From b8c028bf8d696a145742c6528290289bfec373eb Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 14 Oct 2021 00:00:43 +0800 Subject: [PATCH 272/756] Refactor FailedCommand by abstracting out cases --- .../java/seedu/command/FailedCommand.java | 59 ++++++++++--------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/src/main/java/seedu/command/FailedCommand.java b/src/main/java/seedu/command/FailedCommand.java index 64e331a018..225875c3ef 100644 --- a/src/main/java/seedu/command/FailedCommand.java +++ b/src/main/java/seedu/command/FailedCommand.java @@ -19,51 +19,56 @@ public void execute() { case GENERAL: ExceptionTextUi.invalidCommandMessage(); break; + case INVALID_FLAG: // Fallthrough + case INVALID_INDEX: // Fallthrough + case INVALID_NUM: // Fallthrough + case INVALID_FORMAT: // Fallthrough + case NUM_OUT_OF_BOUND: // Fallthrough + invalidUserInputExecute(); + break; + case MISSING_ARG: // Fallthrough + case MISSING_DETAIL: // Fallthrough + case MISSING_NAME: // Fallthrough + missingUserInputExecute(); + break; + default: + return; + } + } + + private void invalidUserInputExecute() { + switch (type) { case INVALID_FLAG: ExceptionTextUi.invalidFlagMessage(); break; case INVALID_INDEX: ExceptionTextUi.invalidIndexMessage(); break; - case MISSING_ARG: - ExceptionTextUi.missingArgMessage(); - break; - case MISSING_DETAIL: - ExceptionTextUi.missingDetailMessage(); - break; case INVALID_NUM: ExceptionTextUi.invalidNumMessage(); break; case INVALID_FORMAT: ExceptionTextUi.invalidFormatMessage(); break; - case INVALID_NAME: - ExceptionTextUi.invalidNameInput(); - break; - case INVALID_GITHUB_USERNAME: - ExceptionTextUi.invalidGithubUsernameInput(); - break; - case INVALID_TELEGRAM: - ExceptionTextUi.invalidTelegramUsernameInput(); - break; - case INVALID_LINKEDIN: - ExceptionTextUi.invalidLinkedinInput(); - break; - case INVALID_MAIL: - ExceptionTextUi.invalidEmailInput(); - break; - case INVALID_TWITTER: - ExceptionTextUi.invalidTwitterUsernameInput(); - break; case NUM_OUT_OF_BOUND: ExceptionTextUi.numOutOfRangeMessage(contactList.getListSize() - 1); break; + default: + return; + } + } + + private void missingUserInputExecute() { + switch (type) { + case MISSING_ARG: + ExceptionTextUi.missingArgMessage(); + break; + case MISSING_DETAIL: + ExceptionTextUi.missingDetailMessage(); + break; case MISSING_NAME: ExceptionTextUi.missingNameMessage(); break; - case FORBIDDEN_DETAIL: - ExceptionTextUi.forbiddenDetailMessage(); - break; default: return; } From 7601c2886f5678e83a9e13e0f4b136a42282019d Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 14 Oct 2021 00:02:07 +0800 Subject: [PATCH 273/756] Implement InvalidDetailCommand to isolate invalid detail failures --- .../seedu/command/InvalidDetailCommand.java | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 src/main/java/seedu/command/InvalidDetailCommand.java diff --git a/src/main/java/seedu/command/InvalidDetailCommand.java b/src/main/java/seedu/command/InvalidDetailCommand.java new file mode 100644 index 0000000000..6fe737efa3 --- /dev/null +++ b/src/main/java/seedu/command/InvalidDetailCommand.java @@ -0,0 +1,44 @@ +package seedu.command; + +import seedu.parser.FailedCommandType; +import seedu.ui.ExceptionTextUi; + +public class InvalidDetailCommand extends Command { + private FailedCommandType type; + + public InvalidDetailCommand(FailedCommandType type) { + this.type = type; + } + + public FailedCommandType getType() { + return type; + } + + public void execute() { + switch (type) { + case INVALID_NAME: + ExceptionTextUi.invalidNameInput(); + break; + case INVALID_GITHUB_USERNAME: + ExceptionTextUi.invalidGithubUsernameInput(); + break; + case INVALID_TELEGRAM: + ExceptionTextUi.invalidTelegramUsernameInput(); + break; + case INVALID_LINKEDIN: + ExceptionTextUi.invalidLinkedinInput(); + break; + case INVALID_MAIL: + ExceptionTextUi.invalidEmailInput(); + break; + case INVALID_TWITTER: + ExceptionTextUi.invalidTwitterUsernameInput(); + break; + case FORBIDDEN_DETAIL: + ExceptionTextUi.forbiddenDetailMessage(); + break; + default: + return; + } + } +} From b50d3e506941c92c9751708ca1f0cb044fe08629 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 14 Oct 2021 00:02:46 +0800 Subject: [PATCH 274/756] Rename JUnit test for delete command to expect Exception --- src/test/java/seedu/parser/MainParserTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/seedu/parser/MainParserTest.java b/src/test/java/seedu/parser/MainParserTest.java index 8545b30102..6a9b8169aa 100644 --- a/src/test/java/seedu/parser/MainParserTest.java +++ b/src/test/java/seedu/parser/MainParserTest.java @@ -86,7 +86,7 @@ public void parseDeleteCommand_invalidNumber_expectFailedCommandType() { @Test - public void parseDeleteCommand_outOfRangeIndex_expectFailedCommandType() { + public void parseDeleteCommand_outOfRangeIndex_expectException() { ContactList contactList = new ContactList(); testUserInput = "rm 3"; // adding 1 input contact into contactList From c55331b0602d0640e6cef09d102f10dced19141f Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 14 Oct 2021 00:03:18 +0800 Subject: [PATCH 275/756] Implement InvalidDetailCommand JUnit tests to MainParserTest --- .../java/seedu/parser/MainParserTest.java | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/src/test/java/seedu/parser/MainParserTest.java b/src/test/java/seedu/parser/MainParserTest.java index 6a9b8169aa..1076070b6d 100644 --- a/src/test/java/seedu/parser/MainParserTest.java +++ b/src/test/java/seedu/parser/MainParserTest.java @@ -7,6 +7,7 @@ import seedu.command.Command; import seedu.command.DeleteContactCommand; import seedu.command.FailedCommand; +import seedu.command.InvalidDetailCommand; import seedu.command.ViewContactCommand; import seedu.contact.ContactList; @@ -153,6 +154,70 @@ public void parseAddCommand_validInputsWithPartialFlags_expectAddContactCommand( assertEquals(expectedCommand.getEmail(), actualCommand.getEmail()); } + @Test + public void parseAddCommand_invalidNameWithNumber_expectInvalidDetailCommand() { + testUserInput = "add -n 123456"; + FailedCommandType expectedFailedCommandType = FailedCommandType.INVALID_NAME; + final InvalidDetailCommand actualCommand = getParsedCommand(testUserInput, InvalidDetailCommand.class); + assertEquals(expectedFailedCommandType, actualCommand.getType()); + } + + @Test + public void parseAddCommand_invalidGithubUsername_expectInvalidDetailCommand() { + testUserInput = "add -n marcus -g git@hub//"; + FailedCommandType expectedFailedCommandType = FailedCommandType.INVALID_GITHUB_USERNAME; + final InvalidDetailCommand actualCommand = getParsedCommand(testUserInput, InvalidDetailCommand.class); + assertEquals(expectedFailedCommandType, actualCommand.getType()); + } + + @Test + public void parseAddCommand_invalidLinkedin_expectInvalidDetailCommand() { + testUserInput = "add -n marcus -l linked@in/#"; + FailedCommandType expectedFailedCommandType = FailedCommandType.INVALID_LINKEDIN; + final InvalidDetailCommand actualCommand = getParsedCommand(testUserInput, InvalidDetailCommand.class); + assertEquals(expectedFailedCommandType, actualCommand.getType()); + } + + @Test + public void parseAddCommand_invalidTwitter_expectInvalidDetailCommand() { + testUserInput = "add -n marcus -tw b#b#@@"; + FailedCommandType expectedFailedCommandType = FailedCommandType.INVALID_TWITTER; + final InvalidDetailCommand actualCommand = getParsedCommand(testUserInput, InvalidDetailCommand.class); + assertEquals(expectedFailedCommandType, actualCommand.getType()); + } + + @Test + public void parseAddCommand_invalidTelegram_expectInvalidDetailCommand() { + testUserInput = "add -n marcus -te $$5ts@!"; + FailedCommandType expectedFailedCommandType = FailedCommandType.INVALID_TELEGRAM; + final InvalidDetailCommand actualCommand = getParsedCommand(testUserInput, InvalidDetailCommand.class); + assertEquals(expectedFailedCommandType, actualCommand.getType()); + } + + @Test + public void parseAddCommand_invalidEmail_expectInvalidDetailCommand() { + testUserInput = "add -n marcus -e marcus"; + FailedCommandType expectedFailedCommandType = FailedCommandType.INVALID_MAIL; + final InvalidDetailCommand actualCommand = getParsedCommand(testUserInput, InvalidDetailCommand.class); + assertEquals(expectedFailedCommandType, actualCommand.getType()); + } + + @Test + public void parseAddCommand_forbiddenGithub_expectInvalidDetailCommand() { + testUserInput = "add -n marcus -g null"; + FailedCommandType expectedFailedCommandType = FailedCommandType.FORBIDDEN_DETAIL; + final InvalidDetailCommand actualCommand = getParsedCommand(testUserInput, InvalidDetailCommand.class); + assertEquals(expectedFailedCommandType, actualCommand.getType()); + } + + @Test + public void parseAddCommand_forbiddenName_expectInvalidDetailCommand() { + testUserInput = "add -n null -g legit"; + FailedCommandType expectedFailedCommandType = FailedCommandType.FORBIDDEN_DETAIL; + final InvalidDetailCommand actualCommand = getParsedCommand(testUserInput, InvalidDetailCommand.class); + assertEquals(expectedFailedCommandType, actualCommand.getType()); + } + @Test public void parseViewCommand_validIndex_expectViewContactIndexMatch() { final int testIndex = 1; From 634c3df901abed64c2e256ef89999f003a502806 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 14 Oct 2021 00:06:03 +0800 Subject: [PATCH 276/756] Update IO redirection test for UNIX --- text-ui-test/EXPECTED-UNIX.TXT | 150 +++++++++++++++++++++++++-------- 1 file changed, 114 insertions(+), 36 deletions(-) diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index cb90196229..afac34bc00 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -12,8 +12,8 @@ ____________________________________________________________ Welcome to ConTech, your personal contact tracker. ____________________________________________________________ -As ConTech is unable to find your saved data, - it has created a new one for you at: +As ConTech is unable to find your saved data, + it has created a new one for you at: data/contacts.txt ____________________________________________________________ @@ -22,7 +22,7 @@ There are no contacts stored in ConTech. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: ng andre Github: github.com/ng-andre @@ -39,7 +39,7 @@ Please enter a valid contact index. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: ashraf Github: github.com/ashraf @@ -67,7 +67,7 @@ Delete has been cancelled. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: mayank Github: github.com/mayankp123 @@ -80,7 +80,7 @@ Please input a number between 0 and 2. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: bory Github: github.com/marcus @@ -88,7 +88,7 @@ You now have 4 contact(s). ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: andre Github: github.com/ng-andre @@ -115,7 +115,7 @@ ____________________________________________________________ ____________________________________________________________ There are missing details. -Please remove any flags with no details, +Please remove any flags with no details, and ensure that your flags used are correct: -n NAME -g GITHUB @@ -130,7 +130,7 @@ Please enter a valid contact index. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: lezong Github: github.com/lezongmun @@ -185,7 +185,7 @@ ____________________________________________________________ ____________________________________________________________ There are missing details. -Please remove any flags with no details, +Please remove any flags with no details, and ensure that your flags used are correct: -n NAME -g GITHUB @@ -227,7 +227,7 @@ Please try again with a valid flag. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: lezongmun Github: github.com/lezong @@ -271,6 +271,65 @@ ____________________________________________________________ Please enter a valid contact index. ____________________________________________________________ +____________________________________________________________ +There are missing details. +Please remove any flags with no details, +and ensure that your flags used are correct: + -n NAME + -g GITHUB + -l LINKEDIN + -te TELEGRAM + -tw TWITTER + -e EMAIL +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: +Name: yusdhsdsd +Github: github.com/sdj0-11222 + +You now have 5 contact(s). +____________________________________________________________ + +____________________________________________________________ +The github username is not correctly formatted, +Rules for Github username : + * Only contain alphanumeric characters or hyphens + * Only lowercase allowed + * Maximum 39 characters allowed + * Cannot have multiple consecutive hyphens + * Cannot begin or end with a hyphen + +____________________________________________________________ + +____________________________________________________________ +The github username is not correctly formatted, +Rules for Github username : + * Only contain alphanumeric characters or hyphens + * Only lowercase allowed + * Maximum 39 characters allowed + * Cannot have multiple consecutive hyphens + * Cannot begin or end with a hyphen + +____________________________________________________________ + +____________________________________________________________ +The name is not correctly formatted, +Rules for name : + * Uppercase and lowercase letters + * Spaces + * No numbers or special characters + * Cannot be "null" +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: +Name: asjoda sadfsd +Telegram: t.me/_123adad + +You now have 6 contact(s). +____________________________________________________________ + ____________________________________________________________ 0. mayank Github: github.com/mayankp123 @@ -278,7 +337,7 @@ ____________________________________________________________ ____________________________________________________________ There are missing details. -Please remove any flags with no details, +Please remove any flags with no details, and ensure that your flags used are correct: -n NAME -g GITHUB @@ -294,47 +353,67 @@ Due to the storage nature of ConTech, we will remove commas (","), and attempt to parse it as: add -n lezong mun -g lezaimun ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: lezong mun Github: github.com/lezaimun -You now have 5 contact(s). +You now have 7 contact(s). ____________________________________________________________ ____________________________________________________________ -As one of the details to be stored is "null", +As one of the details to be stored is "null", ConTech is unable to process it ____________________________________________________________ ____________________________________________________________ -As one of the details to be stored is "null", +As one of the details to be stored is "null", ConTech is unable to process it ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: dev Github: github.com/nullptr -You now have 6 contact(s). +You now have 8 contact(s). ____________________________________________________________ ____________________________________________________________ -ConTech has edited the specified contact: +ConTech has edited the specified contact: Name: lezongmun Github: github.com/new-git ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: -Name: name -Github: github.com/github -Email: email -Telegram: t.me/telegram -LinkedIn: linkedin.com/in/linkedin -Twitter: twitter.com/twitter +The twitter username is not correctly formatted, +Rules for Twitter username : + * Lowercase letters only + * Numbers and underscore allowed + * Maximum 15 characters allowed +____________________________________________________________ -You now have 7 contact(s). +____________________________________________________________ +ConTech has added the specified contact: +Name: asjoda sadfsd +Twitter: twitter.com/123_adad + +You now have 9 contact(s). +____________________________________________________________ + +____________________________________________________________ +The email id is not correctly formatted, +Rules for email id : + * Lowercase letters only + * Numbers, underscore, hyphen and dot allowed + * @ cannot be at the start or end +____________________________________________________________ + +____________________________________________________________ +The email id is not correctly formatted, +Rules for email id : + * Lowercase letters only + * Numbers, underscore, hyphen and dot allowed + * @ cannot be at the start or end ____________________________________________________________ ____________________________________________________________ @@ -349,21 +428,20 @@ Please try again with a valid flag. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: -Name: lezai3 -Github: github.com/lezongmun -Email: lezongmun@gmail.com -LinkedIn: linkedin.com/in/lezongmun - -You now have 8 contact(s). +The name is not correctly formatted, +Rules for name : + * Uppercase and lowercase letters + * Spaces + * No numbers or special characters + * Cannot be "null" ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: lezongggg Telegram: t.me/testTelegram -You now have 9 contact(s). +You now have 10 contact(s). ____________________________________________________________ ____________________________________________________________ From a536c966850b9e15f54005f51e951d4ed3dcb88c Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 14 Oct 2021 00:13:41 +0800 Subject: [PATCH 277/756] Update to fulfill Checkstyle --- src/main/java/seedu/parser/MainParser.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 126c78215e..d4e237ccae 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -96,8 +96,9 @@ private Command parseAddContact(String userInput) { return new FailedCommand(FailedCommandType.MISSING_NAME); } catch (MissingDetailException e) { return new FailedCommand(FailedCommandType.MISSING_DETAIL); - } catch (InvalidNameException | InvalidGithubUsernameException | InvalidEmailException | InvalidLinkedinUsernameException - | InvalidTelegramUsernameException | InvalidTwitterUsernameException | ForbiddenDetailException e) { + } catch (InvalidNameException | InvalidGithubUsernameException | InvalidEmailException + | InvalidLinkedinUsernameException | InvalidTelegramUsernameException + | InvalidTwitterUsernameException | ForbiddenDetailException e) { return parseInvalidDetailCommand(e); } } @@ -117,8 +118,9 @@ private Command parseEditContact(String userInput) { // userInput is raw user in return new FailedCommand(FailedCommandType.INVALID_INDEX); } catch (MissingDetailException e) { return new FailedCommand(FailedCommandType.MISSING_DETAIL); - } catch (InvalidNameException | InvalidGithubUsernameException | InvalidEmailException | InvalidLinkedinUsernameException - | InvalidTelegramUsernameException | InvalidTwitterUsernameException | ForbiddenDetailException e) { + } catch (InvalidNameException | InvalidGithubUsernameException | InvalidEmailException + | InvalidLinkedinUsernameException | InvalidTelegramUsernameException + | InvalidTwitterUsernameException | ForbiddenDetailException e) { return parseInvalidDetailCommand(e); } } From f65aa64bea6bcc1827c7756cc1d14098e67ac7e0 Mon Sep 17 00:00:00 2001 From: lezong Date: Sun, 17 Oct 2021 00:59:05 +0800 Subject: [PATCH 278/756] Merge with bory --- text-ui-test/EXPECTED-UNIX.TXT | 150 +++++++++++++++++++++++++-------- 1 file changed, 114 insertions(+), 36 deletions(-) diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index cb90196229..afac34bc00 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -12,8 +12,8 @@ ____________________________________________________________ Welcome to ConTech, your personal contact tracker. ____________________________________________________________ -As ConTech is unable to find your saved data, - it has created a new one for you at: +As ConTech is unable to find your saved data, + it has created a new one for you at: data/contacts.txt ____________________________________________________________ @@ -22,7 +22,7 @@ There are no contacts stored in ConTech. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: ng andre Github: github.com/ng-andre @@ -39,7 +39,7 @@ Please enter a valid contact index. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: ashraf Github: github.com/ashraf @@ -67,7 +67,7 @@ Delete has been cancelled. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: mayank Github: github.com/mayankp123 @@ -80,7 +80,7 @@ Please input a number between 0 and 2. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: bory Github: github.com/marcus @@ -88,7 +88,7 @@ You now have 4 contact(s). ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: andre Github: github.com/ng-andre @@ -115,7 +115,7 @@ ____________________________________________________________ ____________________________________________________________ There are missing details. -Please remove any flags with no details, +Please remove any flags with no details, and ensure that your flags used are correct: -n NAME -g GITHUB @@ -130,7 +130,7 @@ Please enter a valid contact index. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: lezong Github: github.com/lezongmun @@ -185,7 +185,7 @@ ____________________________________________________________ ____________________________________________________________ There are missing details. -Please remove any flags with no details, +Please remove any flags with no details, and ensure that your flags used are correct: -n NAME -g GITHUB @@ -227,7 +227,7 @@ Please try again with a valid flag. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: lezongmun Github: github.com/lezong @@ -271,6 +271,65 @@ ____________________________________________________________ Please enter a valid contact index. ____________________________________________________________ +____________________________________________________________ +There are missing details. +Please remove any flags with no details, +and ensure that your flags used are correct: + -n NAME + -g GITHUB + -l LINKEDIN + -te TELEGRAM + -tw TWITTER + -e EMAIL +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: +Name: yusdhsdsd +Github: github.com/sdj0-11222 + +You now have 5 contact(s). +____________________________________________________________ + +____________________________________________________________ +The github username is not correctly formatted, +Rules for Github username : + * Only contain alphanumeric characters or hyphens + * Only lowercase allowed + * Maximum 39 characters allowed + * Cannot have multiple consecutive hyphens + * Cannot begin or end with a hyphen + +____________________________________________________________ + +____________________________________________________________ +The github username is not correctly formatted, +Rules for Github username : + * Only contain alphanumeric characters or hyphens + * Only lowercase allowed + * Maximum 39 characters allowed + * Cannot have multiple consecutive hyphens + * Cannot begin or end with a hyphen + +____________________________________________________________ + +____________________________________________________________ +The name is not correctly formatted, +Rules for name : + * Uppercase and lowercase letters + * Spaces + * No numbers or special characters + * Cannot be "null" +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: +Name: asjoda sadfsd +Telegram: t.me/_123adad + +You now have 6 contact(s). +____________________________________________________________ + ____________________________________________________________ 0. mayank Github: github.com/mayankp123 @@ -278,7 +337,7 @@ ____________________________________________________________ ____________________________________________________________ There are missing details. -Please remove any flags with no details, +Please remove any flags with no details, and ensure that your flags used are correct: -n NAME -g GITHUB @@ -294,47 +353,67 @@ Due to the storage nature of ConTech, we will remove commas (","), and attempt to parse it as: add -n lezong mun -g lezaimun ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: lezong mun Github: github.com/lezaimun -You now have 5 contact(s). +You now have 7 contact(s). ____________________________________________________________ ____________________________________________________________ -As one of the details to be stored is "null", +As one of the details to be stored is "null", ConTech is unable to process it ____________________________________________________________ ____________________________________________________________ -As one of the details to be stored is "null", +As one of the details to be stored is "null", ConTech is unable to process it ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: dev Github: github.com/nullptr -You now have 6 contact(s). +You now have 8 contact(s). ____________________________________________________________ ____________________________________________________________ -ConTech has edited the specified contact: +ConTech has edited the specified contact: Name: lezongmun Github: github.com/new-git ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: -Name: name -Github: github.com/github -Email: email -Telegram: t.me/telegram -LinkedIn: linkedin.com/in/linkedin -Twitter: twitter.com/twitter +The twitter username is not correctly formatted, +Rules for Twitter username : + * Lowercase letters only + * Numbers and underscore allowed + * Maximum 15 characters allowed +____________________________________________________________ -You now have 7 contact(s). +____________________________________________________________ +ConTech has added the specified contact: +Name: asjoda sadfsd +Twitter: twitter.com/123_adad + +You now have 9 contact(s). +____________________________________________________________ + +____________________________________________________________ +The email id is not correctly formatted, +Rules for email id : + * Lowercase letters only + * Numbers, underscore, hyphen and dot allowed + * @ cannot be at the start or end +____________________________________________________________ + +____________________________________________________________ +The email id is not correctly formatted, +Rules for email id : + * Lowercase letters only + * Numbers, underscore, hyphen and dot allowed + * @ cannot be at the start or end ____________________________________________________________ ____________________________________________________________ @@ -349,21 +428,20 @@ Please try again with a valid flag. ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: -Name: lezai3 -Github: github.com/lezongmun -Email: lezongmun@gmail.com -LinkedIn: linkedin.com/in/lezongmun - -You now have 8 contact(s). +The name is not correctly formatted, +Rules for name : + * Uppercase and lowercase letters + * Spaces + * No numbers or special characters + * Cannot be "null" ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: +ConTech has added the specified contact: Name: lezongggg Telegram: t.me/testTelegram -You now have 9 contact(s). +You now have 10 contact(s). ____________________________________________________________ ____________________________________________________________ From 86638bb1810aa51f1cd0790a415512deebc0bdd3 Mon Sep 17 00:00:00 2001 From: lezong Date: Sun, 17 Oct 2021 02:09:33 +0800 Subject: [PATCH 279/756] Move TextUi with scanner into UserInputTextUi --- .../seedu/command/DeleteContactCommand.java | 4 +- src/main/java/seedu/duke/Duke.java | 4 +- src/main/java/seedu/parser/ContactParser.java | 1 - .../java/seedu/storage/ContactsDecoder.java | 5 +- src/main/java/seedu/storage/Storage.java | 8 +- src/main/java/seedu/ui/TextUi.java | 79 +++++++------------ src/main/java/seedu/ui/UserInputTextUi.java | 22 ++++++ 7 files changed, 63 insertions(+), 60 deletions(-) create mode 100644 src/main/java/seedu/ui/UserInputTextUi.java diff --git a/src/main/java/seedu/command/DeleteContactCommand.java b/src/main/java/seedu/command/DeleteContactCommand.java index 5142a78be0..a3dd6863e0 100644 --- a/src/main/java/seedu/command/DeleteContactCommand.java +++ b/src/main/java/seedu/command/DeleteContactCommand.java @@ -4,6 +4,7 @@ import seedu.parser.IndexParser; import seedu.ui.TextUi; import seedu.ui.ExceptionTextUi; +import seedu.ui.UserInputTextUi; public class DeleteContactCommand extends Command { @@ -19,7 +20,8 @@ public int getDeletedIndex() { private void deleteOnConfirmation(Contact deletedContact) { // ask for confirmation to delete from user - String userDeleteConfirmation = TextUi.getUserDeleteConfirmation(deletedContact, contactIndex); + TextUi.confirmDeleteMessage(deletedContact, contactIndex); + String userDeleteConfirmation = UserInputTextUi.getUserDeleteConfirmation(); if (userDeleteConfirmation.equalsIgnoreCase("y")) { this.contactList.deleteContact(contactIndex); TextUi.deleteContactMessage(deletedContact.getName(), contactList.getListSize()); diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index b4878da7f8..00be8a1467 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -9,9 +9,9 @@ import seedu.storage.Storage; import seedu.ui.TextUi; import seedu.ui.ExceptionTextUi; +import seedu.ui.UserInputTextUi; public class Duke { - private TextUi textUi; private String contactFilePath; private Storage storage; private MainParser parser; @@ -36,7 +36,7 @@ public Duke(String contactFilePath, String personalContactFilePath) { private void runConTech() { Command command; do { - String userInput = textUi.getUserInput(); + String userInput = UserInputTextUi.getUserInput(); command = parser.parseCommand(userInput); runCommandProcedure(command); } while (!command.isExit()); diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index 8cf88c0dd2..7ebd6cd0bf 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -161,7 +161,6 @@ private void checkNameRegex(String detailToParse) throws InvalidNameException { } } - private int getIndexToStore(String flag) throws InvalidFlagException { int indexToStore; switch (flag) { diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index 21738f03f3..2b819ee4d5 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -7,7 +7,6 @@ import seedu.ui.ExceptionTextUi; import static seedu.storage.Storage.SEPARATOR; -import static seedu.parser.ContactParser.NUMBER_OF_FIELDS; import java.io.File; import java.io.FileNotFoundException; @@ -42,6 +41,10 @@ public static Contact readPersonalContact(File personalContactFile) throws FileE return personalContact; } + public void getPersonalContactDetails() { + + } + private static Contact decodePersonalContact(String contactText, Contact contact) { String[] destructuredInputs = contactText.split(SEPARATOR); Contact personalContact = contact; diff --git a/src/main/java/seedu/storage/Storage.java b/src/main/java/seedu/storage/Storage.java index bdc8291a11..b50a3e8413 100644 --- a/src/main/java/seedu/storage/Storage.java +++ b/src/main/java/seedu/storage/Storage.java @@ -1,10 +1,10 @@ package seedu.storage; -import org.w3c.dom.Text; import seedu.contact.Contact; import seedu.contact.ContactList; import seedu.exception.FileErrorException; import seedu.ui.TextUi; +import seedu.ui.UserInputTextUi; import java.io.File; import java.io.IOException; @@ -76,8 +76,9 @@ public ContactList loadExistingContacts() throws FileErrorException { public Contact loadExistingPersonalContact() throws FileErrorException { if (!hasExistingPersonalContactFile() || hasEmptyExistingPersonalContactFile()) { isFirstRun = true; - // get new contact - String personalName = TextUi.getNameMessage(); + // get new contact's name + TextUi.welcomeMessage(); + String personalName = UserInputTextUi.getUserInput(); Contact personalContact = new Contact(personalName, null,null,null, null,null); ContactsEncoder.savePersonalContact(personalContactFilePath, personalContact); @@ -88,4 +89,5 @@ public Contact loadExistingPersonalContact() throws FileErrorException { TextUi.welcomeBackMessage(personalContact); return personalContact; } + } diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index e880c03217..9d6688d9f1 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -12,49 +12,37 @@ public abstract class TextUi { private static final String LINE = "____________________________________________________________\n"; - private static final Scanner scanner = new Scanner(System.in); - -// public TextUi(boolean isFirstRun, Contact personalContact) { -// initMessage(isFirstRun, personalContact); -// } - - public static String getUserInput() { - String userInput = scanner.nextLine().trim(); - if (userInput.contains(",")) { - String newUserInput = userInput.replace(",", ""); - ExceptionTextUi.forbiddenInputCommaMessage(newUserInput); - return newUserInput; - } - return userInput; + // Used for print messages after user inputs + private static void printDoubleLineMessage(String message) { + System.out.println(LINE + message + "\n" + LINE); } - public static String getUserDeleteConfirmation(Contact deletedContact, int deletedIndex) { - String message = "Delete this contact? (y/n)\n" - + deletedIndex + ". " + deletedContact.getName() + formatContactFields(deletedContact); - printDoubleLineMessage(message); + // Used for system messages without user inputs + private static void printBottomLineMessage(String message) { + System.out.println(message + "\n" + LINE); + } - String userDeleteConfirmation = scanner.nextLine().trim(); - return userDeleteConfirmation; + private static void printTopLineMessage(String message) { + System.out.println(LINE + "\n" + message); } - public static String getUserPersonalContact() { - String message = "Can I get your name?"; - System.out.println(message); - System.out.println(LINE); - return scanner.nextLine().trim(); + // Used to print a line after displayed data + public static void printBottomLine() { + System.out.println("\n" + LINE); } - public static String getNameMessage() { + public static void welcomeMessage() { printDoubleLineMessage(LOGO); - System.out.println("Welcome to ConTech, your personal contact tracker.\n"); - String personalContact = getUserPersonalContact(); - return personalContact; + String message = "Welcome to ConTech, your personal contact tracker.\n" + + "Can I get your name?"; + printBottomLineMessage(message); } public static void welcomeBackMessage(Contact personalContact) { printDoubleLineMessage(LOGO); - System.out.println("Hello, " + personalContact.getName() + "." + " Welcome back to ConTech.\n"); - System.out.println(LINE); + String message = "Hello, " + personalContact.getName() + ". Welcome back to ConTech, " + + "your personal contact tracker."; + printBottomLineMessage(message); } public static void greetingMessage(Contact personalContact) { @@ -66,25 +54,6 @@ public static void greetingMessage(Contact personalContact) { printDoubleLineMessage(message); } - // Used for print messages after user inputs - private static void printDoubleLineMessage(String message) { - System.out.println(LINE + message + "\n" + LINE); - } - - // Used for system messages without user inputs - private static void printBottomLineMessage(String message) { - System.out.println(message + "\n" + LINE); - } - - private static void printTopLineMessage(String message) { - System.out.println(LINE + "\n" + message); - } - - // Used to print a line after displayed data - public static void printBottomLine() { - System.out.println("\n" + LINE); - } - public static void createNewContactFileMessage(String contactFilePath) { String message = "As ConTech is unable to find your saved data,\n" + " it has created a new one for you at:\n" + contactFilePath; @@ -142,8 +111,9 @@ public static void contactsEmptyListMessage() { printDoubleLineMessage(message); } - public static void cancelDeleteContactMessage() { - String message = "Delete has been cancelled."; + public static void confirmDeleteMessage(Contact deletedContact, int deletedIndex) { + String message = "Delete this contact? (y/n)\n" + + deletedIndex + ". " + deletedContact.getName() + formatContactFields(deletedContact); printDoubleLineMessage(message); } @@ -153,6 +123,11 @@ public static void deleteContactMessage(String contactName, int listSize) { printDoubleLineMessage(message); } + public static void cancelDeleteContactMessage() { + String message = "Delete has been cancelled."; + printDoubleLineMessage(message); + } + public static void exitMessage() { String message = "ConTech will now shutdown.\n" + "We hope you have enjoyed using it."; printDoubleLineMessage(message); diff --git a/src/main/java/seedu/ui/UserInputTextUi.java b/src/main/java/seedu/ui/UserInputTextUi.java new file mode 100644 index 0000000000..d46e167bc0 --- /dev/null +++ b/src/main/java/seedu/ui/UserInputTextUi.java @@ -0,0 +1,22 @@ +package seedu.ui; + +import java.util.Scanner; + +public class UserInputTextUi { + private static final Scanner scanner = new Scanner(System.in); + + public static String getUserInput() { + String userInput = scanner.nextLine().trim(); + if (userInput.contains(",")) { + String newUserInput = userInput.replace(",", ""); + ExceptionTextUi.forbiddenInputCommaMessage(newUserInput); + return newUserInput; + } + return userInput; + } + + public static String getUserDeleteConfirmation() { + String userDeleteConfirmation = scanner.nextLine().trim(); + return userDeleteConfirmation; + } +} From cbf7f34469e855300c026d5a5889357e3746261b Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sun, 17 Oct 2021 12:13:45 +0800 Subject: [PATCH 280/756] Enable assertions in gradle --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index d8641cf35d..c358356036 100644 --- a/build.gradle +++ b/build.gradle @@ -58,5 +58,6 @@ checkstyle { run{ standardInput = System.in + enableAssertions = true } From 337c2bd2302bec22261147c8b7d49f6194288a2e Mon Sep 17 00:00:00 2001 From: lezong Date: Sun, 17 Oct 2021 13:01:05 +0800 Subject: [PATCH 281/756] Add text-ui-test inputs --- src/main/java/seedu/ui/TextUi.java | 2 +- text-ui-test/ACTUAL.TXT | 22 +++++++++++++++++++--- text-ui-test/EXPECTED-UNIX.TXT | 22 +++++++++++++++++++--- text-ui-test/EXPECTED.TXT | 22 +++++++++++++++++++--- text-ui-test/input.txt | 1 + 5 files changed, 59 insertions(+), 10 deletions(-) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 9d6688d9f1..0d8e7526e4 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -41,7 +41,7 @@ public static void welcomeMessage() { public static void welcomeBackMessage(Contact personalContact) { printDoubleLineMessage(LOGO); String message = "Hello, " + personalContact.getName() + ". Welcome back to ConTech, " - + "your personal contact tracker."; + + "your personal \ncontact tracker."; printBottomLineMessage(message); } diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index afac34bc00..283e033e74 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -1,3 +1,13 @@ +As ConTech is unable to find your saved data, + it has created a new one for you at: +data/contacts.txt +____________________________________________________________ + +As ConTech is unable to find any saved personal data, + it has created a new one for you at: +data/me.txt +____________________________________________________________ + ____________________________________________________________ _____ _______ _ / ____| |__ __| | | @@ -10,11 +20,17 @@ ____________________________________________________________ ____________________________________________________________ Welcome to ConTech, your personal contact tracker. +Can I get your name? ____________________________________________________________ -As ConTech is unable to find your saved data, - it has created a new one for you at: -data/contacts.txt +____________________________________________________________ +Hello there, Le Zong. + +This is ConTech, your very own contact tracking application +to manage computing-related contacts, like GitHub Accounts +or even Emails. + +Enter "help" to see what you can do with ConTech. ____________________________________________________________ ____________________________________________________________ diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index afac34bc00..283e033e74 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -1,3 +1,13 @@ +As ConTech is unable to find your saved data, + it has created a new one for you at: +data/contacts.txt +____________________________________________________________ + +As ConTech is unable to find any saved personal data, + it has created a new one for you at: +data/me.txt +____________________________________________________________ + ____________________________________________________________ _____ _______ _ / ____| |__ __| | | @@ -10,11 +20,17 @@ ____________________________________________________________ ____________________________________________________________ Welcome to ConTech, your personal contact tracker. +Can I get your name? ____________________________________________________________ -As ConTech is unable to find your saved data, - it has created a new one for you at: -data/contacts.txt +____________________________________________________________ +Hello there, Le Zong. + +This is ConTech, your very own contact tracking application +to manage computing-related contacts, like GitHub Accounts +or even Emails. + +Enter "help" to see what you can do with ConTech. ____________________________________________________________ ____________________________________________________________ diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index afac34bc00..283e033e74 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,3 +1,13 @@ +As ConTech is unable to find your saved data, + it has created a new one for you at: +data/contacts.txt +____________________________________________________________ + +As ConTech is unable to find any saved personal data, + it has created a new one for you at: +data/me.txt +____________________________________________________________ + ____________________________________________________________ _____ _______ _ / ____| |__ __| | | @@ -10,11 +20,17 @@ ____________________________________________________________ ____________________________________________________________ Welcome to ConTech, your personal contact tracker. +Can I get your name? ____________________________________________________________ -As ConTech is unable to find your saved data, - it has created a new one for you at: -data/contacts.txt +____________________________________________________________ +Hello there, Le Zong. + +This is ConTech, your very own contact tracking application +to manage computing-related contacts, like GitHub Accounts +or even Emails. + +Enter "help" to see what you can do with ConTech. ____________________________________________________________ ____________________________________________________________ diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index bbcf82359e..58df2626d9 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -1,3 +1,4 @@ +Le Zong rm 1 add -n ng andre -g ng-andre rm 2 From 81e8800cc5f727c3aa17c647aa709fd2b4cbcb33 Mon Sep 17 00:00:00 2001 From: lezong Date: Sun, 17 Oct 2021 14:18:08 +0800 Subject: [PATCH 282/756] Move regex parsing in ContactParser into RegexParser class --- .../seedu/command/DeleteContactCommand.java | 2 +- .../java/seedu/parser/AddContactParser.java | 1 + .../parser/AddPersonalContactParser.java | 7 ++ src/main/java/seedu/parser/ContactParser.java | 90 +------------- src/main/java/seedu/parser/RegexParser.java | 111 ++++++++++++++++++ src/main/java/seedu/ui/UserInputTextUi.java | 6 +- 6 files changed, 125 insertions(+), 92 deletions(-) create mode 100644 src/main/java/seedu/parser/AddPersonalContactParser.java create mode 100644 src/main/java/seedu/parser/RegexParser.java diff --git a/src/main/java/seedu/command/DeleteContactCommand.java b/src/main/java/seedu/command/DeleteContactCommand.java index a3dd6863e0..a34227015f 100644 --- a/src/main/java/seedu/command/DeleteContactCommand.java +++ b/src/main/java/seedu/command/DeleteContactCommand.java @@ -21,7 +21,7 @@ public int getDeletedIndex() { private void deleteOnConfirmation(Contact deletedContact) { // ask for confirmation to delete from user TextUi.confirmDeleteMessage(deletedContact, contactIndex); - String userDeleteConfirmation = UserInputTextUi.getUserDeleteConfirmation(); + String userDeleteConfirmation = UserInputTextUi.getUserConfirmation(); if (userDeleteConfirmation.equalsIgnoreCase("y")) { this.contactList.deleteContact(contactIndex); TextUi.deleteContactMessage(deletedContact.getName(), contactList.getListSize()); diff --git a/src/main/java/seedu/parser/AddContactParser.java b/src/main/java/seedu/parser/AddContactParser.java index 57800a2223..3b62ba9ae5 100644 --- a/src/main/java/seedu/parser/AddContactParser.java +++ b/src/main/java/seedu/parser/AddContactParser.java @@ -25,6 +25,7 @@ public class AddContactParser extends ContactParser { * @return String[] Returns an array of details * @throws InvalidFlagException If the flag given is not recognised */ + public String[] parseContactDetails(String userInput) throws InvalidFlagException, MissingArgException, InvalidNameException, InvalidGithubUsernameException, InvalidTelegramUsernameException, InvalidLinkedinUsernameException, InvalidTwitterUsernameException, diff --git a/src/main/java/seedu/parser/AddPersonalContactParser.java b/src/main/java/seedu/parser/AddPersonalContactParser.java new file mode 100644 index 0000000000..d6f0c99aae --- /dev/null +++ b/src/main/java/seedu/parser/AddPersonalContactParser.java @@ -0,0 +1,7 @@ +package seedu.parser; + +import seedu.contact.Contact; +import seedu.exception.*; + +public class AddPersonalContactParser extends RegexParser { +} \ No newline at end of file diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index 412c9ae7cc..ac33ef219a 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -15,7 +15,8 @@ import java.util.logging.Level; import java.util.logging.Logger; -public abstract class ContactParser { + +public abstract class ContactParser extends RegexParser { public static final int CONTACT_PARAMS_START_INDEX = 1; public static final int NUMBER_OF_DETAILS = 2; public static final int NUMBER_OF_ADD_ARGS = 2; @@ -73,93 +74,6 @@ public void parseDetail(String[] contactDetails, String detail) } - public void checkRegex(String flag, String detailToParse) - throws InvalidGithubUsernameException, InvalidNameException, InvalidFlagException, - InvalidTelegramUsernameException, InvalidTwitterUsernameException, - InvalidLinkedinUsernameException, InvalidEmailException { - assert flag != null; - assert detailToParse != null; - switch (flag) { - case NAME_FLAG: - checkNameRegex(detailToParse); - break; - case GITHUB_FLAG: - checkGithubUsernameRegex(detailToParse); - break; - case TELEGRAM_FLAG: - checkTelegramUsernameRegex(detailToParse); - break; - case TWITTER_FLAG: - checkTwitterUsernameRegex(detailToParse); - break; - case LINKEDIN_FLAG: - checkLinkedinUsernameRegex(detailToParse); - break; - case EMAIL_FLAG: - checkEmailRegex(detailToParse); - break; - default: - throw new InvalidFlagException(); - } - } - - private void checkEmailRegex(String detailToParse) throws InvalidEmailException { - //allow lowercase email ids - String emailRegex = "^([\\w-\\.]+){1,64}@([\\w&&[^_]]+){2,255}.[a-z]{2,}$"; - if (!detailToParse.matches(emailRegex)) { - LOGGER.log(Level.INFO, "Regex check for Email id failed"); - throw new InvalidEmailException(); - } - } - - private void checkLinkedinUsernameRegex(String detailToParse) throws InvalidLinkedinUsernameException { - //allows lowercase, numbers, underscore and hyphen. Length must be 3-100 characters - String linkedinRegex = "^[a-z0-9-_]{3,100}$"; - if (!detailToParse.matches(linkedinRegex)) { - LOGGER.log(Level.INFO, "Regex check for Linkedin failed"); - throw new InvalidLinkedinUsernameException(); - } - } - - private void checkTwitterUsernameRegex(String detailToParse) throws InvalidTwitterUsernameException { - //allows lowercase, numbers and underscore. Length must be max 15 characters - String twitterRegex = "^[a-z0-9_]{1,15}$"; - if (!detailToParse.matches(twitterRegex)) { - LOGGER.log(Level.INFO, "Regex check for Name failed"); - throw new InvalidTwitterUsernameException(); - } - } - - private void checkTelegramUsernameRegex(String detailToParse) throws InvalidTelegramUsernameException { - //allows uppercase, lowercase, numbers and underscore. Length must be atleast 5 characters - String telegramRegex = "^[a-zA-Z0-9_]{5,}$"; - if (!detailToParse.matches(telegramRegex)) { - LOGGER.log(Level.INFO, "Regex check for Telegram username failed"); - throw new InvalidTelegramUsernameException(); - } - } - - private void checkGithubUsernameRegex(String detailToParse) throws InvalidGithubUsernameException { - //Github username may only contain alphanumeric characters or hyphens. - //Github username cannot have multiple consecutive hyphens. - //Github username cannot begin or end with a hyphen. - //Maximum is 39 characters. - String githubUsernameRegex = "^[a-z\\d](?:[a-z\\d]|-(?=[a-z\\d])){0,39}$"; - if (!detailToParse.matches(githubUsernameRegex)) { - LOGGER.log(Level.INFO, "Regex check for Github username failed"); - throw new InvalidGithubUsernameException(); - } - } - - private void checkNameRegex(String detailToParse) throws InvalidNameException { - //only letters and spaces allowed - String nameRegex = "^[ A-Za-z]+$"; - if (!detailToParse.matches(nameRegex)) { - LOGGER.log(Level.INFO, "Regex check for name failed"); - throw new InvalidNameException(); - } - } - private int getIndexToStore(String flag) throws InvalidFlagException { int indexToStore; switch (flag) { diff --git a/src/main/java/seedu/parser/RegexParser.java b/src/main/java/seedu/parser/RegexParser.java new file mode 100644 index 0000000000..1cfa94abb8 --- /dev/null +++ b/src/main/java/seedu/parser/RegexParser.java @@ -0,0 +1,111 @@ +package seedu.parser; + +import seedu.exception.InvalidEmailException; +import seedu.exception.InvalidFlagException; +import seedu.exception.InvalidGithubUsernameException; +import seedu.exception.InvalidLinkedinUsernameException; +import seedu.exception.InvalidNameException; +import seedu.exception.InvalidTelegramUsernameException; +import seedu.exception.InvalidTwitterUsernameException; +import java.util.logging.Level; +import java.util.logging.Logger; + + +public abstract class RegexParser { + + public static final String NAME_FLAG = "n"; + public static final String GITHUB_FLAG = "g"; + public static final String TELEGRAM_FLAG = "te"; + public static final String TWITTER_FLAG = "tw"; + public static final String EMAIL_FLAG = "e"; + public static final String LINKEDIN_FLAG = "l"; + + private static final Logger LOGGER = Logger.getLogger(RegexParser.class.getName()); + + public void checkRegex(String flag, String detailToParse) + throws InvalidGithubUsernameException, InvalidNameException, InvalidFlagException, + InvalidTelegramUsernameException, InvalidTwitterUsernameException, + InvalidLinkedinUsernameException, InvalidEmailException { + assert flag != null; + assert detailToParse != null; + switch (flag) { + case NAME_FLAG: + checkNameRegex(detailToParse); + break; + case GITHUB_FLAG: + checkGithubUsernameRegex(detailToParse); + break; + case TELEGRAM_FLAG: + checkTelegramUsernameRegex(detailToParse); + break; + case TWITTER_FLAG: + checkTwitterUsernameRegex(detailToParse); + break; + case LINKEDIN_FLAG: + checkLinkedinUsernameRegex(detailToParse); + break; + case EMAIL_FLAG: + checkEmailRegex(detailToParse); + break; + default: + throw new InvalidFlagException(); + } + } + + private void checkEmailRegex(String detailToParse) throws InvalidEmailException { + //allow lowercase email ids + String emailRegex = "^([\\w-\\.]+){1,64}@([\\w&&[^_]]+){2,255}.[a-z]{2,}$"; + if (!detailToParse.matches(emailRegex)) { + LOGGER.log(Level.INFO, "Regex check for Email id failed"); + throw new InvalidEmailException(); + } + } + + private void checkLinkedinUsernameRegex(String detailToParse) throws InvalidLinkedinUsernameException { + //allows lowercase, numbers, underscore and hyphen. Length must be 3-100 characters + String linkedinRegex = "^[a-z0-9-_]{3,100}$"; + if (!detailToParse.matches(linkedinRegex)) { + LOGGER.log(Level.INFO, "Regex check for Linkedin failed"); + throw new InvalidLinkedinUsernameException(); + } + } + + private void checkTwitterUsernameRegex(String detailToParse) throws InvalidTwitterUsernameException { + //allows lowercase, numbers and underscore. Length must be max 15 characters + String twitterRegex = "^[a-z0-9_]{1,15}$"; + if (!detailToParse.matches(twitterRegex)) { + LOGGER.log(Level.INFO, "Regex check for Name failed"); + throw new InvalidTwitterUsernameException(); + } + } + + private void checkTelegramUsernameRegex(String detailToParse) throws InvalidTelegramUsernameException { + //allows uppercase, lowercase, numbers and underscore. Length must be atleast 5 characters + String telegramRegex = "^[a-zA-Z0-9_]{5,}$"; + if (!detailToParse.matches(telegramRegex)) { + LOGGER.log(Level.INFO, "Regex check for Telegram username failed"); + throw new InvalidTelegramUsernameException(); + } + } + + private void checkGithubUsernameRegex(String detailToParse) throws InvalidGithubUsernameException { + //Github username may only contain alphanumeric characters or hyphens. + //Github username cannot have multiple consecutive hyphens. + //Github username cannot begin or end with a hyphen. + //Maximum is 39 characters. + String githubUsernameRegex = "^[a-z\\d](?:[a-z\\d]|-(?=[a-z\\d])){0,39}$"; + if (!detailToParse.matches(githubUsernameRegex)) { + LOGGER.log(Level.INFO, "Regex check for Github username failed"); + throw new InvalidGithubUsernameException(); + } + } + + private void checkNameRegex(String detailToParse) throws InvalidNameException { + //only letters and spaces allowed + String nameRegex = "^[ A-Za-z]+$"; + if (!detailToParse.matches(nameRegex)) { + LOGGER.log(Level.INFO, "Regex check for name failed"); + throw new InvalidNameException(); + } + } +} diff --git a/src/main/java/seedu/ui/UserInputTextUi.java b/src/main/java/seedu/ui/UserInputTextUi.java index d46e167bc0..00ad2bb112 100644 --- a/src/main/java/seedu/ui/UserInputTextUi.java +++ b/src/main/java/seedu/ui/UserInputTextUi.java @@ -15,8 +15,8 @@ public static String getUserInput() { return userInput; } - public static String getUserDeleteConfirmation() { - String userDeleteConfirmation = scanner.nextLine().trim(); - return userDeleteConfirmation; + public static String getUserConfirmation() { + String userConfirmation = scanner.nextLine().trim(); + return userConfirmation; } } From f8a4be885604fdc5da62a336249ae0c306e4196c Mon Sep 17 00:00:00 2001 From: lezong Date: Sun, 17 Oct 2021 15:44:45 +0800 Subject: [PATCH 283/756] Add AddPersonalContactParser to prompt user for their name and check with checkRegex --- .../parser/AddPersonalContactParser.java | 41 ++++++++++++++++++- src/main/java/seedu/parser/RegexParser.java | 12 +++--- src/main/java/seedu/storage/Storage.java | 8 ++-- src/main/java/seedu/ui/ExceptionTextUi.java | 11 +++++ 4 files changed, 60 insertions(+), 12 deletions(-) diff --git a/src/main/java/seedu/parser/AddPersonalContactParser.java b/src/main/java/seedu/parser/AddPersonalContactParser.java index d6f0c99aae..5cf84ee1df 100644 --- a/src/main/java/seedu/parser/AddPersonalContactParser.java +++ b/src/main/java/seedu/parser/AddPersonalContactParser.java @@ -1,7 +1,46 @@ package seedu.parser; + import seedu.contact.Contact; -import seedu.exception.*; +import seedu.exception.InvalidNameException; +import seedu.ui.ExceptionTextUi; +import seedu.ui.TextUi; +import seedu.ui.UserInputTextUi; public class AddPersonalContactParser extends RegexParser { + public static final String NAME_FLAG = "n"; + public static final String GITHUB_FLAG = "g"; + public static final String TELEGRAM_FLAG = "te"; + public static final String TWITTER_FLAG = "tw"; + public static final String EMAIL_FLAG = "e"; + public static final String LINKEDIN_FLAG = "l"; + + private Contact personalContact = new Contact(null, null,null,null, + null,null); + + public AddPersonalContactParser() { + TextUi.welcomeMessage(); + promptPersonalName(); + TextUi.greetingMessage(personalContact); + } + + private void promptPersonalName() { + boolean isValid = false; + String personalName = ""; + do { + try { + personalName = UserInputTextUi.getUserInput(); + checkNameRegex(personalName); + //checkNameRegex passes so the name must be valid + isValid = true; + } catch (InvalidNameException e) { + ExceptionTextUi.invalidPersonalNameErrorMessage(); + } + } while (!isValid); + this.personalContact.setName(personalName); + } + + public Contact getPersonalContact() { + return personalContact; + } } \ No newline at end of file diff --git a/src/main/java/seedu/parser/RegexParser.java b/src/main/java/seedu/parser/RegexParser.java index 1cfa94abb8..037cbbf7f8 100644 --- a/src/main/java/seedu/parser/RegexParser.java +++ b/src/main/java/seedu/parser/RegexParser.java @@ -52,7 +52,7 @@ public void checkRegex(String flag, String detailToParse) } } - private void checkEmailRegex(String detailToParse) throws InvalidEmailException { + protected void checkEmailRegex(String detailToParse) throws InvalidEmailException { //allow lowercase email ids String emailRegex = "^([\\w-\\.]+){1,64}@([\\w&&[^_]]+){2,255}.[a-z]{2,}$"; if (!detailToParse.matches(emailRegex)) { @@ -61,7 +61,7 @@ private void checkEmailRegex(String detailToParse) throws InvalidEmailException } } - private void checkLinkedinUsernameRegex(String detailToParse) throws InvalidLinkedinUsernameException { + protected void checkLinkedinUsernameRegex(String detailToParse) throws InvalidLinkedinUsernameException { //allows lowercase, numbers, underscore and hyphen. Length must be 3-100 characters String linkedinRegex = "^[a-z0-9-_]{3,100}$"; if (!detailToParse.matches(linkedinRegex)) { @@ -70,7 +70,7 @@ private void checkLinkedinUsernameRegex(String detailToParse) throws InvalidLink } } - private void checkTwitterUsernameRegex(String detailToParse) throws InvalidTwitterUsernameException { + protected void checkTwitterUsernameRegex(String detailToParse) throws InvalidTwitterUsernameException { //allows lowercase, numbers and underscore. Length must be max 15 characters String twitterRegex = "^[a-z0-9_]{1,15}$"; if (!detailToParse.matches(twitterRegex)) { @@ -79,7 +79,7 @@ private void checkTwitterUsernameRegex(String detailToParse) throws InvalidTwitt } } - private void checkTelegramUsernameRegex(String detailToParse) throws InvalidTelegramUsernameException { + protected void checkTelegramUsernameRegex(String detailToParse) throws InvalidTelegramUsernameException { //allows uppercase, lowercase, numbers and underscore. Length must be atleast 5 characters String telegramRegex = "^[a-zA-Z0-9_]{5,}$"; if (!detailToParse.matches(telegramRegex)) { @@ -88,7 +88,7 @@ private void checkTelegramUsernameRegex(String detailToParse) throws InvalidTele } } - private void checkGithubUsernameRegex(String detailToParse) throws InvalidGithubUsernameException { + protected void checkGithubUsernameRegex(String detailToParse) throws InvalidGithubUsernameException { //Github username may only contain alphanumeric characters or hyphens. //Github username cannot have multiple consecutive hyphens. //Github username cannot begin or end with a hyphen. @@ -100,7 +100,7 @@ private void checkGithubUsernameRegex(String detailToParse) throws InvalidGithub } } - private void checkNameRegex(String detailToParse) throws InvalidNameException { + protected void checkNameRegex(String detailToParse) throws InvalidNameException { //only letters and spaces allowed String nameRegex = "^[ A-Za-z]+$"; if (!detailToParse.matches(nameRegex)) { diff --git a/src/main/java/seedu/storage/Storage.java b/src/main/java/seedu/storage/Storage.java index b50a3e8413..2456c86881 100644 --- a/src/main/java/seedu/storage/Storage.java +++ b/src/main/java/seedu/storage/Storage.java @@ -3,6 +3,7 @@ import seedu.contact.Contact; import seedu.contact.ContactList; import seedu.exception.FileErrorException; +import seedu.parser.AddPersonalContactParser; import seedu.ui.TextUi; import seedu.ui.UserInputTextUi; @@ -77,12 +78,9 @@ public Contact loadExistingPersonalContact() throws FileErrorException { if (!hasExistingPersonalContactFile() || hasEmptyExistingPersonalContactFile()) { isFirstRun = true; // get new contact's name - TextUi.welcomeMessage(); - String personalName = UserInputTextUi.getUserInput(); - Contact personalContact = new Contact(personalName, null,null,null, - null,null); + AddPersonalContactParser addPersonalContactParser = new AddPersonalContactParser(); + Contact personalContact = addPersonalContactParser.getPersonalContact(); ContactsEncoder.savePersonalContact(personalContactFilePath, personalContact); - TextUi.greetingMessage(personalContact); return personalContact; } Contact personalContact = ContactsDecoder.readPersonalContact(personalContactFile); diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index efc19b7de4..194a3f2e55 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -22,6 +22,17 @@ public static void printBottomLine() { System.out.println("\n" + LINE); } + public static void invalidPersonalNameErrorMessage() { + String message = "The name is not correctly formatted,\n" + + "Rules for name :\n" + + " * Uppercase and lowercase letters\n" + + " * Spaces\n" + + " * No numbers or special characters\n" + + " * Cannot be \"null\"\n\n" + + "Please enter your name again."; + printDoubleLineMessage(message); + } + // Error Messages public static void fileErrorMessage(String contactFilePath) { String message = "ConTech is unfortunately unable to access / create a\n" + " save file at " + contactFilePath From f03dd4120c2a319073eff78cdec8e37fdfe8c094 Mon Sep 17 00:00:00 2001 From: lezong Date: Sun, 17 Oct 2021 15:45:19 +0800 Subject: [PATCH 284/756] Minor edits to AddPersonalContactParser --- src/main/java/seedu/parser/AddPersonalContactParser.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/main/java/seedu/parser/AddPersonalContactParser.java b/src/main/java/seedu/parser/AddPersonalContactParser.java index 5cf84ee1df..0f6f2861f6 100644 --- a/src/main/java/seedu/parser/AddPersonalContactParser.java +++ b/src/main/java/seedu/parser/AddPersonalContactParser.java @@ -8,13 +8,6 @@ import seedu.ui.UserInputTextUi; public class AddPersonalContactParser extends RegexParser { - public static final String NAME_FLAG = "n"; - public static final String GITHUB_FLAG = "g"; - public static final String TELEGRAM_FLAG = "te"; - public static final String TWITTER_FLAG = "tw"; - public static final String EMAIL_FLAG = "e"; - public static final String LINKEDIN_FLAG = "l"; - private Contact personalContact = new Contact(null, null,null,null, null,null); From 4a73514e360f465232e55c2b20521e7661a7c409 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sun, 17 Oct 2021 16:22:22 +0800 Subject: [PATCH 285/756] Add links for (current) acknowledgements --- docs/DeveloperGuide.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 64e1f0ed2b..3cbb46c908 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -2,6 +2,14 @@ ## Acknowledgements +- Inspiration for App Idea and OOP Structure: AddressBook (Level 2)
+ https://github.com/se-edu/addressbook-level2 +- Inspiration for User Guide and Developer Guide: AddressBook (Level 2)
+ https://se-education.org/addressbook-level3/DeveloperGuide.html
+ https://se-education.org/addressbook-level3/UserGuide.html +- Converting text for ConTech:
+ https://patorjk.com/software/taag/#p=display&f=Graffiti&t=Type%20Something%20 + {list here sources of all reused/adapted ideas, code, documentation, and third-party libraries -- include links to the original source as well} ## Design & implementation From aebee03a874c72d9f40d0ae6d54f6abbce08c4eb Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sun, 17 Oct 2021 16:22:43 +0800 Subject: [PATCH 286/756] Add product scope - target user profile --- docs/DeveloperGuide.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 3cbb46c908..e8d89d97dc 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -19,8 +19,10 @@ ## Product scope ### Target user profile - -{Describe the target user profile} +- Has a need to store a significant amount of computing-related contacts +- Prefers and is familiar with Command Line Interface (CLI) applications +- Has many contacts that use common computing platforms, such as: Github, Linkedin, Twitter, Telegram, and Email +- Can type fast and prefers typing to mouse interactions ### Value proposition From 07b8dcba21a7d12f47b999adf0ad3721afc0ff98 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sun, 17 Oct 2021 16:22:58 +0800 Subject: [PATCH 287/756] Add value proposition --- docs/DeveloperGuide.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index e8d89d97dc..d63f897001 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -26,7 +26,9 @@ ### Value proposition -{Describe the value proposition: what problem does it solve?} +As computing professionals are often on their computer, ConTech allows them to have a platform to +manage their computing-related contacts locally and efficiently, without the need to use +additional devices or platforms. ## User Stories From 8792de7d33a7deb69e302801bb87db79819dc907 Mon Sep 17 00:00:00 2001 From: lezong Date: Sun, 17 Oct 2021 17:32:24 +0800 Subject: [PATCH 288/756] Add GitHub field in personal contact --- .../seedu/command/InvalidDetailCommand.java | 2 +- .../parser/AddPersonalContactParser.java | 96 +++++++++++++++++-- src/main/java/seedu/ui/ExceptionTextUi.java | 61 +++++++++++- src/main/java/seedu/ui/TextUi.java | 31 ++++++ 4 files changed, 181 insertions(+), 9 deletions(-) diff --git a/src/main/java/seedu/command/InvalidDetailCommand.java b/src/main/java/seedu/command/InvalidDetailCommand.java index 6fe737efa3..44a3d0d676 100644 --- a/src/main/java/seedu/command/InvalidDetailCommand.java +++ b/src/main/java/seedu/command/InvalidDetailCommand.java @@ -26,7 +26,7 @@ public void execute() { ExceptionTextUi.invalidTelegramUsernameInput(); break; case INVALID_LINKEDIN: - ExceptionTextUi.invalidLinkedinInput(); + ExceptionTextUi.invalidLinkedinUsernameInput(); break; case INVALID_MAIL: ExceptionTextUi.invalidEmailInput(); diff --git a/src/main/java/seedu/parser/AddPersonalContactParser.java b/src/main/java/seedu/parser/AddPersonalContactParser.java index 0f6f2861f6..0e1d47de5f 100644 --- a/src/main/java/seedu/parser/AddPersonalContactParser.java +++ b/src/main/java/seedu/parser/AddPersonalContactParser.java @@ -1,38 +1,122 @@ package seedu.parser; +import seedu.command.ExitCommand; +import seedu.command.FailedCommand; +import seedu.command.HelpCommand; +import seedu.command.ListContactsCommand; import seedu.contact.Contact; +import seedu.exception.InvalidGithubUsernameException; import seedu.exception.InvalidNameException; +import seedu.exception.InvalidTelegramUsernameException; import seedu.ui.ExceptionTextUi; import seedu.ui.TextUi; import seedu.ui.UserInputTextUi; public class AddPersonalContactParser extends RegexParser { + public static final String NAME_FLAG = "n"; + public static final String GITHUB_FLAG = "g"; + public static final String TELEGRAM_FLAG = "te"; + public static final String TWITTER_FLAG = "tw"; + public static final String EMAIL_FLAG = "e"; + public static final String LINKEDIN_FLAG = "l"; + private Contact personalContact = new Contact(null, null,null,null, null,null); + private boolean isValidDetail = false; public AddPersonalContactParser() { TextUi.welcomeMessage(); promptPersonalName(); + promptPersonalGithubUsername(); + promptPersonalTelegramUsername(); TextUi.greetingMessage(personalContact); } private void promptPersonalName() { - boolean isValid = false; - String personalName = ""; + isValidDetail = false; do { try { - personalName = UserInputTextUi.getUserInput(); + String personalName = UserInputTextUi.getUserInput(); checkNameRegex(personalName); //checkNameRegex passes so the name must be valid - isValid = true; + isValidDetail = true; + this.personalContact.setName(personalName); } catch (InvalidNameException e) { ExceptionTextUi.invalidPersonalNameErrorMessage(); } - } while (!isValid); - this.personalContact.setName(personalName); + } while (!isValidDetail); } + private void promptPersonalGithubUsername() { + isValidDetail = false; + TextUi.promptPersonalGithubUsernameMessage(this.personalContact.getName()); + do { + try { + String personalGithubUsername = UserInputTextUi.getUserInput(); + setGithubIfValid(personalGithubUsername); + } catch (InvalidGithubUsernameException e) { + ExceptionTextUi.invalidPersonalGithubUsernameErrorMessage(); + } + } while (!isValidDetail); + } + + public void setGithubIfValid(String userInput) throws InvalidGithubUsernameException { + if (userInput.isEmpty()) { + isValidDetail = true; + } else { + checkGithubUsernameRegex(userInput); + isValidDetail = true; + this.personalContact.setGithub(userInput); + } + } + + private void promptPersonalTelegramUsername() { + isValidDetail = false; + TextUi.promptPersonalTelegramUsernameMessage(); + do { + try { + String personalTelegram = UserInputTextUi.getUserInput(); + setTelegramIfValid(personalTelegram); + } catch (InvalidTelegramUsernameException e) { + ExceptionTextUi.invalidPersonalTelegramUsernameErrorMessage(); + } + } while (!isValidDetail); + } + + public void setTelegramIfValid(String userInput) throws InvalidTelegramUsernameException { + if (userInput.isEmpty()) { + isValidDetail = true; + } else { + checkTelegramUsernameRegex(userInput); + isValidDetail = true; + this.personalContact.setTelegram(userInput); + } + } + + +// private void setDetailsIfValid(String userInput, String flag) throws InvalidGithubUsernameException, +// InvalidTelegramUsernameException { +// if (userInput.isEmpty()) { +// isValidDetail = true; +// return; +// } +// switch (flag) { +// case GITHUB_FLAG: +// checkGithubUsernameRegex(userInput); +// isValidDetail = true; +// this.personalContact.setGithub(userInput); +// break; +// case TELEGRAM_FLAG: +// checkTelegramUsernameRegex(userInput); +// isValidDetail = true; +// this.personalContact.setTelegram(userInput); +// break; +// default: +// return; +// } +// } + public Contact getPersonalContact() { return personalContact; } diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index 194a3f2e55..398be53a65 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -33,6 +33,63 @@ public static void invalidPersonalNameErrorMessage() { printDoubleLineMessage(message); } + public static void invalidPersonalGithubUsernameErrorMessage() { + String message = "The github username is not correctly formatted,\n" + + "Rules for Github username :\n" + + " * Only contain alphanumeric characters or hyphens\n" + + " * Only lowercase allowed\n" + + " * Maximum 39 characters allowed\n" + + " * Cannot have multiple consecutive hyphens\n" + + " * Cannot begin or end with a hyphen\n\n" + + "Please enter your github username again\n" + + "or press ENTER to skip."; + printDoubleLineMessage(message); + } + + public static void invalidPersonalTelegramUsernameErrorMessage() { + String message = "The telegram username is not correctly formatted,\n" + + "Rules for Telegram username :\n" + + " * Uppercase and lowercase letters allowed\n" + + " * Numbers and underscore allowed\n" + + " * Length at-least 5 characters\n\n" + + "Please enter your telegram username again\n" + + "or press ENTER to skip."; + printDoubleLineMessage(message); + } + + public static void invalidPersonalTwitterUsernameErrorMessage() { + String message = "The twitter username is not correctly formatted,\n" + + "Rules for Twitter username :\n" + + " * Lowercase letters only\n" + + " * Numbers and underscore allowed\n" + + " * Maximum 15 characters allowed\n\n" + + "Please enter your twitter username again\n" + + "or press ENTER to skip."; + printDoubleLineMessage(message); + } + + public static void invalidPersonalEmailErrorMessage() { + String message = "The email id is not correctly formatted,\n" + + "Rules for email id :\n" + + " * Lowercase letters only\n" + + " * Numbers, underscore, hyphen and dot allowed\n" + + " * @ cannot be at the start or end\n\n" + + "Please enter your email again\n" + + "or press ENTER to skip."; + printDoubleLineMessage(message); + } + + public static void invalidPersonalLinkedinUsernameErrorMessage() { + String message = "The linkedin username is not correctly formatted,\n" + + "Rules for Linkedin username :\n" + + " * Lowercase letters only\n" + + " * Numbers, underscore and hyphen allowed\n" + + " * Length between 3 to 100 characters\n\n" + + "Please enter your linkedin username again\n" + + "or press ENTER to skip."; + printDoubleLineMessage(message); + } + // Error Messages public static void fileErrorMessage(String contactFilePath) { String message = "ConTech is unfortunately unable to access / create a\n" + " save file at " + contactFilePath @@ -135,7 +192,7 @@ public static void invalidGithubUsernameInput() { + " * Only lowercase allowed\n" + " * Maximum 39 characters allowed\n" + " * Cannot have multiple consecutive hyphens\n" - + " * Cannot begin or end with a hyphen\n"; + + " * Cannot begin or end with a hyphen"; printDoubleLineMessage(message); } @@ -167,7 +224,7 @@ public static void invalidEmailInput() { printDoubleLineMessage(message); } - public static void invalidLinkedinInput() { + public static void invalidLinkedinUsernameInput() { String message = "The linkedin username is not correctly formatted,\n" + "Rules for Linkedin username :\n" + " * Lowercase letters only\n" diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 0d8e7526e4..d642036f0c 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -54,6 +54,37 @@ public static void greetingMessage(Contact personalContact) { printDoubleLineMessage(message); } + public static void promptPersonalGithubUsernameMessage(String personalName) { + String message = "Hello, " + personalName + ".\n\n" + + "Please provide us with your Github Username\n" + + "or press ENTER if you would like to skip."; + printDoubleLineMessage(message); + } + + public static void promptPersonalTelegramUsernameMessage() { + String message = "Please provide us with your Telegram Handle\n" + + "or press ENTER if you would like to skip."; + printDoubleLineMessage(message); + } + + public static void promptPersonalTwitterUsernameMessage() { + String message = "Please provide us with your Twitter Username\n" + + "or press ENTER if you would like to skip."; + printDoubleLineMessage(message); + } + + public static void promptPersonalEmailMessage() { + String message = "Please provide us with your Email Address\n" + + "or press ENTER if you would like to skip."; + printDoubleLineMessage(message); + } + + public static void promptPersonalLinkedInUsernameMessage() { + String message = "Please provide us with your LinkedIn Username\n" + + "or press ENTER if you would like to skip."; + printDoubleLineMessage(message); + } + public static void createNewContactFileMessage(String contactFilePath) { String message = "As ConTech is unable to find your saved data,\n" + " it has created a new one for you at:\n" + contactFilePath; From aec3d77bd538e8dd6538dec86595771980ec76c5 Mon Sep 17 00:00:00 2001 From: lezong Date: Sun, 17 Oct 2021 17:33:15 +0800 Subject: [PATCH 289/756] Add Telegram field in personal contact --- src/main/java/seedu/ui/ExceptionTextUi.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index 398be53a65..39c050eff9 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -79,16 +79,6 @@ public static void invalidPersonalEmailErrorMessage() { printDoubleLineMessage(message); } - public static void invalidPersonalLinkedinUsernameErrorMessage() { - String message = "The linkedin username is not correctly formatted,\n" - + "Rules for Linkedin username :\n" - + " * Lowercase letters only\n" - + " * Numbers, underscore and hyphen allowed\n" - + " * Length between 3 to 100 characters\n\n" - + "Please enter your linkedin username again\n" - + "or press ENTER to skip."; - printDoubleLineMessage(message); - } // Error Messages public static void fileErrorMessage(String contactFilePath) { From ba3d7c0cec097c5128540510177ddb05e82527dd Mon Sep 17 00:00:00 2001 From: lezong Date: Sun, 17 Oct 2021 17:36:05 +0800 Subject: [PATCH 290/756] Add Twitter field in personal contact --- .../parser/AddPersonalContactParser.java | 25 +++++++++++++++++++ src/main/java/seedu/ui/ExceptionTextUi.java | 10 ++++++++ 2 files changed, 35 insertions(+) diff --git a/src/main/java/seedu/parser/AddPersonalContactParser.java b/src/main/java/seedu/parser/AddPersonalContactParser.java index 0e1d47de5f..3f93e17e1f 100644 --- a/src/main/java/seedu/parser/AddPersonalContactParser.java +++ b/src/main/java/seedu/parser/AddPersonalContactParser.java @@ -9,6 +9,7 @@ import seedu.exception.InvalidGithubUsernameException; import seedu.exception.InvalidNameException; import seedu.exception.InvalidTelegramUsernameException; +import seedu.exception.InvalidTwitterUsernameException; import seedu.ui.ExceptionTextUi; import seedu.ui.TextUi; import seedu.ui.UserInputTextUi; @@ -30,6 +31,7 @@ public AddPersonalContactParser() { promptPersonalName(); promptPersonalGithubUsername(); promptPersonalTelegramUsername(); + promptPersonalTwitterUsername(); TextUi.greetingMessage(personalContact); } @@ -94,6 +96,29 @@ public void setTelegramIfValid(String userInput) throws InvalidTelegramUsernameE } } + private void promptPersonalTwitterUsername() { + isValidDetail = false; + TextUi.promptPersonalTwitterUsernameMessage(); + do { + try { + String personalTwitter = UserInputTextUi.getUserInput(); + setTwitterIfValid(personalTwitter); + } catch (InvalidTwitterUsernameException e) { + ExceptionTextUi.invalidPersonalTwitterUsernameErrorMessage(); + } + } while (!isValidDetail); + } + + public void setTwitterIfValid(String userInput) throws InvalidTwitterUsernameException { + if (userInput.isEmpty()) { + isValidDetail = true; + } else { + checkTwitterUsernameRegex(userInput); + isValidDetail = true; + this.personalContact.setTwitter(userInput); + } + } + // private void setDetailsIfValid(String userInput, String flag) throws InvalidGithubUsernameException, // InvalidTelegramUsernameException { diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index 39c050eff9..398be53a65 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -79,6 +79,16 @@ public static void invalidPersonalEmailErrorMessage() { printDoubleLineMessage(message); } + public static void invalidPersonalLinkedinUsernameErrorMessage() { + String message = "The linkedin username is not correctly formatted,\n" + + "Rules for Linkedin username :\n" + + " * Lowercase letters only\n" + + " * Numbers, underscore and hyphen allowed\n" + + " * Length between 3 to 100 characters\n\n" + + "Please enter your linkedin username again\n" + + "or press ENTER to skip."; + printDoubleLineMessage(message); + } // Error Messages public static void fileErrorMessage(String contactFilePath) { From 6a89528678a94cbd6d0276ddc578ca6b8e9f2687 Mon Sep 17 00:00:00 2001 From: lezong Date: Sun, 17 Oct 2021 17:48:13 +0800 Subject: [PATCH 291/756] Add Email field in personal contact --- .../parser/AddPersonalContactParser.java | 64 ++++++++----------- 1 file changed, 28 insertions(+), 36 deletions(-) diff --git a/src/main/java/seedu/parser/AddPersonalContactParser.java b/src/main/java/seedu/parser/AddPersonalContactParser.java index 3f93e17e1f..0485509432 100644 --- a/src/main/java/seedu/parser/AddPersonalContactParser.java +++ b/src/main/java/seedu/parser/AddPersonalContactParser.java @@ -1,27 +1,17 @@ package seedu.parser; - -import seedu.command.ExitCommand; -import seedu.command.FailedCommand; -import seedu.command.HelpCommand; -import seedu.command.ListContactsCommand; import seedu.contact.Contact; import seedu.exception.InvalidGithubUsernameException; import seedu.exception.InvalidNameException; import seedu.exception.InvalidTelegramUsernameException; import seedu.exception.InvalidTwitterUsernameException; +import seedu.exception.InvalidLinkedinUsernameException; +import seedu.exception.InvalidEmailException; import seedu.ui.ExceptionTextUi; import seedu.ui.TextUi; import seedu.ui.UserInputTextUi; public class AddPersonalContactParser extends RegexParser { - public static final String NAME_FLAG = "n"; - public static final String GITHUB_FLAG = "g"; - public static final String TELEGRAM_FLAG = "te"; - public static final String TWITTER_FLAG = "tw"; - public static final String EMAIL_FLAG = "e"; - public static final String LINKEDIN_FLAG = "l"; - private Contact personalContact = new Contact(null, null,null,null, null,null); private boolean isValidDetail = false; @@ -32,6 +22,7 @@ public AddPersonalContactParser() { promptPersonalGithubUsername(); promptPersonalTelegramUsername(); promptPersonalTwitterUsername(); + promptPersonalEmailAddress(); TextUi.greetingMessage(personalContact); } @@ -63,7 +54,7 @@ private void promptPersonalGithubUsername() { } while (!isValidDetail); } - public void setGithubIfValid(String userInput) throws InvalidGithubUsernameException { + private void setGithubIfValid(String userInput) throws InvalidGithubUsernameException { if (userInput.isEmpty()) { isValidDetail = true; } else { @@ -86,7 +77,7 @@ private void promptPersonalTelegramUsername() { } while (!isValidDetail); } - public void setTelegramIfValid(String userInput) throws InvalidTelegramUsernameException { + private void setTelegramIfValid(String userInput) throws InvalidTelegramUsernameException { if (userInput.isEmpty()) { isValidDetail = true; } else { @@ -109,7 +100,7 @@ private void promptPersonalTwitterUsername() { } while (!isValidDetail); } - public void setTwitterIfValid(String userInput) throws InvalidTwitterUsernameException { + private void setTwitterIfValid(String userInput) throws InvalidTwitterUsernameException { if (userInput.isEmpty()) { isValidDetail = true; } else { @@ -119,28 +110,29 @@ public void setTwitterIfValid(String userInput) throws InvalidTwitterUsernameExc } } + private void promptPersonalEmailAddress() { + isValidDetail = false; + TextUi.promptPersonalEmailMessage(); + do { + try { + String personalEmail = UserInputTextUi.getUserInput(); + setEmailIfValid(personalEmail); + } catch (InvalidEmailException e) { + ExceptionTextUi.invalidPersonalEmailErrorMessage(); + } + } while (!isValidDetail); + } + + private void setEmailIfValid(String userInput) throws InvalidEmailException { + if (userInput.isEmpty()) { + isValidDetail = true; + } else { + checkEmailRegex(userInput); + isValidDetail = true; + this.personalContact.setEmail(userInput); + } + } -// private void setDetailsIfValid(String userInput, String flag) throws InvalidGithubUsernameException, -// InvalidTelegramUsernameException { -// if (userInput.isEmpty()) { -// isValidDetail = true; -// return; -// } -// switch (flag) { -// case GITHUB_FLAG: -// checkGithubUsernameRegex(userInput); -// isValidDetail = true; -// this.personalContact.setGithub(userInput); -// break; -// case TELEGRAM_FLAG: -// checkTelegramUsernameRegex(userInput); -// isValidDetail = true; -// this.personalContact.setTelegram(userInput); -// break; -// default: -// return; -// } -// } public Contact getPersonalContact() { return personalContact; From bc9e62b673ecd6985e5bf41a34ebc6b573608948 Mon Sep 17 00:00:00 2001 From: lezong Date: Sun, 17 Oct 2021 17:48:30 +0800 Subject: [PATCH 292/756] Add LinkedIn field in personal contact --- .../parser/AddPersonalContactParser.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/main/java/seedu/parser/AddPersonalContactParser.java b/src/main/java/seedu/parser/AddPersonalContactParser.java index 0485509432..bfd31d9eea 100644 --- a/src/main/java/seedu/parser/AddPersonalContactParser.java +++ b/src/main/java/seedu/parser/AddPersonalContactParser.java @@ -23,6 +23,7 @@ public AddPersonalContactParser() { promptPersonalTelegramUsername(); promptPersonalTwitterUsername(); promptPersonalEmailAddress(); + promptPersonalLinkedInUsername(); TextUi.greetingMessage(personalContact); } @@ -133,6 +134,28 @@ private void setEmailIfValid(String userInput) throws InvalidEmailException { } } + private void promptPersonalLinkedInUsername() { + isValidDetail = false; + TextUi.promptPersonalLinkedInUsernameMessage(); + do { + try { + String personalLinkedIn = UserInputTextUi.getUserInput(); + setLinkedInIfValid(personalLinkedIn); + } catch (InvalidLinkedinUsernameException e) { + ExceptionTextUi.invalidPersonalLinkedinUsernameErrorMessage(); + } + } while (!isValidDetail); + } + + private void setLinkedInIfValid(String userInput) throws InvalidLinkedinUsernameException { + if (userInput.isEmpty()) { + isValidDetail = true; + } else { + checkLinkedinUsernameRegex(userInput); + isValidDetail = true; + this.personalContact.setLinkedin(userInput); + } + } public Contact getPersonalContact() { return personalContact; From 8f586cbe93f40dcda867d314caa527cde6e27d65 Mon Sep 17 00:00:00 2001 From: lezong Date: Sun, 17 Oct 2021 18:18:02 +0800 Subject: [PATCH 293/756] Change Ui for first run of app --- .../seedu/parser/AddPersonalContactParser.java | 18 +++++++++++++----- src/main/java/seedu/storage/Storage.java | 1 + src/main/java/seedu/ui/TextUi.java | 18 +++++++++++++----- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/main/java/seedu/parser/AddPersonalContactParser.java b/src/main/java/seedu/parser/AddPersonalContactParser.java index bfd31d9eea..8922c3c746 100644 --- a/src/main/java/seedu/parser/AddPersonalContactParser.java +++ b/src/main/java/seedu/parser/AddPersonalContactParser.java @@ -18,13 +18,21 @@ public class AddPersonalContactParser extends RegexParser { public AddPersonalContactParser() { TextUi.welcomeMessage(); + } + + + public void startCollectingPersonalDetails() { promptPersonalName(); - promptPersonalGithubUsername(); - promptPersonalTelegramUsername(); - promptPersonalTwitterUsername(); - promptPersonalEmailAddress(); - promptPersonalLinkedInUsername(); TextUi.greetingMessage(personalContact); + String userConfirmation = UserInputTextUi.getUserConfirmation(); + if (userConfirmation != null || userConfirmation.isBlank()) { + promptPersonalGithubUsername(); + promptPersonalTelegramUsername(); + promptPersonalTwitterUsername(); + promptPersonalEmailAddress(); + promptPersonalLinkedInUsername(); + TextUi.finishSetUpMessage(); + } } private void promptPersonalName() { diff --git a/src/main/java/seedu/storage/Storage.java b/src/main/java/seedu/storage/Storage.java index 2456c86881..1260f8aa5c 100644 --- a/src/main/java/seedu/storage/Storage.java +++ b/src/main/java/seedu/storage/Storage.java @@ -79,6 +79,7 @@ public Contact loadExistingPersonalContact() throws FileErrorException { isFirstRun = true; // get new contact's name AddPersonalContactParser addPersonalContactParser = new AddPersonalContactParser(); + addPersonalContactParser.startCollectingPersonalDetails(); Contact personalContact = addPersonalContactParser.getPersonalContact(); ContactsEncoder.savePersonalContact(personalContactFilePath, personalContact); return personalContact; diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index d642036f0c..b42f0179d2 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -48,15 +48,23 @@ public static void welcomeBackMessage(Contact personalContact) { public static void greetingMessage(Contact personalContact) { String message = "Hello there, " + personalContact.getName() + ".\n\n" + "This is ConTech, your very own contact tracking application\n" - + "to manage computing-related contacts, like GitHub Accounts\n" - + "or even Emails.\n\n" - + "Enter \"help\" to see what you can do with ConTech."; + + "to manage tech-related contacts, like GitHub Accounts or\n" + + "even Emails.\n\n" + + "Before we start, let's set up your personal contact, shall\n" + + "we?\n\n" + + "Enter anything to continue..."; + printDoubleLineMessage(message); + } + + public static void finishSetUpMessage() { + String message = "You have successfully set up your own personal contact.\n" + + "Don't worry, you can always edit your personal details \n" + + "later on.\n\nTo see what you can do with ConTech, enter \"help\"."; printDoubleLineMessage(message); } public static void promptPersonalGithubUsernameMessage(String personalName) { - String message = "Hello, " + personalName + ".\n\n" - + "Please provide us with your Github Username\n" + String message = "Please provide us with your Github Username\n" + "or press ENTER if you would like to skip."; printDoubleLineMessage(message); } From c182ccca5fc947016156b54763b3412786818331 Mon Sep 17 00:00:00 2001 From: lezong Date: Sun, 17 Oct 2021 18:28:24 +0800 Subject: [PATCH 294/756] Add detail padding before user input --- .../java/seedu/parser/AddPersonalContactParser.java | 10 +++++----- src/main/java/seedu/ui/ExceptionTextUi.java | 6 ++++++ src/main/java/seedu/ui/TextUi.java | 8 +++++++- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/main/java/seedu/parser/AddPersonalContactParser.java b/src/main/java/seedu/parser/AddPersonalContactParser.java index 8922c3c746..50a1cba610 100644 --- a/src/main/java/seedu/parser/AddPersonalContactParser.java +++ b/src/main/java/seedu/parser/AddPersonalContactParser.java @@ -64,7 +64,7 @@ private void promptPersonalGithubUsername() { } private void setGithubIfValid(String userInput) throws InvalidGithubUsernameException { - if (userInput.isEmpty()) { + if (userInput.isEmpty() || userInput == null) { isValidDetail = true; } else { checkGithubUsernameRegex(userInput); @@ -87,7 +87,7 @@ private void promptPersonalTelegramUsername() { } private void setTelegramIfValid(String userInput) throws InvalidTelegramUsernameException { - if (userInput.isEmpty()) { + if (userInput.isEmpty() || userInput == null) { isValidDetail = true; } else { checkTelegramUsernameRegex(userInput); @@ -110,7 +110,7 @@ private void promptPersonalTwitterUsername() { } private void setTwitterIfValid(String userInput) throws InvalidTwitterUsernameException { - if (userInput.isEmpty()) { + if (userInput.isEmpty() || userInput == null) { isValidDetail = true; } else { checkTwitterUsernameRegex(userInput); @@ -133,7 +133,7 @@ private void promptPersonalEmailAddress() { } private void setEmailIfValid(String userInput) throws InvalidEmailException { - if (userInput.isEmpty()) { + if (userInput.isEmpty() || userInput == null) { isValidDetail = true; } else { checkEmailRegex(userInput); @@ -156,7 +156,7 @@ private void promptPersonalLinkedInUsername() { } private void setLinkedInIfValid(String userInput) throws InvalidLinkedinUsernameException { - if (userInput.isEmpty()) { + if (userInput.isEmpty() || userInput == null) { isValidDetail = true; } else { checkLinkedinUsernameRegex(userInput); diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index 398be53a65..ec0152ed54 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -31,6 +31,7 @@ public static void invalidPersonalNameErrorMessage() { + " * Cannot be \"null\"\n\n" + "Please enter your name again."; printDoubleLineMessage(message); + System.out.print("Name:"); } public static void invalidPersonalGithubUsernameErrorMessage() { @@ -44,6 +45,7 @@ public static void invalidPersonalGithubUsernameErrorMessage() { + "Please enter your github username again\n" + "or press ENTER to skip."; printDoubleLineMessage(message); + System.out.print("GitHub Username:"); } public static void invalidPersonalTelegramUsernameErrorMessage() { @@ -55,6 +57,7 @@ public static void invalidPersonalTelegramUsernameErrorMessage() { + "Please enter your telegram username again\n" + "or press ENTER to skip."; printDoubleLineMessage(message); + System.out.print("Telegram Handle: @"); } public static void invalidPersonalTwitterUsernameErrorMessage() { @@ -66,6 +69,7 @@ public static void invalidPersonalTwitterUsernameErrorMessage() { + "Please enter your twitter username again\n" + "or press ENTER to skip."; printDoubleLineMessage(message); + System.out.print("Twitter Username:"); } public static void invalidPersonalEmailErrorMessage() { @@ -77,6 +81,7 @@ public static void invalidPersonalEmailErrorMessage() { + "Please enter your email again\n" + "or press ENTER to skip."; printDoubleLineMessage(message); + System.out.print("Email Address:"); } public static void invalidPersonalLinkedinUsernameErrorMessage() { @@ -88,6 +93,7 @@ public static void invalidPersonalLinkedinUsernameErrorMessage() { + "Please enter your linkedin username again\n" + "or press ENTER to skip."; printDoubleLineMessage(message); + System.out.print("LinkedIn Username:"); } // Error Messages diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index b42f0179d2..be0ffea474 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -36,11 +36,12 @@ public static void welcomeMessage() { String message = "Welcome to ConTech, your personal contact tracker.\n" + "Can I get your name?"; printBottomLineMessage(message); + System.out.print("Name:"); } public static void welcomeBackMessage(Contact personalContact) { printDoubleLineMessage(LOGO); - String message = "Hello, " + personalContact.getName() + ". Welcome back to ConTech, " + String message = "Hello, " + personalContact.getName() + ". \nWelcome back to ConTech, " + "your personal \ncontact tracker."; printBottomLineMessage(message); } @@ -67,30 +68,35 @@ public static void promptPersonalGithubUsernameMessage(String personalName) { String message = "Please provide us with your Github Username\n" + "or press ENTER if you would like to skip."; printDoubleLineMessage(message); + System.out.print("GitHub Username:"); } public static void promptPersonalTelegramUsernameMessage() { String message = "Please provide us with your Telegram Handle\n" + "or press ENTER if you would like to skip."; printDoubleLineMessage(message); + System.out.print("Telegram Handle: @"); } public static void promptPersonalTwitterUsernameMessage() { String message = "Please provide us with your Twitter Username\n" + "or press ENTER if you would like to skip."; printDoubleLineMessage(message); + System.out.print("Twitter Username:"); } public static void promptPersonalEmailMessage() { String message = "Please provide us with your Email Address\n" + "or press ENTER if you would like to skip."; printDoubleLineMessage(message); + System.out.print("Email Address:"); } public static void promptPersonalLinkedInUsernameMessage() { String message = "Please provide us with your LinkedIn Username\n" + "or press ENTER if you would like to skip."; printDoubleLineMessage(message); + System.out.print("LinkedIn Username:"); } public static void createNewContactFileMessage(String contactFilePath) { From d1e9b231684f715cfe3603af87895bd5dfdb6af3 Mon Sep 17 00:00:00 2001 From: lezong Date: Sun, 17 Oct 2021 18:32:21 +0800 Subject: [PATCH 295/756] Minor edits to AddPersonalContactParser --- .../parser/AddPersonalContactParser.java | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/main/java/seedu/parser/AddPersonalContactParser.java b/src/main/java/seedu/parser/AddPersonalContactParser.java index 50a1cba610..22c45d8354 100644 --- a/src/main/java/seedu/parser/AddPersonalContactParser.java +++ b/src/main/java/seedu/parser/AddPersonalContactParser.java @@ -20,22 +20,21 @@ public AddPersonalContactParser() { TextUi.welcomeMessage(); } - public void startCollectingPersonalDetails() { - promptPersonalName(); + parsePersonalName(); TextUi.greetingMessage(personalContact); String userConfirmation = UserInputTextUi.getUserConfirmation(); if (userConfirmation != null || userConfirmation.isBlank()) { - promptPersonalGithubUsername(); - promptPersonalTelegramUsername(); - promptPersonalTwitterUsername(); - promptPersonalEmailAddress(); - promptPersonalLinkedInUsername(); + parsePersonalGithubUsername(); + parsePersonalTelegramUsername(); + parsePersonalTwitterUsername(); + parsePersonalEmailAddress(); + parsePersonalLinkedInUsername(); TextUi.finishSetUpMessage(); } } - private void promptPersonalName() { + private void parsePersonalName() { isValidDetail = false; do { try { @@ -50,7 +49,7 @@ private void promptPersonalName() { } while (!isValidDetail); } - private void promptPersonalGithubUsername() { + private void parsePersonalGithubUsername() { isValidDetail = false; TextUi.promptPersonalGithubUsernameMessage(this.personalContact.getName()); do { @@ -73,7 +72,7 @@ private void setGithubIfValid(String userInput) throws InvalidGithubUsernameExce } } - private void promptPersonalTelegramUsername() { + private void parsePersonalTelegramUsername() { isValidDetail = false; TextUi.promptPersonalTelegramUsernameMessage(); do { @@ -96,7 +95,7 @@ private void setTelegramIfValid(String userInput) throws InvalidTelegramUsername } } - private void promptPersonalTwitterUsername() { + private void parsePersonalTwitterUsername() { isValidDetail = false; TextUi.promptPersonalTwitterUsernameMessage(); do { @@ -119,7 +118,7 @@ private void setTwitterIfValid(String userInput) throws InvalidTwitterUsernameEx } } - private void promptPersonalEmailAddress() { + private void parsePersonalEmailAddress() { isValidDetail = false; TextUi.promptPersonalEmailMessage(); do { @@ -142,7 +141,7 @@ private void setEmailIfValid(String userInput) throws InvalidEmailException { } } - private void promptPersonalLinkedInUsername() { + private void parsePersonalLinkedInUsername() { isValidDetail = false; TextUi.promptPersonalLinkedInUsernameMessage(); do { From a829bde5a430a6c036383dac121798ef9d402447 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sun, 17 Oct 2021 20:14:29 +0800 Subject: [PATCH 296/756] Add basic styling for puml class diagrams --- docs/diagrams/style.puml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 docs/diagrams/style.puml diff --git a/docs/diagrams/style.puml b/docs/diagrams/style.puml new file mode 100644 index 0000000000..aeb3c2f71f --- /dev/null +++ b/docs/diagrams/style.puml @@ -0,0 +1,6 @@ +skinparam MinClassWidth 50 +skinparam Shadowing false + +hide footbox +hide members +hide circle \ No newline at end of file From b128ad6e476137991cdafb1fec3b9663a7edb063 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sun, 17 Oct 2021 20:14:44 +0800 Subject: [PATCH 297/756] Add system architecture diagram --- docs/diagrams/SystemArchitectureDiagram.puml | 28 +++++++++++++++++++ docs/images/SystemArchitectureDiagram.png | Bin 0 -> 15734 bytes 2 files changed, 28 insertions(+) create mode 100644 docs/diagrams/SystemArchitectureDiagram.puml create mode 100644 docs/images/SystemArchitectureDiagram.png diff --git a/docs/diagrams/SystemArchitectureDiagram.puml b/docs/diagrams/SystemArchitectureDiagram.puml new file mode 100644 index 0000000000..c00894649e --- /dev/null +++ b/docs/diagrams/SystemArchitectureDiagram.puml @@ -0,0 +1,28 @@ +@startuml +!include +!include style.puml + +Package "ConTech"<>{ + Class TextUi + Class MainParser + Class Storage + Class Command + Class ContactList + Class Main #grey +} + +Class "<$user>" as User + +Command --> TextUi : Failed\nCommand +TextUi -right-> MainParser +MainParser -down-> Command +Command -down-> ContactList : Pass\nCommand +ContactList -right-> Storage +Storage .left.> ContactList +Main -up[#grey]-> MainParser +Main -down[#grey]-> Storage +Storage .right.> LocalStorage + +User ..> TextUi + +@enduml \ No newline at end of file diff --git a/docs/images/SystemArchitectureDiagram.png b/docs/images/SystemArchitectureDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..a7fdc8b62c3fee4dc245ce07c57d20ac9f763269 GIT binary patch literal 15734 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 literal 0 HcmV?d00001 From 4247aa88910beddde22c768d9a4aac209ea9e889 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sun, 17 Oct 2021 20:15:16 +0800 Subject: [PATCH 298/756] Add basic table of content for DG --- docs/DeveloperGuide.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index d63f897001..643cc61d1b 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -1,6 +1,24 @@ # Developer Guide ## Acknowledgements +### Table of Content +- [Acknowledgements](#acknowledgements) +- [Design](#design) + - [System Architecture](#sys-arch) + - [TextUi](#text-ui) + - [MainParser](#main-parser) + - [Command](#command) + - [ContactList](#contact-list) + - [Storage](#storage) +- [Implementation](#implementation) +- [Product Scope](#scope) + - [Target user profile](#target) + - [Value proposition](#value) +- [User Stories](#stories) +- [Non-Function Requirements](#nf-req) +- [Glossary](#glossary) +- [Instructions for manual testing](#manual-test) + - Inspiration for App Idea and OOP Structure: AddressBook (Level 2)
https://github.com/se-edu/addressbook-level2 From 0ee71b3e2bdd2bfa16894a89b10ede40c45dfc87 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sun, 17 Oct 2021 20:15:35 +0800 Subject: [PATCH 299/756] Update acknowledgements in DG --- docs/DeveloperGuide.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 643cc61d1b..67932235fd 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -1,6 +1,5 @@ # Developer Guide -## Acknowledgements ### Table of Content - [Acknowledgements](#acknowledgements) - [Design](#design) @@ -19,6 +18,7 @@ - [Glossary](#glossary) - [Instructions for manual testing](#manual-test) +## Acknowledgements - Inspiration for App Idea and OOP Structure: AddressBook (Level 2)
https://github.com/se-edu/addressbook-level2 @@ -27,6 +27,10 @@ https://se-education.org/addressbook-level3/UserGuide.html - Converting text for ConTech:
https://patorjk.com/software/taag/#p=display&f=Graffiti&t=Type%20Something%20 +- GitHub Markdown Emoji Syntax for User Guide:
+ https://github.com/ikatyang/emoji-cheat-sheet/blob/master/README.md +- PlantUML Tutorial:
+ https://se-education.org/guides/tutorials/plantUml.html {list here sources of all reused/adapted ideas, code, documentation, and third-party libraries -- include links to the original source as well} From 856a5522b9e1ec365d8ebf9ea50874736edc9d91 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sun, 17 Oct 2021 20:15:59 +0800 Subject: [PATCH 300/756] Add system architecture in DG - design --- docs/DeveloperGuide.md | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 67932235fd..2325443ff5 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -34,7 +34,34 @@ {list here sources of all reused/adapted ideas, code, documentation, and third-party libraries -- include links to the original source as well} -## Design & implementation +## Design + +### System Architecture + +![System Architecture](images/SystemArchitectureDiagram.png) + +The above **System Architecture** diagram shows the high-level design of ConTech. + +On launch, the `Main` class initialises the app components in the correct sequence and links them up +with each other, in the correct sequence. + +ConTech comprises five main components, namely: +- `TextUi`: Command Line User Interface of ConTech. +- `MainParser`: Parser to parser user inputs from `TextUi` for `Command`. +- `Command`: Command to be executed upon input parsing. +- `ContactList`: Data structure to store `Contact`s while running ConTech. +- `Storage`: Reads from and writes to [`LocalStorage`](#local-storage). + +The five main components interact with each other, as shown in the sequence diagram below. +{ NEED SEQUENCE DIAGRAM } + +### TextUi +### MainParser +### Command +### ContactList +### Storage + +## Implementation {Describe the design and implementation of the product. Use UML diagrams and short code snippets where applicable.} From 01af077e1dfcca7f3080cd1e19868728b9be6cf4 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sun, 17 Oct 2021 20:16:10 +0800 Subject: [PATCH 301/756] Create basic template for DG --- docs/DeveloperGuide.md | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 2325443ff5..b504dfaa70 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -65,35 +65,40 @@ The five main components interact with each other, as shown in the sequence diag {Describe the design and implementation of the product. Use UML diagrams and short code snippets where applicable.} +{NOT DONE} -## Product scope -### Target user profile +## Product scope +### Target user profile - Has a need to store a significant amount of computing-related contacts - Prefers and is familiar with Command Line Interface (CLI) applications - Has many contacts that use common computing platforms, such as: Github, Linkedin, Twitter, Telegram, and Email - Can type fast and prefers typing to mouse interactions -### Value proposition +### Value proposition As computing professionals are often on their computer, ConTech allows them to have a platform to manage their computing-related contacts locally and efficiently, without the need to use additional devices or platforms. -## User Stories +## User Stories + +{NOT DONE} |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| -## Non-Functional Requirements +## Non-Functional Requirements +- Should work on any [*mainstream Operating Systems*](#os) as long as Java `11` or higher has been installed on it {Give non-functional requirements} -## Glossary +## Glossary -* *glossary item* - Definition +* **Mainstream Operating Systems** - Windows, macOS, *NIX +* **LocalStorage** - Refers to user's hard disk storage -## Instructions for manual testing +## 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} From 66f8d5860c9ae411b8d4de24142918644c4aec4d Mon Sep 17 00:00:00 2001 From: lezong Date: Sun, 17 Oct 2021 20:31:17 +0800 Subject: [PATCH 302/756] Update inputs.txt in Text-ui-test --- text-ui-test/ACTUAL.TXT | 57 ++++++++++++++++++++++++++++++---- text-ui-test/EXPECTED-UNIX.TXT | 57 ++++++++++++++++++++++++++++++---- text-ui-test/EXPECTED.TXT | 57 ++++++++++++++++++++++++++++++---- text-ui-test/input.txt | 7 +++++ 4 files changed, 160 insertions(+), 18 deletions(-) diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index 283e033e74..4cc5815b2d 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -23,14 +23,61 @@ Welcome to ConTech, your personal contact tracker. Can I get your name? ____________________________________________________________ -____________________________________________________________ +Name:____________________________________________________________ Hello there, Le Zong. This is ConTech, your very own contact tracking application -to manage computing-related contacts, like GitHub Accounts -or even Emails. +to manage tech-related contacts, like GitHub Accounts or +even Emails. + +Before we start, let's set up your personal contact, shall +we? + +Enter anything to continue... +____________________________________________________________ + +____________________________________________________________ +Please provide us with your Github Username +or press ENTER if you would like to skip. +____________________________________________________________ + +GitHub Username:____________________________________________________________ +Please provide us with your Telegram Handle +or press ENTER if you would like to skip. +____________________________________________________________ + +Telegram Handle: @____________________________________________________________ +Please provide us with your Twitter Username +or press ENTER if you would like to skip. +____________________________________________________________ + +Twitter Username:____________________________________________________________ +Please provide us with your Email Address +or press ENTER if you would like to skip. +____________________________________________________________ -Enter "help" to see what you can do with ConTech. +Email Address:____________________________________________________________ +The email id is not correctly formatted, +Rules for email id : + * Lowercase letters only + * Numbers, underscore, hyphen and dot allowed + * @ cannot be at the start or end + +Please enter your email again +or press ENTER to skip. +____________________________________________________________ + +Email Address:____________________________________________________________ +Please provide us with your LinkedIn Username +or press ENTER if you would like to skip. +____________________________________________________________ + +LinkedIn Username:____________________________________________________________ +You have successfully set up your own personal contact. +Don't worry, you can always edit your personal details +later on. + +To see what you can do with ConTech, enter "help". ____________________________________________________________ ____________________________________________________________ @@ -315,7 +362,6 @@ Rules for Github username : * Maximum 39 characters allowed * Cannot have multiple consecutive hyphens * Cannot begin or end with a hyphen - ____________________________________________________________ ____________________________________________________________ @@ -326,7 +372,6 @@ Rules for Github username : * Maximum 39 characters allowed * Cannot have multiple consecutive hyphens * Cannot begin or end with a hyphen - ____________________________________________________________ ____________________________________________________________ diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index 283e033e74..4cc5815b2d 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -23,14 +23,61 @@ Welcome to ConTech, your personal contact tracker. Can I get your name? ____________________________________________________________ -____________________________________________________________ +Name:____________________________________________________________ Hello there, Le Zong. This is ConTech, your very own contact tracking application -to manage computing-related contacts, like GitHub Accounts -or even Emails. +to manage tech-related contacts, like GitHub Accounts or +even Emails. + +Before we start, let's set up your personal contact, shall +we? + +Enter anything to continue... +____________________________________________________________ + +____________________________________________________________ +Please provide us with your Github Username +or press ENTER if you would like to skip. +____________________________________________________________ + +GitHub Username:____________________________________________________________ +Please provide us with your Telegram Handle +or press ENTER if you would like to skip. +____________________________________________________________ + +Telegram Handle: @____________________________________________________________ +Please provide us with your Twitter Username +or press ENTER if you would like to skip. +____________________________________________________________ + +Twitter Username:____________________________________________________________ +Please provide us with your Email Address +or press ENTER if you would like to skip. +____________________________________________________________ -Enter "help" to see what you can do with ConTech. +Email Address:____________________________________________________________ +The email id is not correctly formatted, +Rules for email id : + * Lowercase letters only + * Numbers, underscore, hyphen and dot allowed + * @ cannot be at the start or end + +Please enter your email again +or press ENTER to skip. +____________________________________________________________ + +Email Address:____________________________________________________________ +Please provide us with your LinkedIn Username +or press ENTER if you would like to skip. +____________________________________________________________ + +LinkedIn Username:____________________________________________________________ +You have successfully set up your own personal contact. +Don't worry, you can always edit your personal details +later on. + +To see what you can do with ConTech, enter "help". ____________________________________________________________ ____________________________________________________________ @@ -315,7 +362,6 @@ Rules for Github username : * Maximum 39 characters allowed * Cannot have multiple consecutive hyphens * Cannot begin or end with a hyphen - ____________________________________________________________ ____________________________________________________________ @@ -326,7 +372,6 @@ Rules for Github username : * Maximum 39 characters allowed * Cannot have multiple consecutive hyphens * Cannot begin or end with a hyphen - ____________________________________________________________ ____________________________________________________________ diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 283e033e74..4cc5815b2d 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -23,14 +23,61 @@ Welcome to ConTech, your personal contact tracker. Can I get your name? ____________________________________________________________ -____________________________________________________________ +Name:____________________________________________________________ Hello there, Le Zong. This is ConTech, your very own contact tracking application -to manage computing-related contacts, like GitHub Accounts -or even Emails. +to manage tech-related contacts, like GitHub Accounts or +even Emails. + +Before we start, let's set up your personal contact, shall +we? + +Enter anything to continue... +____________________________________________________________ + +____________________________________________________________ +Please provide us with your Github Username +or press ENTER if you would like to skip. +____________________________________________________________ + +GitHub Username:____________________________________________________________ +Please provide us with your Telegram Handle +or press ENTER if you would like to skip. +____________________________________________________________ + +Telegram Handle: @____________________________________________________________ +Please provide us with your Twitter Username +or press ENTER if you would like to skip. +____________________________________________________________ + +Twitter Username:____________________________________________________________ +Please provide us with your Email Address +or press ENTER if you would like to skip. +____________________________________________________________ -Enter "help" to see what you can do with ConTech. +Email Address:____________________________________________________________ +The email id is not correctly formatted, +Rules for email id : + * Lowercase letters only + * Numbers, underscore, hyphen and dot allowed + * @ cannot be at the start or end + +Please enter your email again +or press ENTER to skip. +____________________________________________________________ + +Email Address:____________________________________________________________ +Please provide us with your LinkedIn Username +or press ENTER if you would like to skip. +____________________________________________________________ + +LinkedIn Username:____________________________________________________________ +You have successfully set up your own personal contact. +Don't worry, you can always edit your personal details +later on. + +To see what you can do with ConTech, enter "help". ____________________________________________________________ ____________________________________________________________ @@ -315,7 +362,6 @@ Rules for Github username : * Maximum 39 characters allowed * Cannot have multiple consecutive hyphens * Cannot begin or end with a hyphen - ____________________________________________________________ ____________________________________________________________ @@ -326,7 +372,6 @@ Rules for Github username : * Maximum 39 characters allowed * Cannot have multiple consecutive hyphens * Cannot begin or end with a hyphen - ____________________________________________________________ ____________________________________________________________ diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index 58df2626d9..d7b616c228 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -1,4 +1,11 @@ Le Zong + +lezongmun +lezongg + +@gmail.com +lezongmun@gmail.com + rm 1 add -n ng andre -g ng-andre rm 2 From fe274fb6d3b9f1508f458d22c22cddb89fe90dff Mon Sep 17 00:00:00 2001 From: lezong Date: Sun, 17 Oct 2021 22:42:25 +0800 Subject: [PATCH 303/756] Add spaces in text --- src/main/java/seedu/ui/ExceptionTextUi.java | 10 +++++----- src/main/java/seedu/ui/TextUi.java | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index ec0152ed54..218ed5b521 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -31,7 +31,7 @@ public static void invalidPersonalNameErrorMessage() { + " * Cannot be \"null\"\n\n" + "Please enter your name again."; printDoubleLineMessage(message); - System.out.print("Name:"); + System.out.print("Name: "); } public static void invalidPersonalGithubUsernameErrorMessage() { @@ -45,7 +45,7 @@ public static void invalidPersonalGithubUsernameErrorMessage() { + "Please enter your github username again\n" + "or press ENTER to skip."; printDoubleLineMessage(message); - System.out.print("GitHub Username:"); + System.out.print("GitHub Username: "); } public static void invalidPersonalTelegramUsernameErrorMessage() { @@ -69,7 +69,7 @@ public static void invalidPersonalTwitterUsernameErrorMessage() { + "Please enter your twitter username again\n" + "or press ENTER to skip."; printDoubleLineMessage(message); - System.out.print("Twitter Username:"); + System.out.print("Twitter Username: "); } public static void invalidPersonalEmailErrorMessage() { @@ -81,7 +81,7 @@ public static void invalidPersonalEmailErrorMessage() { + "Please enter your email again\n" + "or press ENTER to skip."; printDoubleLineMessage(message); - System.out.print("Email Address:"); + System.out.print("Email Address: "); } public static void invalidPersonalLinkedinUsernameErrorMessage() { @@ -93,7 +93,7 @@ public static void invalidPersonalLinkedinUsernameErrorMessage() { + "Please enter your linkedin username again\n" + "or press ENTER to skip."; printDoubleLineMessage(message); - System.out.print("LinkedIn Username:"); + System.out.print("LinkedIn Username: "); } // Error Messages diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index be0ffea474..13a6b391a7 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -36,7 +36,7 @@ public static void welcomeMessage() { String message = "Welcome to ConTech, your personal contact tracker.\n" + "Can I get your name?"; printBottomLineMessage(message); - System.out.print("Name:"); + System.out.print("Name: "); } public static void welcomeBackMessage(Contact personalContact) { @@ -68,7 +68,7 @@ public static void promptPersonalGithubUsernameMessage(String personalName) { String message = "Please provide us with your Github Username\n" + "or press ENTER if you would like to skip."; printDoubleLineMessage(message); - System.out.print("GitHub Username:"); + System.out.print("GitHub Username: "); } public static void promptPersonalTelegramUsernameMessage() { @@ -82,21 +82,21 @@ public static void promptPersonalTwitterUsernameMessage() { String message = "Please provide us with your Twitter Username\n" + "or press ENTER if you would like to skip."; printDoubleLineMessage(message); - System.out.print("Twitter Username:"); + System.out.print("Twitter Username: "); } public static void promptPersonalEmailMessage() { String message = "Please provide us with your Email Address\n" + "or press ENTER if you would like to skip."; printDoubleLineMessage(message); - System.out.print("Email Address:"); + System.out.print("Email Address: "); } public static void promptPersonalLinkedInUsernameMessage() { String message = "Please provide us with your LinkedIn Username\n" + "or press ENTER if you would like to skip."; printDoubleLineMessage(message); - System.out.print("LinkedIn Username:"); + System.out.print("LinkedIn Username: "); } public static void createNewContactFileMessage(String contactFilePath) { From e323c135aac068c901b96e1be978d247838cfc91 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Mon, 18 Oct 2021 20:19:01 +0800 Subject: [PATCH 304/756] Add comparator class --- src/main/java/seedu/contact/ContactComparator.java | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 src/main/java/seedu/contact/ContactComparator.java diff --git a/src/main/java/seedu/contact/ContactComparator.java b/src/main/java/seedu/contact/ContactComparator.java new file mode 100644 index 0000000000..d62ceeab03 --- /dev/null +++ b/src/main/java/seedu/contact/ContactComparator.java @@ -0,0 +1,2 @@ +package seedu.contact;public class contactComparator { +} From ccb836655c58a49eb252a6fd512ecdce9a733cd1 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Mon, 18 Oct 2021 20:20:42 +0800 Subject: [PATCH 305/756] Update comparator for sort --- src/main/java/seedu/contact/ContactComparator.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/contact/ContactComparator.java b/src/main/java/seedu/contact/ContactComparator.java index d62ceeab03..21dab2ba50 100644 --- a/src/main/java/seedu/contact/ContactComparator.java +++ b/src/main/java/seedu/contact/ContactComparator.java @@ -1,2 +1,9 @@ -package seedu.contact;public class contactComparator { +package seedu.contact; + +import java.util.Comparator; + +public class ContactComparator implements Comparator { + public int compare(Contact contact1, Contact contact2) { + return contact1.getName().compareTo(contact2.getName()); + } } From 78ec9fd05abaf273d597bf24afcdd8442f6ee536 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Mon, 18 Oct 2021 20:21:07 +0800 Subject: [PATCH 306/756] Implement ascending sort --- src/main/java/seedu/contact/ContactList.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/seedu/contact/ContactList.java b/src/main/java/seedu/contact/ContactList.java index 1feb35fc5e..a53a277eba 100644 --- a/src/main/java/seedu/contact/ContactList.java +++ b/src/main/java/seedu/contact/ContactList.java @@ -20,6 +20,7 @@ public ContactList() { public void addContact(Contact contact) { contacts.add(contact); + contacts.sort(new ContactComparator()); } public void editContact(String[] contactDetails, int contactIndex) throws InvalidFlagException { @@ -28,6 +29,7 @@ public void editContact(String[] contactDetails, int contactIndex) throws Invali switch (i) { case NAME_INDEX: contacts.get(contactIndex).setName(contactDetails[i]); + contacts.sort(new ContactComparator()); break; case GITHUB_INDEX: contacts.get(contactIndex).setGithub(contactDetails[i]); @@ -62,6 +64,7 @@ public int getIndexOfContact(Contact contact) { } public Contact getContactAtIndex(int index) { + contacts.sort(new ContactComparator()); return contacts.get(index); } From 7a05f0433af3aa65ad4bc138ddd0136d1d247117 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Mon, 18 Oct 2021 20:21:23 +0800 Subject: [PATCH 307/756] Update IO redirection tests --- text-ui-test/ACTUAL.TXT | 62 +++++++++++++++++----------------- text-ui-test/EXPECTED-UNIX.TXT | 62 +++++++++++++++++----------------- text-ui-test/EXPECTED.TXT | 62 +++++++++++++++++----------------- 3 files changed, 93 insertions(+), 93 deletions(-) diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index 4cc5815b2d..eb423ac716 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -111,8 +111,8 @@ ____________________________________________________________ ____________________________________________________________ Delete this contact? (y/n) -1. ashraf -Github: github.com/ashraf +1. ng andre +Github: github.com/ng-andre ____________________________________________________________ ____________________________________________________________ @@ -121,8 +121,8 @@ ____________________________________________________________ ____________________________________________________________ Delete this contact? (y/n) -1. ashraf -Github: github.com/ashraf +1. ng andre +Github: github.com/ng-andre ____________________________________________________________ ____________________________________________________________ @@ -163,11 +163,11 @@ ConTech has 5 contacts stored. Here's the list : ____________________________________________________________ -0. ng andre +0. andre 1. ashraf -2. mayank -3. bory -4. andre +2. bory +3. mayank +4. ng andre ____________________________________________________________ @@ -210,28 +210,28 @@ ConTech has 6 contacts stored. Here's the list : ____________________________________________________________ -0. ng andre +0. andre 1. ashraf -2. mayank -3. bory -4. andre -5. lezong +2. bory +3. lezong +4. mayank +5. ng andre ____________________________________________________________ ____________________________________________________________ -3. bory -Github: github.com/marcus +3. lezong +Github: github.com/lezongmun ____________________________________________________________ ____________________________________________________________ Delete this contact? (y/n) -0. ng andre +0. andre Github: github.com/ng-andre ____________________________________________________________ ____________________________________________________________ -ConTech has removed the specified contact: ng andre +ConTech has removed the specified contact: andre You now have 5 contact(s). ____________________________________________________________ @@ -259,8 +259,8 @@ and ensure that your flags used are correct: ____________________________________________________________ ____________________________________________________________ -2. andre -Github: github.com/ng-andre +2. mayank +Github: github.com/mayankp123 ____________________________________________________________ ____________________________________________________________ @@ -299,8 +299,8 @@ ____________________________________________________________ ____________________________________________________________ Delete this contact? (y/n) -1. bory -Github: github.com/marcus +1. lezong +Github: github.com/lezongmun ____________________________________________________________ ____________________________________________________________ @@ -309,12 +309,12 @@ ____________________________________________________________ ____________________________________________________________ Delete this contact? (y/n) -1. bory -Github: github.com/marcus +1. lezong +Github: github.com/lezongmun ____________________________________________________________ ____________________________________________________________ -ConTech has removed the specified contact: bory +ConTech has removed the specified contact: lezong You now have 4 contact(s). ____________________________________________________________ @@ -323,10 +323,10 @@ ConTech has 4 contacts stored. Here's the list : ____________________________________________________________ -0. mayank -1. andre -2. lezong -3. lezongmun +0. bory +1. lezongmun +2. mayank +3. ng andre ____________________________________________________________ @@ -392,8 +392,8 @@ You now have 6 contact(s). ____________________________________________________________ ____________________________________________________________ -0. mayank -Github: github.com/mayankp123 +0. asjoda sadfsd +Telegram: t.me/_123adad ____________________________________________________________ ____________________________________________________________ @@ -441,7 +441,7 @@ ____________________________________________________________ ____________________________________________________________ ConTech has edited the specified contact: -Name: lezongmun +Name: lezong mun Github: github.com/new-git ____________________________________________________________ diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index 4cc5815b2d..eb423ac716 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -111,8 +111,8 @@ ____________________________________________________________ ____________________________________________________________ Delete this contact? (y/n) -1. ashraf -Github: github.com/ashraf +1. ng andre +Github: github.com/ng-andre ____________________________________________________________ ____________________________________________________________ @@ -121,8 +121,8 @@ ____________________________________________________________ ____________________________________________________________ Delete this contact? (y/n) -1. ashraf -Github: github.com/ashraf +1. ng andre +Github: github.com/ng-andre ____________________________________________________________ ____________________________________________________________ @@ -163,11 +163,11 @@ ConTech has 5 contacts stored. Here's the list : ____________________________________________________________ -0. ng andre +0. andre 1. ashraf -2. mayank -3. bory -4. andre +2. bory +3. mayank +4. ng andre ____________________________________________________________ @@ -210,28 +210,28 @@ ConTech has 6 contacts stored. Here's the list : ____________________________________________________________ -0. ng andre +0. andre 1. ashraf -2. mayank -3. bory -4. andre -5. lezong +2. bory +3. lezong +4. mayank +5. ng andre ____________________________________________________________ ____________________________________________________________ -3. bory -Github: github.com/marcus +3. lezong +Github: github.com/lezongmun ____________________________________________________________ ____________________________________________________________ Delete this contact? (y/n) -0. ng andre +0. andre Github: github.com/ng-andre ____________________________________________________________ ____________________________________________________________ -ConTech has removed the specified contact: ng andre +ConTech has removed the specified contact: andre You now have 5 contact(s). ____________________________________________________________ @@ -259,8 +259,8 @@ and ensure that your flags used are correct: ____________________________________________________________ ____________________________________________________________ -2. andre -Github: github.com/ng-andre +2. mayank +Github: github.com/mayankp123 ____________________________________________________________ ____________________________________________________________ @@ -299,8 +299,8 @@ ____________________________________________________________ ____________________________________________________________ Delete this contact? (y/n) -1. bory -Github: github.com/marcus +1. lezong +Github: github.com/lezongmun ____________________________________________________________ ____________________________________________________________ @@ -309,12 +309,12 @@ ____________________________________________________________ ____________________________________________________________ Delete this contact? (y/n) -1. bory -Github: github.com/marcus +1. lezong +Github: github.com/lezongmun ____________________________________________________________ ____________________________________________________________ -ConTech has removed the specified contact: bory +ConTech has removed the specified contact: lezong You now have 4 contact(s). ____________________________________________________________ @@ -323,10 +323,10 @@ ConTech has 4 contacts stored. Here's the list : ____________________________________________________________ -0. mayank -1. andre -2. lezong -3. lezongmun +0. bory +1. lezongmun +2. mayank +3. ng andre ____________________________________________________________ @@ -392,8 +392,8 @@ You now have 6 contact(s). ____________________________________________________________ ____________________________________________________________ -0. mayank -Github: github.com/mayankp123 +0. asjoda sadfsd +Telegram: t.me/_123adad ____________________________________________________________ ____________________________________________________________ @@ -441,7 +441,7 @@ ____________________________________________________________ ____________________________________________________________ ConTech has edited the specified contact: -Name: lezongmun +Name: lezong mun Github: github.com/new-git ____________________________________________________________ diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 4cc5815b2d..eb423ac716 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -111,8 +111,8 @@ ____________________________________________________________ ____________________________________________________________ Delete this contact? (y/n) -1. ashraf -Github: github.com/ashraf +1. ng andre +Github: github.com/ng-andre ____________________________________________________________ ____________________________________________________________ @@ -121,8 +121,8 @@ ____________________________________________________________ ____________________________________________________________ Delete this contact? (y/n) -1. ashraf -Github: github.com/ashraf +1. ng andre +Github: github.com/ng-andre ____________________________________________________________ ____________________________________________________________ @@ -163,11 +163,11 @@ ConTech has 5 contacts stored. Here's the list : ____________________________________________________________ -0. ng andre +0. andre 1. ashraf -2. mayank -3. bory -4. andre +2. bory +3. mayank +4. ng andre ____________________________________________________________ @@ -210,28 +210,28 @@ ConTech has 6 contacts stored. Here's the list : ____________________________________________________________ -0. ng andre +0. andre 1. ashraf -2. mayank -3. bory -4. andre -5. lezong +2. bory +3. lezong +4. mayank +5. ng andre ____________________________________________________________ ____________________________________________________________ -3. bory -Github: github.com/marcus +3. lezong +Github: github.com/lezongmun ____________________________________________________________ ____________________________________________________________ Delete this contact? (y/n) -0. ng andre +0. andre Github: github.com/ng-andre ____________________________________________________________ ____________________________________________________________ -ConTech has removed the specified contact: ng andre +ConTech has removed the specified contact: andre You now have 5 contact(s). ____________________________________________________________ @@ -259,8 +259,8 @@ and ensure that your flags used are correct: ____________________________________________________________ ____________________________________________________________ -2. andre -Github: github.com/ng-andre +2. mayank +Github: github.com/mayankp123 ____________________________________________________________ ____________________________________________________________ @@ -299,8 +299,8 @@ ____________________________________________________________ ____________________________________________________________ Delete this contact? (y/n) -1. bory -Github: github.com/marcus +1. lezong +Github: github.com/lezongmun ____________________________________________________________ ____________________________________________________________ @@ -309,12 +309,12 @@ ____________________________________________________________ ____________________________________________________________ Delete this contact? (y/n) -1. bory -Github: github.com/marcus +1. lezong +Github: github.com/lezongmun ____________________________________________________________ ____________________________________________________________ -ConTech has removed the specified contact: bory +ConTech has removed the specified contact: lezong You now have 4 contact(s). ____________________________________________________________ @@ -323,10 +323,10 @@ ConTech has 4 contacts stored. Here's the list : ____________________________________________________________ -0. mayank -1. andre -2. lezong -3. lezongmun +0. bory +1. lezongmun +2. mayank +3. ng andre ____________________________________________________________ @@ -392,8 +392,8 @@ You now have 6 contact(s). ____________________________________________________________ ____________________________________________________________ -0. mayank -Github: github.com/mayankp123 +0. asjoda sadfsd +Telegram: t.me/_123adad ____________________________________________________________ ____________________________________________________________ @@ -441,7 +441,7 @@ ____________________________________________________________ ____________________________________________________________ ConTech has edited the specified contact: -Name: lezongmun +Name: lezong mun Github: github.com/new-git ____________________________________________________________ From 5640822aa2a4c4e92a88eb889d425b71aac84992 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Mon, 18 Oct 2021 21:27:57 +0800 Subject: [PATCH 308/756] Add author tags --- src/main/java/seedu/command/InvalidDetailCommand.java | 2 ++ src/main/java/seedu/command/ListContactsCommand.java | 2 ++ src/main/java/seedu/contact/ContactComparator.java | 2 ++ src/main/java/seedu/exception/InvalidEmailException.java | 2 ++ src/main/java/seedu/exception/InvalidFlagException.java | 2 ++ .../seedu/exception/InvalidGithubUsernameException.java | 2 ++ .../seedu/exception/InvalidLinkedinUsernameException.java | 2 ++ src/main/java/seedu/exception/InvalidNameException.java | 2 ++ .../seedu/exception/InvalidTelegramUsernameException.java | 2 ++ .../seedu/exception/InvalidTwitterUsernameException.java | 2 ++ src/main/java/seedu/parser/MainParser.java | 2 ++ src/main/java/seedu/parser/RegexParser.java | 3 ++- src/main/java/seedu/ui/ExceptionTextUi.java | 6 ++++++ 13 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/command/InvalidDetailCommand.java b/src/main/java/seedu/command/InvalidDetailCommand.java index 44a3d0d676..cc66fed0b7 100644 --- a/src/main/java/seedu/command/InvalidDetailCommand.java +++ b/src/main/java/seedu/command/InvalidDetailCommand.java @@ -1,3 +1,5 @@ +//@@author mayankp291 + package seedu.command; import seedu.parser.FailedCommandType; diff --git a/src/main/java/seedu/command/ListContactsCommand.java b/src/main/java/seedu/command/ListContactsCommand.java index 5ee646c2ed..482e20f325 100644 --- a/src/main/java/seedu/command/ListContactsCommand.java +++ b/src/main/java/seedu/command/ListContactsCommand.java @@ -1,3 +1,5 @@ +//@@author mayankp291 + package seedu.command; import seedu.ui.TextUi; diff --git a/src/main/java/seedu/contact/ContactComparator.java b/src/main/java/seedu/contact/ContactComparator.java index 21dab2ba50..649966cc65 100644 --- a/src/main/java/seedu/contact/ContactComparator.java +++ b/src/main/java/seedu/contact/ContactComparator.java @@ -1,3 +1,5 @@ +//@@author mayankp291 + package seedu.contact; import java.util.Comparator; diff --git a/src/main/java/seedu/exception/InvalidEmailException.java b/src/main/java/seedu/exception/InvalidEmailException.java index bcc7261120..39686cb717 100644 --- a/src/main/java/seedu/exception/InvalidEmailException.java +++ b/src/main/java/seedu/exception/InvalidEmailException.java @@ -1,3 +1,5 @@ +//@@author mayankp291 + package seedu.exception; public class InvalidEmailException extends Exception { diff --git a/src/main/java/seedu/exception/InvalidFlagException.java b/src/main/java/seedu/exception/InvalidFlagException.java index db17ee92f9..7713bdcb41 100644 --- a/src/main/java/seedu/exception/InvalidFlagException.java +++ b/src/main/java/seedu/exception/InvalidFlagException.java @@ -1,3 +1,5 @@ +//@@author mayankp291 + package seedu.exception; public class InvalidFlagException extends Exception { diff --git a/src/main/java/seedu/exception/InvalidGithubUsernameException.java b/src/main/java/seedu/exception/InvalidGithubUsernameException.java index f6149b525c..b4261604f6 100644 --- a/src/main/java/seedu/exception/InvalidGithubUsernameException.java +++ b/src/main/java/seedu/exception/InvalidGithubUsernameException.java @@ -1,3 +1,5 @@ +//@@author mayankp291 + package seedu.exception; public class InvalidGithubUsernameException extends Exception { diff --git a/src/main/java/seedu/exception/InvalidLinkedinUsernameException.java b/src/main/java/seedu/exception/InvalidLinkedinUsernameException.java index bb14510600..63d52f221a 100644 --- a/src/main/java/seedu/exception/InvalidLinkedinUsernameException.java +++ b/src/main/java/seedu/exception/InvalidLinkedinUsernameException.java @@ -1,3 +1,5 @@ +//@@author mayankp291 + package seedu.exception; public class InvalidLinkedinUsernameException extends Exception { diff --git a/src/main/java/seedu/exception/InvalidNameException.java b/src/main/java/seedu/exception/InvalidNameException.java index dccf326de6..f7f152e0b6 100644 --- a/src/main/java/seedu/exception/InvalidNameException.java +++ b/src/main/java/seedu/exception/InvalidNameException.java @@ -1,3 +1,5 @@ +//@@author mayankp291 + package seedu.exception; public class InvalidNameException extends Exception { diff --git a/src/main/java/seedu/exception/InvalidTelegramUsernameException.java b/src/main/java/seedu/exception/InvalidTelegramUsernameException.java index 99c04bd7f8..11d9370b03 100644 --- a/src/main/java/seedu/exception/InvalidTelegramUsernameException.java +++ b/src/main/java/seedu/exception/InvalidTelegramUsernameException.java @@ -1,3 +1,5 @@ +//@@author mayankp291 + package seedu.exception; public class InvalidTelegramUsernameException extends Exception { diff --git a/src/main/java/seedu/exception/InvalidTwitterUsernameException.java b/src/main/java/seedu/exception/InvalidTwitterUsernameException.java index 5a0f05a196..cb6056d381 100644 --- a/src/main/java/seedu/exception/InvalidTwitterUsernameException.java +++ b/src/main/java/seedu/exception/InvalidTwitterUsernameException.java @@ -1,3 +1,5 @@ +//@@author mayankp291 + package seedu.exception; public class InvalidTwitterUsernameException extends Exception { diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index a68d3cb628..3d4d45156f 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -125,6 +125,7 @@ private Command parseEditContact(String userInput) { // userInput is raw user in } } + //@@author mayankp291 private Command parseInvalidDetailCommand(Exception e) { if (e instanceof InvalidNameException) { return new InvalidDetailCommand(FailedCommandType.INVALID_NAME); @@ -151,6 +152,7 @@ private Command parseInvalidDetailCommand(Exception e) { return new FailedCommand(FailedCommandType.GENERAL); } + //@@author private Command parseViewContact(String userInput) { try { int viewedIndex = IndexParser.getIndexFromInput(userInput); diff --git a/src/main/java/seedu/parser/RegexParser.java b/src/main/java/seedu/parser/RegexParser.java index 037cbbf7f8..07e4efe976 100644 --- a/src/main/java/seedu/parser/RegexParser.java +++ b/src/main/java/seedu/parser/RegexParser.java @@ -1,3 +1,5 @@ +//@@author mayankp291 + package seedu.parser; import seedu.exception.InvalidEmailException; @@ -10,7 +12,6 @@ import java.util.logging.Level; import java.util.logging.Logger; - public abstract class RegexParser { public static final String NAME_FLAG = "n"; diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index ec0152ed54..0915b0ea8b 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -181,6 +181,7 @@ public static void forbiddenDetailMessage() { printDoubleLineMessage(message); } + //@@author mayankp291 public static void invalidNameInput() { String message = "The name is not correctly formatted,\n" + "Rules for name :\n" @@ -191,6 +192,7 @@ public static void invalidNameInput() { printDoubleLineMessage(message); } + //@@author mayankp291 public static void invalidGithubUsernameInput() { String message = "The github username is not correctly formatted,\n" + "Rules for Github username :\n" @@ -202,6 +204,7 @@ public static void invalidGithubUsernameInput() { printDoubleLineMessage(message); } + //@@author mayankp291 public static void invalidTelegramUsernameInput() { String message = "The telegram username is not correctly formatted,\n" + "Rules for Telegram username :\n" @@ -211,6 +214,7 @@ public static void invalidTelegramUsernameInput() { printDoubleLineMessage(message); } + //@@author mayankp291 public static void invalidTwitterUsernameInput() { String message = "The twitter username is not correctly formatted,\n" + "Rules for Twitter username :\n" @@ -220,6 +224,7 @@ public static void invalidTwitterUsernameInput() { printDoubleLineMessage(message); } + //@@author mayankp291 //not full, need to update public static void invalidEmailInput() { String message = "The email id is not correctly formatted,\n" @@ -230,6 +235,7 @@ public static void invalidEmailInput() { printDoubleLineMessage(message); } + //@@author mayankp291 public static void invalidLinkedinUsernameInput() { String message = "The linkedin username is not correctly formatted,\n" + "Rules for Linkedin username :\n" From 1f28ae04c0f005364c60984083c57d870c41e941 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 19 Oct 2021 10:15:21 +0800 Subject: [PATCH 309/756] Add SearchContactParser class, implement parseSearchQuery method --- .../seedu/parser/SearchContactParser.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/main/java/seedu/parser/SearchContactParser.java diff --git a/src/main/java/seedu/parser/SearchContactParser.java b/src/main/java/seedu/parser/SearchContactParser.java new file mode 100644 index 0000000000..6c55339322 --- /dev/null +++ b/src/main/java/seedu/parser/SearchContactParser.java @@ -0,0 +1,21 @@ +package seedu.parser; + +import seedu.exception.MissingArgException; + +import java.util.Locale; + +public class SearchContactParser { + + private static final int NUMBER_OF_SEARCH_ARGS = 3; + + //return only search query as a String + public String parseSearchQuery(String userInput) throws MissingArgException { + String[] destructuredInputs = userInput.split(" ", NUMBER_OF_SEARCH_ARGS); + if (destructuredInputs.length == 2) { //search for name if no flag specified + return destructuredInputs[1].toLowerCase().trim(); + } else if (destructuredInputs.length == 3) { //search for name with flag + return destructuredInputs[2].toLowerCase().trim(); + } + throw new MissingArgException(); //if no query is specified + } +} From b3d18fda7f59a631608acf3b0a29e19b3f8c4485 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 19 Oct 2021 10:15:51 +0800 Subject: [PATCH 310/756] Add search methods for main parser --- src/main/java/seedu/parser/MainParser.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 3d4d45156f..d77fa0b466 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -10,6 +10,7 @@ import seedu.command.FailedCommand; import seedu.command.ExitCommand; import seedu.command.ListContactsCommand; +import seedu.command.SearchContactCommand; import seedu.exception.ForbiddenDetailException; import seedu.exception.InvalidEmailException; @@ -33,6 +34,7 @@ public class MainParser { private static final String EXIT_COMD = "exit"; private static final String LIST_COMD = "list"; private static final String HELP_COMD = "help"; + private static final String SEARCH_COMD = "search"; private static final int COMD_WORD_INDEX = 0; private static final int ISOLATE_COMD_WORD = 2; @@ -67,6 +69,9 @@ public Command parseCommand(String userInput) { case HELP_COMD: command = new HelpCommand(); break; + case SEARCH_COMD: + command = new parseSearchCommand(userInput); + break; default: command = new FailedCommand(FailedCommandType.GENERAL); } From 96a187dc0d53414a05a321858f6129249f0296fc Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 19 Oct 2021 11:03:53 +0800 Subject: [PATCH 311/756] Change getIndexToStore to public --- src/main/java/seedu/parser/ContactParser.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index ac33ef219a..ef68ad0628 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -21,6 +21,7 @@ public abstract class ContactParser extends RegexParser { public static final int NUMBER_OF_DETAILS = 2; public static final int NUMBER_OF_ADD_ARGS = 2; public static final int NUMBER_OF_EDIT_ARGS = 3; + public static final int NUMBER_OF_SEARCH_ARGS = 3; public static final int NUMBER_OF_FIELDS = 6; public static final String DETAIL_SEPARATOR = " -"; @@ -73,8 +74,7 @@ public void parseDetail(String[] contactDetails, String detail) contactDetails[indexToStore] = detailToStore; } - - private int getIndexToStore(String flag) throws InvalidFlagException { + public int getIndexToStore(String flag) throws InvalidFlagException { int indexToStore; switch (flag) { case NAME_FLAG: From f7c619f0e4443dc8705241de779fd62da2acc638 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 19 Oct 2021 11:05:09 +0800 Subject: [PATCH 312/756] Inherit ContactParser for SearchContactParser and implement getDetailFlag method --- .../seedu/parser/SearchContactParser.java | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/main/java/seedu/parser/SearchContactParser.java b/src/main/java/seedu/parser/SearchContactParser.java index 6c55339322..1caf3794c1 100644 --- a/src/main/java/seedu/parser/SearchContactParser.java +++ b/src/main/java/seedu/parser/SearchContactParser.java @@ -1,13 +1,9 @@ package seedu.parser; +import seedu.exception.InvalidFlagException; import seedu.exception.MissingArgException; -import java.util.Locale; - -public class SearchContactParser { - - private static final int NUMBER_OF_SEARCH_ARGS = 3; - +public class SearchContactParser extends ContactParser { //return only search query as a String public String parseSearchQuery(String userInput) throws MissingArgException { String[] destructuredInputs = userInput.split(" ", NUMBER_OF_SEARCH_ARGS); @@ -16,6 +12,27 @@ public String parseSearchQuery(String userInput) throws MissingArgException { } else if (destructuredInputs.length == 3) { //search for name with flag return destructuredInputs[2].toLowerCase().trim(); } - throw new MissingArgException(); //if no query is specified + //no query specified + //destructuredInputs.length == 1 + throw new MissingArgException(); + } + + public int getDetailFlag(String userInput) throws MissingArgException, InvalidFlagException { + String[] destructuredInputs = userInput.split(" ", NUMBER_OF_SEARCH_ARGS); + //"search " with one or two spaces should not have an issue since the input is trimmed + if (destructuredInputs.length == 1) { //no arguments specified, only "search" + throw new MissingArgException(); + } else if (destructuredInputs.length == 2) { //no flag specified + return -1; + } else { + assert destructuredInputs.length == 3; + return getIndexToStore(destructuredInputs[2]); + } + } + + //method not used for Search but has to be implemented for classes inheriting ContactParser + public String[] parseContactDetails(String userInput) { + assert false; + return new String[0]; } } From f890944060733924fc482556bc334cc55349a44e Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Tue, 19 Oct 2021 11:29:11 +0800 Subject: [PATCH 313/756] Move constants and common method regarding contacts to Interface --- .../java/seedu/parser/ContactDetails.java | 52 +++++++++++++++++++ src/main/java/seedu/parser/ContactParser.java | 48 +---------------- 2 files changed, 54 insertions(+), 46 deletions(-) create mode 100644 src/main/java/seedu/parser/ContactDetails.java diff --git a/src/main/java/seedu/parser/ContactDetails.java b/src/main/java/seedu/parser/ContactDetails.java new file mode 100644 index 0000000000..1a38b2ea31 --- /dev/null +++ b/src/main/java/seedu/parser/ContactDetails.java @@ -0,0 +1,52 @@ +package seedu.parser; + +import seedu.contact.DetailType; +import seedu.exception.InvalidFlagException; + +public interface ContactDetails { + int CONTACT_PARAMS_START_INDEX = 1; + int NUMBER_OF_DETAILS = 2; + int NUMBER_OF_ADD_ARGS = 2; + int NUMBER_OF_EDIT_ARGS = 3; + int NUMBER_OF_FIELDS = 6; + // int NUMBER_OF_SEARCH_ARGS = 2 OR 3; -- for andre + + String DETAIL_SEPARATOR = " -"; + int FLAG_INDEX_IN_DETAILS = 0; + int DETAIL_INDEX_IN_DETAILS = 1; + int USER_INFO_INDEX = 2; + + String NAME_FLAG = "n"; + String GITHUB_FLAG = "g"; + String TELEGRAM_FLAG = "te"; + String TWITTER_FLAG = "tw"; + String EMAIL_FLAG = "e"; + String LINKEDIN_FLAG = "l"; + + default int getIndexToStore(String flag) throws InvalidFlagException { + int indexToStore; + switch (flag) { + case NAME_FLAG: + indexToStore = DetailType.NAME.getIndex(); + break; + case GITHUB_FLAG: + indexToStore = DetailType.GITHUB.getIndex(); + break; + case TELEGRAM_FLAG: + indexToStore = DetailType.TELEGRAM.getIndex(); + break; + case TWITTER_FLAG: + indexToStore = DetailType.TWITTER.getIndex(); + break; + case EMAIL_FLAG: + indexToStore = DetailType.EMAIL.getIndex(); + break; + case LINKEDIN_FLAG: + indexToStore = DetailType.LINKEDIN.getIndex(); + break; + default: + throw new InvalidFlagException(); + } + return indexToStore; + } +} diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index ac33ef219a..92e3992b30 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -16,24 +16,8 @@ import java.util.logging.Logger; -public abstract class ContactParser extends RegexParser { - public static final int CONTACT_PARAMS_START_INDEX = 1; - public static final int NUMBER_OF_DETAILS = 2; - public static final int NUMBER_OF_ADD_ARGS = 2; - public static final int NUMBER_OF_EDIT_ARGS = 3; - public static final int NUMBER_OF_FIELDS = 6; +public abstract class ContactParser extends RegexParser implements ContactDetails { - public static final String DETAIL_SEPARATOR = " -"; - public static final int FLAG_INDEX_IN_DETAILS = 0; - public static final int DETAIL_INDEX_IN_DETAILS = 1; - public static final int USER_INFO_INDEX = 2; - - public static final String NAME_FLAG = "n"; - public static final String GITHUB_FLAG = "g"; - public static final String TELEGRAM_FLAG = "te"; - public static final String TWITTER_FLAG = "tw"; - public static final String EMAIL_FLAG = "e"; - public static final String LINKEDIN_FLAG = "l"; private static final Logger LOGGER = Logger.getLogger(ContactParser.class.getName()); @@ -72,32 +56,4 @@ public void parseDetail(String[] contactDetails, String detail) indexToStore = getIndexToStore(flag); contactDetails[indexToStore] = detailToStore; } - - - private int getIndexToStore(String flag) throws InvalidFlagException { - int indexToStore; - switch (flag) { - case NAME_FLAG: - indexToStore = DetailType.NAME.getIndex(); - break; - case GITHUB_FLAG: - indexToStore = DetailType.GITHUB.getIndex(); - break; - case TELEGRAM_FLAG: - indexToStore = DetailType.TELEGRAM.getIndex(); - break; - case TWITTER_FLAG: - indexToStore = DetailType.TWITTER.getIndex(); - break; - case EMAIL_FLAG: - indexToStore = DetailType.EMAIL.getIndex(); - break; - case LINKEDIN_FLAG: - indexToStore = DetailType.LINKEDIN.getIndex(); - break; - default: - throw new InvalidFlagException(); - } - return indexToStore; - } -} +} \ No newline at end of file From 46a0520ee68e6a490d2a6c72e11d86fc1c5859b5 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Tue, 19 Oct 2021 12:02:50 +0800 Subject: [PATCH 314/756] Make add and edit parsers as final --- src/main/java/seedu/parser/MainParser.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 3d4d45156f..d7aa37cfaf 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -39,8 +39,8 @@ public class MainParser { public static final int NAME_INDEX = 0; private ContactParser contactParser; - private AddContactParser addContactParser = new AddContactParser(); - private EditContactParser editContactParser = new EditContactParser(); + private final AddContactParser addContactParser = new AddContactParser(); + private final EditContactParser editContactParser = new EditContactParser(); public Command parseCommand(String userInput) { String commandType = getCommandWord(userInput); From b7856e718eb64a06d8a53345cf3ab2b42a5741a3 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Tue, 19 Oct 2021 12:03:22 +0800 Subject: [PATCH 315/756] Remove unnecessary import in add contact parser test --- src/test/java/seedu/parser/AddContactParserTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/java/seedu/parser/AddContactParserTest.java b/src/test/java/seedu/parser/AddContactParserTest.java index 00cc423a61..38bd7b325e 100644 --- a/src/test/java/seedu/parser/AddContactParserTest.java +++ b/src/test/java/seedu/parser/AddContactParserTest.java @@ -14,7 +14,6 @@ import seedu.exception.MissingArgException; import seedu.exception.MissingDetailException; -import static seedu.parser.ContactParser.NUMBER_OF_ADD_ARGS; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; From 0170a666af4827000d85adcb56b7f37fc04ce5b0 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Tue, 19 Oct 2021 12:03:40 +0800 Subject: [PATCH 316/756] Move constants for contact parser back from interface --- src/main/java/seedu/parser/ContactDetails.java | 11 ----------- src/main/java/seedu/parser/ContactParser.java | 10 +++++++++- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/main/java/seedu/parser/ContactDetails.java b/src/main/java/seedu/parser/ContactDetails.java index 1a38b2ea31..df428b6357 100644 --- a/src/main/java/seedu/parser/ContactDetails.java +++ b/src/main/java/seedu/parser/ContactDetails.java @@ -4,17 +4,6 @@ import seedu.exception.InvalidFlagException; public interface ContactDetails { - int CONTACT_PARAMS_START_INDEX = 1; - int NUMBER_OF_DETAILS = 2; - int NUMBER_OF_ADD_ARGS = 2; - int NUMBER_OF_EDIT_ARGS = 3; - int NUMBER_OF_FIELDS = 6; - // int NUMBER_OF_SEARCH_ARGS = 2 OR 3; -- for andre - - String DETAIL_SEPARATOR = " -"; - int FLAG_INDEX_IN_DETAILS = 0; - int DETAIL_INDEX_IN_DETAILS = 1; - int USER_INFO_INDEX = 2; String NAME_FLAG = "n"; String GITHUB_FLAG = "g"; diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index 92e3992b30..513e7918de 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -15,9 +15,17 @@ import java.util.logging.Level; import java.util.logging.Logger; - public abstract class ContactParser extends RegexParser implements ContactDetails { + public static final int CONTACT_PARAMS_START_INDEX = 1; + public static final int NUMBER_OF_DETAILS = 2; + public static final int NUMBER_OF_ADD_ARGS = 2; + public static final int NUMBER_OF_EDIT_ARGS = 3; + public static final int NUMBER_OF_FIELDS = 6; + public static final String DETAIL_SEPARATOR = " -"; + public static final int FLAG_INDEX_IN_DETAILS = 0; + public static final int DETAIL_INDEX_IN_DETAILS = 1; + public static final int USER_INFO_INDEX = 2; private static final Logger LOGGER = Logger.getLogger(ContactParser.class.getName()); From c228de9c3815e85d3d072a82f5db0888b84d9236 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 19 Oct 2021 13:33:36 +0800 Subject: [PATCH 317/756] Implement searchContact method in ContactList, update author --- src/main/java/seedu/contact/ContactList.java | 43 ++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/main/java/seedu/contact/ContactList.java b/src/main/java/seedu/contact/ContactList.java index a53a277eba..92d4e157a4 100644 --- a/src/main/java/seedu/contact/ContactList.java +++ b/src/main/java/seedu/contact/ContactList.java @@ -23,6 +23,7 @@ public void addContact(Contact contact) { contacts.sort(new ContactComparator()); } + //@@author ng-andre public void editContact(String[] contactDetails, int contactIndex) throws InvalidFlagException { for (int i = 0; i < contactDetails.length; i++) { if (contactDetails[i] != null) { @@ -59,6 +60,48 @@ public void deleteContact(int deletedIndex) { contacts.remove(deletedIndex); } + //@@author ng-andre + public void searchContact(String query, int detailType) throws InvalidFlagException { + for (Contact contact : contacts) { + switch (detailType) { + case NAME_INDEX: + if (contact.getName().toLowerCase().contains(query)) { + System.out.println(true); + } + break; + case GITHUB_INDEX: + if (contact.getGithub().toLowerCase().contains(query)) { + System.out.println(true); + } + break; + case LINKEDIN_INDEX: + if (contact.getLinkedin().toLowerCase().contains(query)) { + System.out.println(true); + } + break; + case TELEGRAM_INDEX: + if (contact.getTelegram().toLowerCase().contains(query)) { + System.out.println(true); + } + break; + case TWITTER_INDEX: + if (contact.getTwitter().toLowerCase().contains(query)) { + System.out.println(true); + } + break; + case EMAIL_INDEX: + if (contact.getEmail().toLowerCase().contains(query)) { + System.out.println(true); + } + break; + default: + //control should never reach here + assert false; + throw new InvalidFlagException(); + } + } + } + public int getIndexOfContact(Contact contact) { return contacts.indexOf(contact); } From 47b8bef7bcb0911866dc374c4db6e2633ce30d9f Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 19 Oct 2021 13:34:46 +0800 Subject: [PATCH 318/756] Update author and method call for search in MainParser --- src/main/java/seedu/parser/MainParser.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index d77fa0b466..34a622d289 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -70,7 +70,7 @@ public Command parseCommand(String userInput) { command = new HelpCommand(); break; case SEARCH_COMD: - command = new parseSearchCommand(userInput); + command = parseSearchCommand(userInput); break; default: command = new FailedCommand(FailedCommandType.GENERAL); @@ -108,6 +108,7 @@ private Command parseAddContact(String userInput) { } } + //@@author ng-andre private Command parseEditContact(String userInput) { // userInput is raw user input contactParser = editContactParser; try { @@ -179,4 +180,8 @@ private Command parseDeleteContact(String userInput) { return new FailedCommand(FailedCommandType.INVALID_INDEX); } } + + //@@author ng-andre + private Command parseSearchCommand(String userInput) { + } } From 0e46b7923f56cfd7a3b99daf16dfcb97d74117b3 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 19 Oct 2021 13:35:38 +0800 Subject: [PATCH 319/756] Remove inheritance for SearchContactParser --- .../java/seedu/parser/SearchContactParser.java | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/main/java/seedu/parser/SearchContactParser.java b/src/main/java/seedu/parser/SearchContactParser.java index 1caf3794c1..d4e69c781d 100644 --- a/src/main/java/seedu/parser/SearchContactParser.java +++ b/src/main/java/seedu/parser/SearchContactParser.java @@ -3,7 +3,10 @@ import seedu.exception.InvalidFlagException; import seedu.exception.MissingArgException; -public class SearchContactParser extends ContactParser { +import static seedu.parser.ContactParser.NUMBER_OF_SEARCH_ARGS; +import static seedu.parser.ContactParser.getIndexToStore; + +public class SearchContactParser { //return only search query as a String public String parseSearchQuery(String userInput) throws MissingArgException { String[] destructuredInputs = userInput.split(" ", NUMBER_OF_SEARCH_ARGS); @@ -13,14 +16,14 @@ public String parseSearchQuery(String userInput) throws MissingArgException { return destructuredInputs[2].toLowerCase().trim(); } //no query specified - //destructuredInputs.length == 1 + //destructuredInputs.length < 2 throw new MissingArgException(); } public int getDetailFlag(String userInput) throws MissingArgException, InvalidFlagException { String[] destructuredInputs = userInput.split(" ", NUMBER_OF_SEARCH_ARGS); //"search " with one or two spaces should not have an issue since the input is trimmed - if (destructuredInputs.length == 1) { //no arguments specified, only "search" + if (destructuredInputs.length < 2) { //no arguments specified, only "search" throw new MissingArgException(); } else if (destructuredInputs.length == 2) { //no flag specified return -1; @@ -29,10 +32,4 @@ public int getDetailFlag(String userInput) throws MissingArgException, InvalidFl return getIndexToStore(destructuredInputs[2]); } } - - //method not used for Search but has to be implemented for classes inheriting ContactParser - public String[] parseContactDetails(String userInput) { - assert false; - return new String[0]; - } } From 8715535848550c071252894640d3231722876f7a Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 19 Oct 2021 13:36:23 +0800 Subject: [PATCH 320/756] Implement Search Contact Command class --- .../seedu/command/SearchContactCommand.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/main/java/seedu/command/SearchContactCommand.java diff --git a/src/main/java/seedu/command/SearchContactCommand.java b/src/main/java/seedu/command/SearchContactCommand.java new file mode 100644 index 0000000000..4caf5d93b3 --- /dev/null +++ b/src/main/java/seedu/command/SearchContactCommand.java @@ -0,0 +1,23 @@ +package seedu.command; + +import seedu.exception.InvalidFlagException; +import seedu.exception.MissingDetailException; +import seedu.ui.ExceptionTextUi; + +public class SearchContactCommand extends Command { + String query; + int detailIndex; + + public SearchContactCommand(String query, int detailIndex) { + this.query = query; + this.detailIndex = detailIndex; + } + + public void execute() { + try { + contactList.searchContact(query, detailIndex); + } catch (InvalidFlagException e) { + ExceptionTextUi.invalidFlagMessage(); + } + } +} From 11d6d1c5dd467d18e57d1213203d8986649b070f Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 19 Oct 2021 13:36:39 +0800 Subject: [PATCH 321/756] Update getIndexToStore as static class --- src/main/java/seedu/parser/ContactParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index ef68ad0628..264a81fe88 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -74,7 +74,7 @@ public void parseDetail(String[] contactDetails, String detail) contactDetails[indexToStore] = detailToStore; } - public int getIndexToStore(String flag) throws InvalidFlagException { + public static int getIndexToStore(String flag) throws InvalidFlagException { int indexToStore; switch (flag) { case NAME_FLAG: From 6cb0700720c4bccbd3490535394a3df19c9a0f20 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 19 Oct 2021 14:33:40 +0800 Subject: [PATCH 322/756] Update Search method with TextUI method calls --- src/main/java/seedu/contact/ContactList.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/main/java/seedu/contact/ContactList.java b/src/main/java/seedu/contact/ContactList.java index 92d4e157a4..d08c57f30c 100644 --- a/src/main/java/seedu/contact/ContactList.java +++ b/src/main/java/seedu/contact/ContactList.java @@ -1,6 +1,7 @@ package seedu.contact; import seedu.exception.InvalidFlagException; +import seedu.ui.TextUi; import java.util.ArrayList; @@ -62,36 +63,37 @@ public void deleteContact(int deletedIndex) { //@@author ng-andre public void searchContact(String query, int detailType) throws InvalidFlagException { - for (Contact contact : contacts) { + for (int i = 0; i < contacts.size(); i++) { + Contact contact = getContactAtIndex(i); switch (detailType) { case NAME_INDEX: if (contact.getName().toLowerCase().contains(query)) { - System.out.println(true); + TextUi.viewContactMessage(contact, i); } break; case GITHUB_INDEX: if (contact.getGithub().toLowerCase().contains(query)) { - System.out.println(true); + TextUi.viewContactMessage(contact, i); } break; case LINKEDIN_INDEX: if (contact.getLinkedin().toLowerCase().contains(query)) { - System.out.println(true); + TextUi.viewContactMessage(contact, i); } break; case TELEGRAM_INDEX: if (contact.getTelegram().toLowerCase().contains(query)) { - System.out.println(true); + TextUi.viewContactMessage(contact, i); } break; case TWITTER_INDEX: if (contact.getTwitter().toLowerCase().contains(query)) { - System.out.println(true); + TextUi.viewContactMessage(contact, i); } break; case EMAIL_INDEX: if (contact.getEmail().toLowerCase().contains(query)) { - System.out.println(true); + TextUi.viewContactMessage(contact, i); } break; default: From 58580a043cebc6cdd81b3c136a56802753df2533 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 19 Oct 2021 14:34:08 +0800 Subject: [PATCH 323/756] Reorder switch cases for ContactDetails to reflect correct index --- src/main/java/seedu/parser/ContactDetails.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/parser/ContactDetails.java b/src/main/java/seedu/parser/ContactDetails.java index df428b6357..bcb5f52c43 100644 --- a/src/main/java/seedu/parser/ContactDetails.java +++ b/src/main/java/seedu/parser/ContactDetails.java @@ -21,6 +21,9 @@ default int getIndexToStore(String flag) throws InvalidFlagException { case GITHUB_FLAG: indexToStore = DetailType.GITHUB.getIndex(); break; + case LINKEDIN_FLAG: + indexToStore = DetailType.LINKEDIN.getIndex(); + break; case TELEGRAM_FLAG: indexToStore = DetailType.TELEGRAM.getIndex(); break; @@ -30,9 +33,6 @@ default int getIndexToStore(String flag) throws InvalidFlagException { case EMAIL_FLAG: indexToStore = DetailType.EMAIL.getIndex(); break; - case LINKEDIN_FLAG: - indexToStore = DetailType.LINKEDIN.getIndex(); - break; default: throw new InvalidFlagException(); } From ae4308311dd8384b5fa4047cfef617576cb5b11f Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 19 Oct 2021 14:34:58 +0800 Subject: [PATCH 324/756] Add search parser for MainParser --- src/main/java/seedu/parser/MainParser.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index d785417c4f..0659681a8d 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -43,6 +43,7 @@ public class MainParser { private ContactParser contactParser; private final AddContactParser addContactParser = new AddContactParser(); private final EditContactParser editContactParser = new EditContactParser(); + private final SearchContactParser searchContactParser = new SearchContactParser(); public Command parseCommand(String userInput) { String commandType = getCommandWord(userInput); @@ -183,5 +184,14 @@ private Command parseDeleteContact(String userInput) { //@@author ng-andre private Command parseSearchCommand(String userInput) { + try { + String query = searchContactParser.parseSearchQuery(userInput); + int detailFlag = searchContactParser.getDetailFlag(userInput); + return new SearchContactCommand(query, detailFlag); + } catch (MissingArgException e) { + return new FailedCommand(FailedCommandType.MISSING_ARG); + } catch (InvalidFlagException e) { + return new FailedCommand(FailedCommandType.INVALID_FLAG); + } } } From 8263d50dd0551b0162a8c04745357de4caf94a1c Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 19 Oct 2021 14:35:21 +0800 Subject: [PATCH 325/756] Update SearchContactParser to implement ContactDetails --- .../java/seedu/parser/SearchContactParser.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/parser/SearchContactParser.java b/src/main/java/seedu/parser/SearchContactParser.java index d4e69c781d..fd18c3363f 100644 --- a/src/main/java/seedu/parser/SearchContactParser.java +++ b/src/main/java/seedu/parser/SearchContactParser.java @@ -1,18 +1,18 @@ package seedu.parser; +import seedu.contact.DetailType; import seedu.exception.InvalidFlagException; import seedu.exception.MissingArgException; import static seedu.parser.ContactParser.NUMBER_OF_SEARCH_ARGS; -import static seedu.parser.ContactParser.getIndexToStore; -public class SearchContactParser { +public class SearchContactParser implements ContactDetails { //return only search query as a String public String parseSearchQuery(String userInput) throws MissingArgException { String[] destructuredInputs = userInput.split(" ", NUMBER_OF_SEARCH_ARGS); if (destructuredInputs.length == 2) { //search for name if no flag specified return destructuredInputs[1].toLowerCase().trim(); - } else if (destructuredInputs.length == 3) { //search for name with flag + } else if (destructuredInputs.length == NUMBER_OF_SEARCH_ARGS) { //search for name with flag return destructuredInputs[2].toLowerCase().trim(); } //no query specified @@ -26,10 +26,14 @@ public int getDetailFlag(String userInput) throws MissingArgException, InvalidFl if (destructuredInputs.length < 2) { //no arguments specified, only "search" throw new MissingArgException(); } else if (destructuredInputs.length == 2) { //no flag specified - return -1; + return DetailType.NAME.getIndex(); //search names } else { assert destructuredInputs.length == 3; - return getIndexToStore(destructuredInputs[2]); + if (destructuredInputs[1].contains("-")) { //check for flag + String flag = destructuredInputs[1].trim().substring(1); + return getIndexToStore(flag); + } + throw new InvalidFlagException(); } } } From aa97e134ae61dbd5bce765200aedf9ae796426de Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 19 Oct 2021 16:07:59 +0800 Subject: [PATCH 326/756] Update TextUI for search --- src/main/java/seedu/ui/TextUi.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index be0ffea474..817cc181cb 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -156,6 +156,11 @@ public static void contactsEmptyListMessage() { printDoubleLineMessage(message); } + public static void searchNoResultsFoundMessage() { + String message = "No search results found."; + printDoubleLineMessage(message); + } + public static void confirmDeleteMessage(Contact deletedContact, int deletedIndex) { String message = "Delete this contact? (y/n)\n" + deletedIndex + ". " + deletedContact.getName() + formatContactFields(deletedContact); @@ -197,6 +202,10 @@ public static void helpMessage() { + " Parameter: INDEX\n" + " Note: Index starts from 0.\n" + " Example: rm 0\n\n" + + "search: Search for a contact containing a specified query.\n" + + " Note: Flags may be used to specify a detail type to search.\n" + + " If no flag is specified, contact name is searched by default.\n" + + " Example: search -g QUERY\n\n" + "help: Displays application usage instructions.\n" + " Example: help"; printDoubleLineMessage(message); From 2436e9c5dbefb32b64ec4bb5ff5dad1fa7acfe6e Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 19 Oct 2021 16:08:28 +0800 Subject: [PATCH 327/756] Trim inputs for SearchContactParser --- src/main/java/seedu/parser/SearchContactParser.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/parser/SearchContactParser.java b/src/main/java/seedu/parser/SearchContactParser.java index fd18c3363f..3085c028fd 100644 --- a/src/main/java/seedu/parser/SearchContactParser.java +++ b/src/main/java/seedu/parser/SearchContactParser.java @@ -9,7 +9,7 @@ public class SearchContactParser implements ContactDetails { //return only search query as a String public String parseSearchQuery(String userInput) throws MissingArgException { - String[] destructuredInputs = userInput.split(" ", NUMBER_OF_SEARCH_ARGS); + String[] destructuredInputs = userInput.trim().split(" ", NUMBER_OF_SEARCH_ARGS); if (destructuredInputs.length == 2) { //search for name if no flag specified return destructuredInputs[1].toLowerCase().trim(); } else if (destructuredInputs.length == NUMBER_OF_SEARCH_ARGS) { //search for name with flag @@ -21,7 +21,7 @@ public String parseSearchQuery(String userInput) throws MissingArgException { } public int getDetailFlag(String userInput) throws MissingArgException, InvalidFlagException { - String[] destructuredInputs = userInput.split(" ", NUMBER_OF_SEARCH_ARGS); + String[] destructuredInputs = userInput.trim().split(" ", NUMBER_OF_SEARCH_ARGS); //"search " with one or two spaces should not have an issue since the input is trimmed if (destructuredInputs.length < 2) { //no arguments specified, only "search" throw new MissingArgException(); From 31b4347c33b5e924a12eff882902bf39eed5e96f Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 19 Oct 2021 16:26:13 +0800 Subject: [PATCH 328/756] Add output for no search results --- src/main/java/seedu/contact/ContactList.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/seedu/contact/ContactList.java b/src/main/java/seedu/contact/ContactList.java index d08c57f30c..0f0e890e02 100644 --- a/src/main/java/seedu/contact/ContactList.java +++ b/src/main/java/seedu/contact/ContactList.java @@ -63,37 +63,44 @@ public void deleteContact(int deletedIndex) { //@@author ng-andre public void searchContact(String query, int detailType) throws InvalidFlagException { + boolean searchResult = false; for (int i = 0; i < contacts.size(); i++) { Contact contact = getContactAtIndex(i); switch (detailType) { case NAME_INDEX: if (contact.getName().toLowerCase().contains(query)) { TextUi.viewContactMessage(contact, i); + searchResult = true; } break; case GITHUB_INDEX: if (contact.getGithub().toLowerCase().contains(query)) { TextUi.viewContactMessage(contact, i); + searchResult = true; } break; case LINKEDIN_INDEX: if (contact.getLinkedin().toLowerCase().contains(query)) { TextUi.viewContactMessage(contact, i); + searchResult = true; } break; case TELEGRAM_INDEX: if (contact.getTelegram().toLowerCase().contains(query)) { TextUi.viewContactMessage(contact, i); + searchResult = true; } break; case TWITTER_INDEX: if (contact.getTwitter().toLowerCase().contains(query)) { TextUi.viewContactMessage(contact, i); + searchResult = true; } break; case EMAIL_INDEX: if (contact.getEmail().toLowerCase().contains(query)) { TextUi.viewContactMessage(contact, i); + searchResult = true; } break; default: @@ -102,6 +109,9 @@ public void searchContact(String query, int detailType) throws InvalidFlagExcept throw new InvalidFlagException(); } } + if (!searchResult) { + TextUi.searchNoResultsFoundMessage(); + } } public int getIndexOfContact(Contact contact) { From 233e6830b4bbd37114e18aaa9692c5238588dc8c Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 19 Oct 2021 16:31:23 +0800 Subject: [PATCH 329/756] Handle exception for missing parameter --- src/main/java/seedu/parser/SearchContactParser.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/seedu/parser/SearchContactParser.java b/src/main/java/seedu/parser/SearchContactParser.java index 3085c028fd..04930c06b6 100644 --- a/src/main/java/seedu/parser/SearchContactParser.java +++ b/src/main/java/seedu/parser/SearchContactParser.java @@ -11,6 +11,9 @@ public class SearchContactParser implements ContactDetails { public String parseSearchQuery(String userInput) throws MissingArgException { String[] destructuredInputs = userInput.trim().split(" ", NUMBER_OF_SEARCH_ARGS); if (destructuredInputs.length == 2) { //search for name if no flag specified + if (destructuredInputs[1].trim().charAt(0) == '-') { //if only flag is specified + throw new MissingArgException(); + } return destructuredInputs[1].toLowerCase().trim(); } else if (destructuredInputs.length == NUMBER_OF_SEARCH_ARGS) { //search for name with flag return destructuredInputs[2].toLowerCase().trim(); From 3a2b33346794fe817c65fb9884daa71b6e11e5e2 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Tue, 19 Oct 2021 18:37:55 +0800 Subject: [PATCH 330/756] Simplify ViewMessageFormatterUi with improvements to decoder --- .../java/seedu/ui/ViewMessageFormatterUi.java | 60 ++++--------------- 1 file changed, 12 insertions(+), 48 deletions(-) diff --git a/src/main/java/seedu/ui/ViewMessageFormatterUi.java b/src/main/java/seedu/ui/ViewMessageFormatterUi.java index cc09859f90..0d52294276 100644 --- a/src/main/java/seedu/ui/ViewMessageFormatterUi.java +++ b/src/main/java/seedu/ui/ViewMessageFormatterUi.java @@ -4,81 +4,45 @@ public class ViewMessageFormatterUi { public static String viewNameFormatter(Contact contact) { - try { - if (contact.getName() == null | contact.getName().equals("null")) { - return ""; - } else { - assert (!contact.getName().equals("null")); - return contact.getName(); - } - } catch (NullPointerException e) { + if (contact.getName() == null) { return ""; } + return contact.getName(); } public static String viewGithubFormatter(Contact contact) { - try { - if (contact.getGithub() == null | contact.getGithub().equals("null")) { - return ""; - } else { - assert (!contact.getGithub().equals("null")); - return "\nGithub: github.com/" + contact.getGithub(); - } - } catch (NullPointerException e) { + if (contact.getGithub() == null) { return ""; } + return "\nGithub: github.com/" + contact.getGithub(); } public static String viewEmailFormatter(Contact contact) { - try { - if (contact.getEmail() == null | contact.getEmail().equals("null")) { - return ""; - } else { - assert (!contact.getEmail().equals("null")); - return "\nEmail: " + contact.getEmail(); - } - } catch (NullPointerException e) { + if (contact.getEmail() == null) { return ""; } + return "\nEmail: " + contact.getEmail(); } public static String viewTelegramFormatter(Contact contact) { - try { - if (contact.getTelegram() == null | contact.getTelegram().equals("null")) { - return ""; - } else { - assert (!contact.getTelegram().equals("null")); - return "\nTelegram: t.me/" + contact.getTelegram(); - } - } catch (NullPointerException e) { + if (contact.getTelegram() == null) { return ""; } + return "\nTelegram: t.me/" + contact.getTelegram(); } public static String viewLinkedinFormatter(Contact contact) { - try { - if (contact.getLinkedin() == null | contact.getLinkedin().equals("null")) { - return ""; - } else { - assert (!contact.getLinkedin().equals("null")); - return "\nLinkedIn: linkedin.com/in/" + contact.getLinkedin(); - } - } catch (NullPointerException e) { + if (contact.getLinkedin() == null) { return ""; } + return "\nLinkedIn: linkedin.com/in/" + contact.getLinkedin(); } public static String viewTwitterFormatter(Contact contact) { - try { - if (contact.getTwitter() == null | contact.getTwitter().equals("null")) { - return ""; - } else { - assert (!contact.getTwitter().equals("null")); - return "\nTwitter: twitter.com/" + contact.getTwitter(); - } - } catch (NullPointerException e) { + if (contact.getTwitter() == null) { return ""; } + return "\nTwitter: twitter.com/" + contact.getTwitter(); } } From 474d5ae17194a084c6cb3a98b0f272805284a184 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Tue, 19 Oct 2021 18:38:25 +0800 Subject: [PATCH 331/756] Implement detail decoder to check for "null" strings in save data --- src/main/java/seedu/storage/ContactsDecoder.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index 2b819ee4d5..b31f949829 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -80,4 +80,18 @@ private static void decodeContact(ContactList contactList, String contactText) { ExceptionTextUi.corruptLineMessage(contactText); } } + + private static String[] decodeDetails(String contactText) throws IndexOutOfBoundsException { + String[] destructuredInputs = contactText.split(SEPARATOR); + String[] compiledDetails = new String[NUMBER_OF_FIELDS]; + for (int i = 0; i < NUMBER_OF_FIELDS; i++) { + if (destructuredInputs[i].equals("null")) { + compiledDetails[i] = null; + } else { + compiledDetails[i] = destructuredInputs[i]; + } + } + assert destructuredInputs.length == compiledDetails.length; + return compiledDetails; + } } From 2bebc138c17285c90c4ecdde209d86553adbe472 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Tue, 19 Oct 2021 18:38:49 +0800 Subject: [PATCH 332/756] Implement improved decoder to save null objects if detail is missing --- src/main/java/seedu/storage/ContactsDecoder.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index b31f949829..a10ccd5f74 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -7,6 +7,7 @@ import seedu.ui.ExceptionTextUi; import static seedu.storage.Storage.SEPARATOR; +import static seedu.parser.ContactParser.NUMBER_OF_FIELDS; import java.io.File; import java.io.FileNotFoundException; @@ -64,15 +65,15 @@ private static Contact decodePersonalContact(String contactText, Contact contact } private static void decodeContact(ContactList contactList, String contactText) { - String[] destructuredInputs = contactText.split(SEPARATOR); // Add the decoded details into the contact list try { - String contactName = destructuredInputs[DetailType.NAME.getIndex()]; - String contactGithub = destructuredInputs[DetailType.GITHUB.getIndex()]; - String contactLinkedin = destructuredInputs[DetailType.LINKEDIN.getIndex()]; - String contactTelegram = destructuredInputs[DetailType.TELEGRAM.getIndex()]; - String contactTwitter = destructuredInputs[DetailType.TWITTER.getIndex()]; - String contactEmail = destructuredInputs[DetailType.EMAIL.getIndex()]; + String[] compiledDetails = decodeDetails(contactText); + String contactName = compiledDetails[DetailType.NAME.getIndex()]; + String contactGithub = compiledDetails[DetailType.GITHUB.getIndex()]; + String contactLinkedin = compiledDetails[DetailType.LINKEDIN.getIndex()]; + String contactTelegram = compiledDetails[DetailType.TELEGRAM.getIndex()]; + String contactTwitter = compiledDetails[DetailType.TWITTER.getIndex()]; + String contactEmail = compiledDetails[DetailType.EMAIL.getIndex()]; Contact newContact = new Contact(contactName, contactGithub, contactLinkedin, contactTelegram, contactTwitter, contactEmail); contactList.addContact(newContact); From f47206373d08fa712969704a8deaf45ac7c5b978 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 19 Oct 2021 19:31:56 +0800 Subject: [PATCH 333/756] Update Search method to handle null fields --- src/main/java/seedu/contact/ContactList.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/seedu/contact/ContactList.java b/src/main/java/seedu/contact/ContactList.java index 0f0e890e02..9a1a0496cf 100644 --- a/src/main/java/seedu/contact/ContactList.java +++ b/src/main/java/seedu/contact/ContactList.java @@ -68,37 +68,37 @@ public void searchContact(String query, int detailType) throws InvalidFlagExcept Contact contact = getContactAtIndex(i); switch (detailType) { case NAME_INDEX: - if (contact.getName().toLowerCase().contains(query)) { + if (contact.getName() != null && contact.getName().toLowerCase().contains(query)) { TextUi.viewContactMessage(contact, i); searchResult = true; } break; case GITHUB_INDEX: - if (contact.getGithub().toLowerCase().contains(query)) { + if (contact.getGithub() != null && contact.getGithub().toLowerCase().contains(query)) { TextUi.viewContactMessage(contact, i); searchResult = true; } break; case LINKEDIN_INDEX: - if (contact.getLinkedin().toLowerCase().contains(query)) { + if (contact.getLinkedin() != null && contact.getLinkedin().toLowerCase().contains(query)) { TextUi.viewContactMessage(contact, i); searchResult = true; } break; case TELEGRAM_INDEX: - if (contact.getTelegram().toLowerCase().contains(query)) { + if (contact.getTelegram() != null && contact.getTelegram().toLowerCase().contains(query)) { TextUi.viewContactMessage(contact, i); searchResult = true; } break; case TWITTER_INDEX: - if (contact.getTwitter().toLowerCase().contains(query)) { + if (contact.getTwitter() != null && contact.getTwitter().toLowerCase().contains(query)) { TextUi.viewContactMessage(contact, i); searchResult = true; } break; case EMAIL_INDEX: - if (contact.getEmail().toLowerCase().contains(query)) { + if (contact.getEmail() != null && contact.getEmail().toLowerCase().contains(query)) { TextUi.viewContactMessage(contact, i); searchResult = true; } From 2d978aa736592a6365944be02f250d1929b841a5 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 19 Oct 2021 19:32:11 +0800 Subject: [PATCH 334/756] Update TextUI tests --- text-ui-test/ACTUAL.TXT | 40 ++++++++++++++++++++++++++++++++++ text-ui-test/EXPECTED-UNIX.TXT | 40 ++++++++++++++++++++++++++++++++++ text-ui-test/EXPECTED.TXT | 40 ++++++++++++++++++++++++++++++++++ text-ui-test/input.txt | 7 ++++++ 4 files changed, 127 insertions(+) diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index eb423ac716..fba8194a58 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -505,6 +505,46 @@ Telegram: t.me/testTelegram You now have 10 contact(s). ____________________________________________________________ +____________________________________________________________ +There seems to be missing parameters in your request. +Please specify your command. +____________________________________________________________ + +____________________________________________________________ +There seems to be missing parameters in your request. +Please specify your command. +____________________________________________________________ + +____________________________________________________________ +There seems to be missing parameters in your request. +Please specify your command. +____________________________________________________________ + +____________________________________________________________ +No search results found. +____________________________________________________________ + +____________________________________________________________ +2. bory +Github: github.com/marcus +____________________________________________________________ + +____________________________________________________________ +6. lezongmun +Github: github.com/lezong +____________________________________________________________ + +____________________________________________________________ +There appears to be a flag that is not recognised. +Please try again with a valid flag. + -n NAME + -g GITHUB + -l LINKEDIN + -te TELEGRAM + -tw TWITTER + -e EMAIL +____________________________________________________________ + ____________________________________________________________ ConTech will now shutdown. We hope you have enjoyed using it. diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index eb423ac716..fba8194a58 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -505,6 +505,46 @@ Telegram: t.me/testTelegram You now have 10 contact(s). ____________________________________________________________ +____________________________________________________________ +There seems to be missing parameters in your request. +Please specify your command. +____________________________________________________________ + +____________________________________________________________ +There seems to be missing parameters in your request. +Please specify your command. +____________________________________________________________ + +____________________________________________________________ +There seems to be missing parameters in your request. +Please specify your command. +____________________________________________________________ + +____________________________________________________________ +No search results found. +____________________________________________________________ + +____________________________________________________________ +2. bory +Github: github.com/marcus +____________________________________________________________ + +____________________________________________________________ +6. lezongmun +Github: github.com/lezong +____________________________________________________________ + +____________________________________________________________ +There appears to be a flag that is not recognised. +Please try again with a valid flag. + -n NAME + -g GITHUB + -l LINKEDIN + -te TELEGRAM + -tw TWITTER + -e EMAIL +____________________________________________________________ + ____________________________________________________________ ConTech will now shutdown. We hope you have enjoyed using it. diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index eb423ac716..fba8194a58 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -505,6 +505,46 @@ Telegram: t.me/testTelegram You now have 10 contact(s). ____________________________________________________________ +____________________________________________________________ +There seems to be missing parameters in your request. +Please specify your command. +____________________________________________________________ + +____________________________________________________________ +There seems to be missing parameters in your request. +Please specify your command. +____________________________________________________________ + +____________________________________________________________ +There seems to be missing parameters in your request. +Please specify your command. +____________________________________________________________ + +____________________________________________________________ +No search results found. +____________________________________________________________ + +____________________________________________________________ +2. bory +Github: github.com/marcus +____________________________________________________________ + +____________________________________________________________ +6. lezongmun +Github: github.com/lezong +____________________________________________________________ + +____________________________________________________________ +There appears to be a flag that is not recognised. +Please try again with a valid flag. + -n NAME + -g GITHUB + -l LINKEDIN + -te TELEGRAM + -tw TWITTER + -e EMAIL +____________________________________________________________ + ____________________________________________________________ ConTech will now shutdown. We hope you have enjoyed using it. diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index d7b616c228..e2795e4175 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -64,4 +64,11 @@ add -n asdasd -l kusdd__ -g adasdas -e .adadas@com add -n lezai -g lezongmun -e lezongmun@gmail.com -linkedin lezongmun add -n lezai3 -g lezongmun -e lezongmun@gmail.com -l lezongmun add -n lezongggg -te testTelegram +search +search +search -g +search boris +search -n bory +search -g lezong +search -zxca lezong exit \ No newline at end of file From 24c91e958b1d6be95424eb34a3b4923eb613f11f Mon Sep 17 00:00:00 2001 From: lezong Date: Wed, 20 Oct 2021 01:28:03 +0800 Subject: [PATCH 335/756] Developer guide for Storage and DeleteContactCommand --- docs/DeveloperGuide.md | 13 +++++ docs/diagrams/DeleteContactCommand.puml | 49 ++++++++++++++++++ docs/diagrams/StorageClassDiagram.puml | 38 ++++++++++++++ docs/images/StorageClassDiagram.png | Bin 0 -> 10045 bytes .../seedu/command/DeleteContactCommand.java | 10 ++-- .../java/seedu/storage/ContactsDecoder.java | 3 -- 6 files changed, 106 insertions(+), 7 deletions(-) create mode 100644 docs/diagrams/DeleteContactCommand.puml create mode 100644 docs/diagrams/StorageClassDiagram.puml create mode 100644 docs/images/StorageClassDiagram.png diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index b504dfaa70..936d9232ce 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -60,6 +60,15 @@ The five main components interact with each other, as shown in the sequence diag ### Command ### ContactList ### Storage +**API** :`Storage.java` + +![Storage Class Diagram](images/StorageClassDiagram.png) + +The `Storage` component is responsible for saving both contacts data and personal contact data locally inside the file +paths, `data/contacts.txt` and `data/me.txt`. `Storage` is also responsible for loading these data back into their +corresponding `ContactList` and `Contact` objects. It is thus dependent on the classes, `ContactList` and +`Contact`. + ## Implementation @@ -67,6 +76,10 @@ The five main components interact with each other, as shown in the sequence diag {NOT DONE} +### Deleting a contact: `rm` + + + ## Product scope ### Target user profile - Has a need to store a significant amount of computing-related contacts diff --git a/docs/diagrams/DeleteContactCommand.puml b/docs/diagrams/DeleteContactCommand.puml new file mode 100644 index 0000000000..d9637c1118 --- /dev/null +++ b/docs/diagrams/DeleteContactCommand.puml @@ -0,0 +1,49 @@ +@startuml +hide footbox +'https://plantuml.com/sequence-diagram +-> ":DeleteContactCommand": execute() +activate ":DeleteContactCommand" + +":DeleteContactCommand" -> ":IndexParser" :getContactFromIndex(contactIndex:int, contactList: ContactList) +activate ":IndexParser" +":IndexParser" --> ":DeleteContactCommand" :deletedContact:Contact +deactivate ":IndexParser" + +":DeleteContactCommand" -> ":DeleteContactCommand":deleteOnConfirmation(deletedContact:Contact) +activate ":DeleteContactCommand" +":DeleteContactCommand" -> ":TextUi":ConfirmDeleteMessage(deletedContact:Contact, contactIndex:int) +activate ":TextUi" +deactivate ":TextUi" + +":DeleteContactCommand" -> ":UserInputTextUi":getUserConfirmation() +activate ":UserInputTextUi" +":UserInputTextUi" --> ":DeleteContactCommand" :userConfirmation:String +deactivate ":UserInputTextUi" + +alt#gold #lightgreen userConfirmation.equalsIgnoreCase("y") + ":DeleteContactCommand" -> ":ContactList": deleteContact(contactIndex:int) + activate ":ContactList" + deactivate ":ContactList" + ":DeleteContactCommand" -> ":Contact" :getName() + activate ":Contact" + ":Contact" --> ":DeleteContactCommand":deletedName:String + deactivate ":Contact" + + ":DeleteContactCommand" -> ":ContactList":getListSize() + activate ":ContactList" + ":ContactList" --> ":DeleteContactCommand" :contactListSize:int + deactivate ":ContactList" + + ":DeleteContactCommand" -> ":TextUi":deleteContactMessage(deletedName:String, contactListSize:int) + activate ":TextUi" + deactivate ":TextUi" + +else #lightblue else + ":DeleteContactCommand" -> ":TextUi":cancelDeleteContactMessage() + activate ":TextUi" + deactivate ":TextUi" +end +deactivate ":DeleteContactCommand" +deactivate ":DeleteContactCommand" + +@enduml \ No newline at end of file diff --git a/docs/diagrams/StorageClassDiagram.puml b/docs/diagrams/StorageClassDiagram.puml new file mode 100644 index 0000000000..93da57fe51 --- /dev/null +++ b/docs/diagrams/StorageClassDiagram.puml @@ -0,0 +1,38 @@ +@startuml +'https://plantuml.com/class-diagram + + +'List <|-- AbstractList +'Collection <|-- AbstractCollection +' +'Collection <|- List +'AbstractCollection <. AbstractList +'AbstractList <|-- ArrayList +Storage .left.> ContactsDecoder +Storage .right.> ContactsEncoder +'Storage -up->"contactFile 0..1"File +'Storage -up->"personalContactFile 0..1"File +ContactsEncoder ..> Storage + +'class File { +'} + +class Storage { +-File contactFile +-File personalContactFile +'-hasExistingPersonalContactFile() : boolean +'-hasEmptyExistingPersonalContactFile() : boolean +'-hasExistingContactFile() : boolean ++loadExistingContact() : ContactList ++loadExistingPersonalContact() : Contact +} + +class ContactsEncoder { +} + +class ContactsDecoder { +} + + + +@enduml \ No newline at end of file diff --git a/docs/images/StorageClassDiagram.png b/docs/images/StorageClassDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..1573729beeb78d7a74d19d0d52c2f9ade9f017d2 GIT binary patch literal 10045 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 literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/command/DeleteContactCommand.java b/src/main/java/seedu/command/DeleteContactCommand.java index a34227015f..6f775173e7 100644 --- a/src/main/java/seedu/command/DeleteContactCommand.java +++ b/src/main/java/seedu/command/DeleteContactCommand.java @@ -21,12 +21,14 @@ public int getDeletedIndex() { private void deleteOnConfirmation(Contact deletedContact) { // ask for confirmation to delete from user TextUi.confirmDeleteMessage(deletedContact, contactIndex); - String userDeleteConfirmation = UserInputTextUi.getUserConfirmation(); - if (userDeleteConfirmation.equalsIgnoreCase("y")) { + String userConfirmation = UserInputTextUi.getUserConfirmation(); + if (userConfirmation.equalsIgnoreCase("y")) { this.contactList.deleteContact(contactIndex); - TextUi.deleteContactMessage(deletedContact.getName(), contactList.getListSize()); + String deletedName = deletedContact.getName(); + int contactListSize = contactList.getListSize(); + TextUi.deleteContactMessage(deletedName, contactListSize); } else { - assert !userDeleteConfirmation.equalsIgnoreCase("y"); + assert !userConfirmation.equalsIgnoreCase("y"); TextUi.cancelDeleteContactMessage(); } } diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index 2b819ee4d5..ac0ccab5b9 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -41,9 +41,6 @@ public static Contact readPersonalContact(File personalContactFile) throws FileE return personalContact; } - public void getPersonalContactDetails() { - - } private static Contact decodePersonalContact(String contactText, Contact contact) { String[] destructuredInputs = contactText.split(SEPARATOR); From 61af032dc4bd946aeb699ff207e637f07799c160 Mon Sep 17 00:00:00 2001 From: lezong Date: Wed, 20 Oct 2021 01:52:54 +0800 Subject: [PATCH 336/756] changes to DG --- docs/DeveloperGuide.md | 8 ++++++++ .../DeleteContactCommandSequenceDiagram.png | Bin 0 -> 42335 bytes 2 files changed, 8 insertions(+) create mode 100644 docs/images/DeleteContactCommandSequenceDiagram.png diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 936d9232ce..62f78f97ae 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -77,6 +77,14 @@ corresponding `ContactList` and `Contact` objects. It is thus dependent on the c {NOT DONE} ### Deleting a contact: `rm` +This feature is processed using the `DeleteContactCommand`. Whenever the user wants to remove a contact from the contact +list using the `rm` command, `DeleteContactCommand` is created in the `MainParser` and executed in`Duke`. The sequence +diagram below shows how the `execute()` function of `DeleteContactCommand` works. + + +![Delete Sequence Diagram](images/DeleteContactCommandSequenceDiagram.png) + + diff --git a/docs/images/DeleteContactCommandSequenceDiagram.png b/docs/images/DeleteContactCommandSequenceDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..981f3510e9a19b9a4d7ad1c39f5df931eb79b5a8 GIT binary patch literal 42335 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%0A+B=ItvQ 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%0ALjya zh*Dv|DioyHt@fs2U#cy)jb#O6s`h;1_oe zy8G;JzyEhY1q1zsK>^UhYh~nHsSU55)v(mh_}PEAWivL-J?X+)Ih(a+!@k|erWBxF ze`6wua#cAbp~HZcz*{)BBPLVTFl4A43ayx6*KNefDh6+sFW6aL>w5u!lEWs3`J`ai zH(XDzo#bA5!PpK1zZVyr(z7syjAC)p2_|IvXfg(JlN-P%uhVJ7mHSPhd;Q=$Wbt`< z8;lFfngv_pV5dvSKw%aPHUy&pcl3OQJw>tiG?!iMXR0k*?rLSCSAnmm zW=@p?)gW+%3i;ur^6lmIlU6wF;m%oAyt>@`tIt+3jvzgIn|1k)Q6n8fm z1&Zg5yOqoM>h_v#Hef{;DRh4Yd~BWWIn}!z_b;XX}go^^%8|gR(Ur@wkpns)6^<>-!8`<=kt94i9J|5M=rSL~=7L@bhZnQu` z)Cx>g!FF+A(;EjNU`V{A+pR*IpA8^^m2$BvVuTYx;U;WY9rEWju$+W$91J7i>UOPj zK%IHnlaam)e8%0`Hx>q0dt1?*W~1P9HRTIPqa04CO%YZ?#+My?{<&d&#bOJvg{L9- z=q}jovnx$`3w%|| Date: Wed, 20 Oct 2021 02:06:30 +0800 Subject: [PATCH 337/756] minor changes to text-ui-test --- text-ui-test/ACTUAL.TXT | 12 ++++++------ text-ui-test/EXPECTED-UNIX.TXT | 12 ++++++------ text-ui-test/EXPECTED.TXT | 12 ++++++------ 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index fba8194a58..d00244fb5d 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -23,7 +23,7 @@ Welcome to ConTech, your personal contact tracker. Can I get your name? ____________________________________________________________ -Name:____________________________________________________________ +Name: ____________________________________________________________ Hello there, Le Zong. This is ConTech, your very own contact tracking application @@ -41,7 +41,7 @@ Please provide us with your Github Username or press ENTER if you would like to skip. ____________________________________________________________ -GitHub Username:____________________________________________________________ +GitHub Username: ____________________________________________________________ Please provide us with your Telegram Handle or press ENTER if you would like to skip. ____________________________________________________________ @@ -51,12 +51,12 @@ Please provide us with your Twitter Username or press ENTER if you would like to skip. ____________________________________________________________ -Twitter Username:____________________________________________________________ +Twitter Username: ____________________________________________________________ Please provide us with your Email Address or press ENTER if you would like to skip. ____________________________________________________________ -Email Address:____________________________________________________________ +Email Address: ____________________________________________________________ The email id is not correctly formatted, Rules for email id : * Lowercase letters only @@ -67,12 +67,12 @@ Please enter your email again or press ENTER to skip. ____________________________________________________________ -Email Address:____________________________________________________________ +Email Address: ____________________________________________________________ Please provide us with your LinkedIn Username or press ENTER if you would like to skip. ____________________________________________________________ -LinkedIn Username:____________________________________________________________ +LinkedIn Username: ____________________________________________________________ You have successfully set up your own personal contact. Don't worry, you can always edit your personal details later on. diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index fba8194a58..d00244fb5d 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -23,7 +23,7 @@ Welcome to ConTech, your personal contact tracker. Can I get your name? ____________________________________________________________ -Name:____________________________________________________________ +Name: ____________________________________________________________ Hello there, Le Zong. This is ConTech, your very own contact tracking application @@ -41,7 +41,7 @@ Please provide us with your Github Username or press ENTER if you would like to skip. ____________________________________________________________ -GitHub Username:____________________________________________________________ +GitHub Username: ____________________________________________________________ Please provide us with your Telegram Handle or press ENTER if you would like to skip. ____________________________________________________________ @@ -51,12 +51,12 @@ Please provide us with your Twitter Username or press ENTER if you would like to skip. ____________________________________________________________ -Twitter Username:____________________________________________________________ +Twitter Username: ____________________________________________________________ Please provide us with your Email Address or press ENTER if you would like to skip. ____________________________________________________________ -Email Address:____________________________________________________________ +Email Address: ____________________________________________________________ The email id is not correctly formatted, Rules for email id : * Lowercase letters only @@ -67,12 +67,12 @@ Please enter your email again or press ENTER to skip. ____________________________________________________________ -Email Address:____________________________________________________________ +Email Address: ____________________________________________________________ Please provide us with your LinkedIn Username or press ENTER if you would like to skip. ____________________________________________________________ -LinkedIn Username:____________________________________________________________ +LinkedIn Username: ____________________________________________________________ You have successfully set up your own personal contact. Don't worry, you can always edit your personal details later on. diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index fba8194a58..d00244fb5d 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -23,7 +23,7 @@ Welcome to ConTech, your personal contact tracker. Can I get your name? ____________________________________________________________ -Name:____________________________________________________________ +Name: ____________________________________________________________ Hello there, Le Zong. This is ConTech, your very own contact tracking application @@ -41,7 +41,7 @@ Please provide us with your Github Username or press ENTER if you would like to skip. ____________________________________________________________ -GitHub Username:____________________________________________________________ +GitHub Username: ____________________________________________________________ Please provide us with your Telegram Handle or press ENTER if you would like to skip. ____________________________________________________________ @@ -51,12 +51,12 @@ Please provide us with your Twitter Username or press ENTER if you would like to skip. ____________________________________________________________ -Twitter Username:____________________________________________________________ +Twitter Username: ____________________________________________________________ Please provide us with your Email Address or press ENTER if you would like to skip. ____________________________________________________________ -Email Address:____________________________________________________________ +Email Address: ____________________________________________________________ The email id is not correctly formatted, Rules for email id : * Lowercase letters only @@ -67,12 +67,12 @@ Please enter your email again or press ENTER to skip. ____________________________________________________________ -Email Address:____________________________________________________________ +Email Address: ____________________________________________________________ Please provide us with your LinkedIn Username or press ENTER if you would like to skip. ____________________________________________________________ -LinkedIn Username:____________________________________________________________ +LinkedIn Username: ____________________________________________________________ You have successfully set up your own personal contact. Don't worry, you can always edit your personal details later on. From 2fdebd3f04da2966d4cff87b198b1d504a6c606d Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Wed, 20 Oct 2021 13:00:08 +0800 Subject: [PATCH 338/756] Add sequence diagram for Edit Contact --- docs/diagrams/EditContactCommand.puml | 40 +++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 docs/diagrams/EditContactCommand.puml diff --git a/docs/diagrams/EditContactCommand.puml b/docs/diagrams/EditContactCommand.puml new file mode 100644 index 0000000000..3fe47523b2 --- /dev/null +++ b/docs/diagrams/EditContactCommand.puml @@ -0,0 +1,40 @@ +@startuml +hide footbox +'https://plantuml.com/sequence-diagram + +-> ":MainParser": execute() +activate ":MainParser" + +":MainParser" -> ":MainParser" :getCommandWord(userInput:String) +":MainParser" -> ":EditContactParser" :EditContactParser(userInput:String) +activate ":EditContactParser" + +":EditContactParser" -> ":EditContactParser" :parseContactDetails(userInput:String) + +":EditContactParser" -> ":IndexParser" :getIndexFromInput(userInput:String) +activate ":IndexParser" +":IndexParser" --> ":EditContactParser" :userIndex:int +deactivate ":IndexParser" + +":EditContactParser" -> ":EditContactCommand" : execute(contactDetails:String[], contactIndex:int) +activate ":EditContactCommand" + +":EditContactCommand" -> ":ContactList" : editContact(contactDetails:String[], contactIndex:int) +activate ":ContactList" + +loop until all contactDetails have been updated +alt#gold #lightgreen NAME_INDEX + ":ContactList" -> ":ContactList" : setName(contactDetails(i)) + else GITHUB_INDEX + ":ContactList" -> ":ContactList" : setGithub(contactDetails(i)) + else LINKEDIN_INDEX + ":ContactList" -> ":ContactList" : setLinkedin(contactDetails(i)) + else TELEGRAM_INDEX + ":ContactList" -> ":ContactList" : setTelegram(contactDetails(i)) + else TWITTER_INDEX + ":ContactList" -> ":ContactList" : setTwitter(contactDetails(i)) + else EMAIL_INDEX + ":ContactList" -> ":ContactList" : setEmail(contactDetails(i)) +end +end +@enduml \ No newline at end of file From 658f307392612c745f8d17d9a54f87950c1cb02d Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Wed, 20 Oct 2021 13:00:14 +0800 Subject: [PATCH 339/756] Add sequence diagram for Search Contact --- docs/diagrams/SearchContactCommand.puml | 64 +++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 docs/diagrams/SearchContactCommand.puml diff --git a/docs/diagrams/SearchContactCommand.puml b/docs/diagrams/SearchContactCommand.puml new file mode 100644 index 0000000000..ae8bb160ca --- /dev/null +++ b/docs/diagrams/SearchContactCommand.puml @@ -0,0 +1,64 @@ +@startuml +hide footbox +'https://plantuml.com/sequence-diagram + +-> ":MainParser": execute() +activate ":MainParser" + +":MainParser" -> ":MainParser" :getCommandWord(userInput:String) +":MainParser" -> ":SearchContactParser" :parseSearchQuery(userInput:String) +activate ":SearchContactParser" + +":SearchContactParser" -> ":SearchContactParser" :parseSearchQuery(userInput:String) +":SearchContactParser" -> ":SearchContactParser" :getDetailFlag(userInput:String) + + +":SearchContactParser" -> ":SearchContactCommand" : execute(query:String, detailIndex:int) +activate ":SearchContactCommand" + +":SearchContactCommand" -> ":ContactList" : searchContact(query:String, detailIndex:int) +activate ":ContactList" + +loop for all contacts +":ContactList" -> ":ContactList" :getDetailFlag(userInput:String) +alt#gold #lightgreen NAME_INDEX + alt contact.getName().contains(query) + ":ContactList" -> ":TextUI" : viewContactMessage(contact, i) + activate ":TextUI" + deactivate ":TextUI" + end + + else GITHUB_INDEX + alt contact.getGithub().contains(query) + ":ContactList" -> ":TextUI" : viewContactMessage(contact, i) + activate ":TextUI" + deactivate ":TextUI" + end + + else LINKEDIN_INDEX + alt contact.getLinkedIn().contains(query) + ":ContactList" -> ":TextUI" : viewContactMessage(contact, i) + activate ":TextUI" + deactivate ":TextUI" + end + + else TELEGRAM_INDEX + alt contact.getTelegram().contains(query) + ":ContactList" -> ":TextUI" : viewContactMessage(contact, i) + activate ":TextUI" + deactivate ":TextUI" + end + else TWITTER_INDEX + alt contact.getTwitter().contains(query) + ":ContactList" -> ":TextUI" : viewContactMessage(contact, i) + activate ":TextUI" + deactivate ":TextUI" + end + else EMAIL_INDEX + alt contact.getEmail().contains(query) + ":ContactList" -> ":TextUI" : viewContactMessage(contact, i) + activate ":TextUI" + deactivate ":TextUI" + end end +end +@enduml \ No newline at end of file From 94847bc5342d745dbb4ccbc2292f724801ebed70 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Wed, 20 Oct 2021 16:00:12 +0800 Subject: [PATCH 340/756] Add sequence diagrams --- .../EditContactCommandSequenceDiagram.png | Bin 0 -> 51768 bytes .../SearchContactCommandSequenceDiagram.png | Bin 0 -> 72334 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/images/EditContactCommandSequenceDiagram.png create mode 100644 docs/images/SearchContactCommandSequenceDiagram.png diff --git a/docs/images/EditContactCommandSequenceDiagram.png b/docs/images/EditContactCommandSequenceDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..68b7f356d78084e67515128b592f21358a10302c GIT binary patch literal 51768 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 z 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 literal 0 HcmV?d00001 From aee35695465c9c447a4cf375589980084b10d4a2 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Wed, 20 Oct 2021 16:00:25 +0800 Subject: [PATCH 341/756] Add DG for editing contact --- docs/DeveloperGuide.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 62f78f97ae..35eb33d53f 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -76,6 +76,17 @@ corresponding `ContactList` and `Contact` objects. It is thus dependent on the c {NOT DONE} +### Editing a contact: `edit` +This feature is processed using `EditContactParser` under `MainParser`. In order to edit a contact in the contact list, +a user must enter a command in the form `edit [CONTACT INDEX] [DETAILS WITH FLAGS]` where the details with flags are +specified in the form `-flag detail` with up to 6 details i.e. `-g github-username -tw twitter_handle`. The user input +will be parsed by `EditContactParser` methods `getIndexToStore` and `parseContactDetails` to obtain a String array with +the details to be edited. An `EditContactCommand` with the specified parameters will then be created and executed in +`Duke`. The sequence diagram below shows how the whole process is carried out. + +![Edit Sequence Diagram](images/EditContactCommandSequenceDiagram.png) + + ### Deleting a contact: `rm` This feature is processed using the `DeleteContactCommand`. Whenever the user wants to remove a contact from the contact list using the `rm` command, `DeleteContactCommand` is created in the `MainParser` and executed in`Duke`. The sequence From a42d62c94f52133ee75855a845dd439c73ad1fe3 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Wed, 20 Oct 2021 16:00:38 +0800 Subject: [PATCH 342/756] Add DG for searching contact --- docs/DeveloperGuide.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 35eb33d53f..2d4bcd2e8d 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -96,7 +96,14 @@ diagram below shows how the `execute()` function of `DeleteContactCommand` works ![Delete Sequence Diagram](images/DeleteContactCommandSequenceDiagram.png) - +### Searching a contact: `edit` +This feature is processed using `SearchContactParser` under `MainParser`. In order to edit a contact in the contact list, +a user must enter a command in the form `search [FLAG] [SEARCH QUERY]`. If no flag is specified, the search will be done +on contact names buy default. From the user input, the search query and the search flag are obtained from the +`parseSearchQuery` and the `getDetailFlag` methods respectively. A `SearchContactCommand` with the specified parameters +will be created and executed in `Duke`. The sequence diagram below shows how the whole process is carried out. + +![Search Sequence Diagram](images/SearchContactCommandSequenceDiagram.png) ## Product scope From 017f20a5c3a630d7341c887221ac69804c4f4700 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 20 Oct 2021 22:46:04 +0800 Subject: [PATCH 343/756] Add sequence diagram for list command --- docs/diagrams/ListContactsCommand.puml | 38 ++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 docs/diagrams/ListContactsCommand.puml diff --git a/docs/diagrams/ListContactsCommand.puml b/docs/diagrams/ListContactsCommand.puml new file mode 100644 index 0000000000..f86a293e8d --- /dev/null +++ b/docs/diagrams/ListContactsCommand.puml @@ -0,0 +1,38 @@ +@startuml +hide footbox +'https://plantuml.com/sequence-diagram + +-> ":ListContactsCommand": execute() +activate ":ListContactsCommand" + +":ListContactsCommand" -> ":ContactList" :getListSize() +activate ":ContactList" + ":ContactList" --> ":ListContactsCommand" :contactListSize:int +deactivate ":ContactList" + +alt#gold #lightgreen listSize == 0 + ":ListContactsCommand" -> ":TextUi" :contactsEmptyListMessage() + activate ":TextUi" + ":TextUi" --> ":ListContactsCommand" + deactivate ":TextUi" +else #lightblue else + ":ListContactsCommand" -> ":ListContactsCommand" : listAllContacts(listSize:int) + activate ":ListContactsCommand" + ":ListContactsCommand" -> ":TextUi" :contactsListMessage(listSize:int) + activate ":TextUi" + ":TextUi" --> ":ListContactsCommand" + deactivate ":TextUi" + + loop #lightgrey listSize times + + ":ListContactsCommand" -> ":ContactList" : getContactName(index:int) + activate ":ContactList" + ":ContactList" --> ":ListContactsCommand" + deactivate ":ContactList" + ":ListContactsCommand" -> ":TextUi" : printContactWithIndex(index:int) + activate ":TextUi" + deactivate ":TextUi" + end + deactivate ":ListContactsCommand" +end +@enduml \ No newline at end of file From 0dc1d13d7ceb9e90c5212e0529affb689bcdaf83 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 20 Oct 2021 22:46:34 +0800 Subject: [PATCH 344/756] Add list sequence diagram as png --- docs/images/ListContactsCommand.png | Bin 0 -> 24464 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/images/ListContactsCommand.png diff --git a/docs/images/ListContactsCommand.png b/docs/images/ListContactsCommand.png new file mode 100644 index 0000000000000000000000000000000000000000..a5c9139ef1e643f96af3951e5133c988adc48e08 GIT binary patch literal 24464 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⁣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 literal 0 HcmV?d00001 From f6cb88ba5eefed623121dc2f209279d3a01f0905 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 20 Oct 2021 22:47:47 +0800 Subject: [PATCH 345/756] Refactor list uml --- docs/diagrams/ListContactsCommand.puml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/docs/diagrams/ListContactsCommand.puml b/docs/diagrams/ListContactsCommand.puml index f86a293e8d..a0fd73fca2 100644 --- a/docs/diagrams/ListContactsCommand.puml +++ b/docs/diagrams/ListContactsCommand.puml @@ -15,6 +15,7 @@ alt#gold #lightgreen listSize == 0 activate ":TextUi" ":TextUi" --> ":ListContactsCommand" deactivate ":TextUi" + else #lightblue else ":ListContactsCommand" -> ":ListContactsCommand" : listAllContacts(listSize:int) activate ":ListContactsCommand" @@ -25,14 +26,15 @@ else #lightblue else loop #lightgrey listSize times - ":ListContactsCommand" -> ":ContactList" : getContactName(index:int) - activate ":ContactList" - ":ContactList" --> ":ListContactsCommand" - deactivate ":ContactList" - ":ListContactsCommand" -> ":TextUi" : printContactWithIndex(index:int) - activate ":TextUi" - deactivate ":TextUi" + ":ListContactsCommand" -> ":ContactList" : getContactName(index:int) + activate ":ContactList" + ":ContactList" --> ":ListContactsCommand" + deactivate ":ContactList" + ":ListContactsCommand" -> ":TextUi" : printContactWithIndex(index:int) + activate ":TextUi" + deactivate ":TextUi" end + deactivate ":ListContactsCommand" end @enduml \ No newline at end of file From 712c0b8f551842227529622d7929a0c41356a748 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 20 Oct 2021 23:08:13 +0800 Subject: [PATCH 346/756] Update system architecture uml --- docs/diagrams/SystemArchitectureSequence.puml | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 docs/diagrams/SystemArchitectureSequence.puml diff --git a/docs/diagrams/SystemArchitectureSequence.puml b/docs/diagrams/SystemArchitectureSequence.puml new file mode 100644 index 0000000000..274fcbafbd --- /dev/null +++ b/docs/diagrams/SystemArchitectureSequence.puml @@ -0,0 +1,37 @@ +@startuml + +hide footbox + +actor User as user +participant ":Main" as main +participant ":MainParser" as parser +participant ":Command" as cmd +participant ":ContactList" as cl +participant ":TextUi" as ui +participant ":Storage" as store + +user -> main : "view 2" +activate main +main -> parser : parse("view 2") + +activate parser +parser -> cmd : viewContact(2) +deactivate parser + +activate cmd +cmd -> cl : getContact(2) +activate cl +cl --> cmd : Contact +deactivate cl + +cmd -> ui : printContact(Contact) +deactivate cmd +activate ui +ui --> main +deactivate ui +main-> store : updateStorage +activate store +store --> main +deactivate store + +@enduml \ No newline at end of file From f2a9a272e6f86ac4ebc464852f269919027cc4c5 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 20 Oct 2021 23:08:23 +0800 Subject: [PATCH 347/756] Save uml as png --- docs/images/SystemArchitectureSequence.png | Bin 0 -> 20923 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/images/SystemArchitectureSequence.png diff --git a/docs/images/SystemArchitectureSequence.png b/docs/images/SystemArchitectureSequence.png new file mode 100644 index 0000000000000000000000000000000000000000..1800ef2dca9c9ef77ea5f33357f1fdbc177562d6 GIT binary patch literal 20923 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 KN$z7^um1-)s|fA@ literal 0 HcmV?d00001 From 63d19b92d7a13ffd475be8dfb1d8a9a0ca31438d Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 20 Oct 2021 23:16:29 +0800 Subject: [PATCH 348/756] Add system sequence diagram --- docs/DeveloperGuide.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 2d4bcd2e8d..b055c9acb5 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -52,8 +52,13 @@ ConTech comprises five main components, namely: - `ContactList`: Data structure to store `Contact`s while running ConTech. - `Storage`: Reads from and writes to [`LocalStorage`](#local-storage). -The five main components interact with each other, as shown in the sequence diagram below. -{ NEED SEQUENCE DIAGRAM } +**How the architecture components interact with each other** + +The five main components interact with each other, as shown in the sequence diagram below +for the example "view 2" + +![Sysem Architecture Sequence Diagram](images/SystemArchitectureSequence.png) + ### TextUi ### MainParser From 7a843f9e4c22f43a1709256f1b5677016c330355 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 20 Oct 2021 23:25:48 +0800 Subject: [PATCH 349/756] Add list feature implementation --- docs/DeveloperGuide.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index b055c9acb5..0eb2527d84 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -111,6 +111,12 @@ will be created and executed in `Duke`. The sequence diagram below shows how the ![Search Sequence Diagram](images/SearchContactCommandSequenceDiagram.png) +### Listing all contacts: `list` +This feature is processed using `MainParser`. The control is sent to `ListContactsCommand` under `Command` to execute the +command which uses a loop to get the Contact object at every available index and print it using the `printContactWithIndex` +function in `TextUi` class. + + ## Product scope ### Target user profile - Has a need to store a significant amount of computing-related contacts From 3ddefd21b1db1cd1c2ceb243abf5ad7c7bf25166 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 20 Oct 2021 23:27:30 +0800 Subject: [PATCH 350/756] Update naming to comply with other files --- ...puml => ListContactsCommandSequenceDiagram.puml} | 0 ...d.png => ListContactsCommandSequenceDiagram.png} | Bin 2 files changed, 0 insertions(+), 0 deletions(-) rename docs/diagrams/{ListContactsCommand.puml => ListContactsCommandSequenceDiagram.puml} (100%) rename docs/images/{ListContactsCommand.png => ListContactsCommandSequenceDiagram.png} (100%) diff --git a/docs/diagrams/ListContactsCommand.puml b/docs/diagrams/ListContactsCommandSequenceDiagram.puml similarity index 100% rename from docs/diagrams/ListContactsCommand.puml rename to docs/diagrams/ListContactsCommandSequenceDiagram.puml diff --git a/docs/images/ListContactsCommand.png b/docs/images/ListContactsCommandSequenceDiagram.png similarity index 100% rename from docs/images/ListContactsCommand.png rename to docs/images/ListContactsCommandSequenceDiagram.png From 079eeeebbc24a9a36ad583da254465396225ca67 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 20 Oct 2021 23:28:44 +0800 Subject: [PATCH 351/756] Add list sequence diagram to DG --- docs/DeveloperGuide.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 0eb2527d84..0c94f518fb 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -116,6 +116,8 @@ This feature is processed using `MainParser`. The control is sent to `ListContac command which uses a loop to get the Contact object at every available index and print it using the `printContactWithIndex` function in `TextUi` class. +![List Sequence Diagram](images/ListContactCommandSequenceDiagram.png) + ## Product scope ### Target user profile From 220c4f40eb20ce58e7e653581eccd6ff9951c0c2 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 20 Oct 2021 23:29:40 +0800 Subject: [PATCH 352/756] Fix name --- docs/DeveloperGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 0c94f518fb..7969d3312c 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -116,7 +116,7 @@ This feature is processed using `MainParser`. The control is sent to `ListContac command which uses a loop to get the Contact object at every available index and print it using the `printContactWithIndex` function in `TextUi` class. -![List Sequence Diagram](images/ListContactCommandSequenceDiagram.png) +![List Sequence Diagram](images/ListContactsCommandSequenceDiagram.png) ## Product scope From df67890252c218afa7487e7c6b769259de48f92c Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Thu, 21 Oct 2021 03:08:01 +0800 Subject: [PATCH 353/756] Add confirmation message for adding duplicates --- src/main/java/seedu/ui/TextUi.java | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index e8b190986c..ef5d5793da 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -1,7 +1,9 @@ package seedu.ui; import seedu.contact.Contact; +import seedu.contact.ContactList; +import java.util.ArrayList; import java.util.Scanner; public abstract class TextUi { @@ -211,4 +213,22 @@ public static void helpMessage() { printDoubleLineMessage(message); } + public static void confirmAddDuplicateMessage(ArrayList duplicatedIndex, ContactList contactList) { + if (duplicatedIndex.size() == 1) { + Contact currentContact = contactList.getContactAtIndex(duplicatedIndex.get(0)); + String message = "One of your saved contacts has a similar field:\n" + + "\n" + duplicatedIndex.get(0) + ". " + currentContact.getName() + + formatContactFields(currentContact) + "\n\nDo you still want to add the contact? (y/n)\n"; + printDoubleLineMessage(message); + } else { + System.out.println(LINE); + System.out.println("These contacts are duplicates:\n"); + for (Integer index : duplicatedIndex) { + duplicatedContactsMessage(contactList.getContactAtIndex(index), index); + } + System.out.println("Do you still want to add the contact? (y/n)\n"); + System.out.println(LINE); + } + } + } From 29f03478d3d33e15518c3e16e38a445ba4adf59e Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Thu, 21 Oct 2021 03:09:15 +0800 Subject: [PATCH 354/756] Add confirmation message when editing duplicates --- src/main/java/seedu/ui/TextUi.java | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index ef5d5793da..f192163239 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -216,13 +216,13 @@ public static void helpMessage() { public static void confirmAddDuplicateMessage(ArrayList duplicatedIndex, ContactList contactList) { if (duplicatedIndex.size() == 1) { Contact currentContact = contactList.getContactAtIndex(duplicatedIndex.get(0)); - String message = "One of your saved contacts has a similar field:\n" + String message = "One of your saved contacts has a duplicate field:\n" + "\n" + duplicatedIndex.get(0) + ". " + currentContact.getName() + formatContactFields(currentContact) + "\n\nDo you still want to add the contact? (y/n)\n"; printDoubleLineMessage(message); } else { System.out.println(LINE); - System.out.println("These contacts are duplicates:\n"); + System.out.println("These contacts have duplicate fields:\n"); for (Integer index : duplicatedIndex) { duplicatedContactsMessage(contactList.getContactAtIndex(index), index); } @@ -231,4 +231,22 @@ public static void confirmAddDuplicateMessage(ArrayList duplicatedIndex } } + public static void confirmEditDuplicateMessage(ArrayList duplicatedIndex, ContactList contactList) { + if (duplicatedIndex.size() == 1) { + Contact currentContact = contactList.getContactAtIndex(duplicatedIndex.get(0)); + String message = "One of your saved contacts has a duplicate field:\n" + + "\n" + duplicatedIndex.get(0) + ". " + currentContact.getName() + + formatContactFields(currentContact) + "\n\nDo you still want to edit the contact? (y/n)\n"; + printDoubleLineMessage(message); + } else { + System.out.println(LINE); + System.out.println("These contacts have duplicate fields:\n"); + for (Integer index : duplicatedIndex) { + duplicatedContactsMessage(contactList.getContactAtIndex(index), index); + } + System.out.println("Do you still want to edit the contact? (y/n)\n"); + System.out.println(LINE); + } + } + } From 572a79a151798cd9cf1b7851fed29a6bf44d165a Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Thu, 21 Oct 2021 03:12:08 +0800 Subject: [PATCH 355/756] Add formatting to print duplicated contacts --- src/main/java/seedu/ui/TextUi.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index f192163239..fb73e589be 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -249,4 +249,10 @@ public static void confirmEditDuplicateMessage(ArrayList duplicatedInde } } + public static void duplicatedContactsMessage(Contact viewingContact, int index) { + String viewName = ViewMessageFormatterUi.viewNameFormatter(viewingContact); + String message = index + ". " + viewName + formatContactFields(viewingContact); + System.out.println(message + "\n"); + } + } From c9d55d509f0af88bdb1abfee0c1173ddcd2563f0 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Thu, 21 Oct 2021 03:13:34 +0800 Subject: [PATCH 356/756] Add ignore add contact message --- src/main/java/seedu/ui/TextUi.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index fb73e589be..4707aa2768 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -255,4 +255,9 @@ public static void duplicatedContactsMessage(Contact viewingContact, int index) System.out.println(message + "\n"); } + public static void ignoreAddContact() { + String message = "Contact was not added."; + printDoubleLineMessage(message); + } + } From b00cec7b84e097a6eb6c7d6d93ee3093e87ae4be Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Thu, 21 Oct 2021 03:14:14 +0800 Subject: [PATCH 357/756] Add ignore edit contact message --- src/main/java/seedu/ui/TextUi.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 4707aa2768..ea5e170b47 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -260,4 +260,9 @@ public static void ignoreAddContact() { printDoubleLineMessage(message); } + public static void ignoreEditContact() { + String message = "Contact was not edited."; + printDoubleLineMessage(message); + } + } From 72ab9ae0fc22e4aa53626ccfbd315226abeaadda Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Thu, 21 Oct 2021 03:15:25 +0800 Subject: [PATCH 358/756] Add duplicate catcher when adding contact --- src/main/java/seedu/command/AddContactCommand.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/command/AddContactCommand.java b/src/main/java/seedu/command/AddContactCommand.java index 3d6de7f4b6..7652bf7348 100644 --- a/src/main/java/seedu/command/AddContactCommand.java +++ b/src/main/java/seedu/command/AddContactCommand.java @@ -1,8 +1,12 @@ package seedu.command; import seedu.contact.Contact; +import seedu.contact.ContactList; import seedu.contact.DetailType; import seedu.ui.TextUi; +import seedu.ui.UserInputTextUi; + +import java.util.ArrayList; public class AddContactCommand extends Command { private final String name; @@ -47,7 +51,13 @@ public AddContactCommand(String[] details) { public void execute() { Contact addedContact = new Contact(name, github, linkedin, telegram, twitter, email); - contactList.addContact(addedContact); - TextUi.addContactMessage(addedContact, contactList.getListSize()); + if (duplicateCatcher(addedContact, contactList)) { + TextUi.ignoreAddContact(); + } else { + contactList.addContact(addedContact); + TextUi.addContactMessage(addedContact, contactList.getListSize()); + } + } + } } From 3cbb1cb762a6a836fc22436af9f6b1c90ed10bc3 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Thu, 21 Oct 2021 03:21:00 +0800 Subject: [PATCH 359/756] Add duplicate checker with all saved contacts for add --- .../java/seedu/command/AddContactCommand.java | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/main/java/seedu/command/AddContactCommand.java b/src/main/java/seedu/command/AddContactCommand.java index 7652bf7348..49ca9e0ab7 100644 --- a/src/main/java/seedu/command/AddContactCommand.java +++ b/src/main/java/seedu/command/AddContactCommand.java @@ -59,5 +59,50 @@ public void execute() { } } + public Boolean duplicateCatcher(Contact addedContact, ContactList contactList) { + ArrayList duplicatedIndex = new ArrayList<>(); + for (int i = 0; i < contactList.getListSize(); i++) { + Contact currentContact = contactList.getContactAtIndex(i); + if (duplicateField(addedContact.getName(), currentContact.getName())) { + duplicatedIndex.add(i); + continue; + } + if (addedContact.getGithub() != null && currentContact.getGithub() != null) { + if (duplicateField(addedContact.getGithub(), currentContact.getGithub())) { + duplicatedIndex.add(i); + continue; + } + } + if (addedContact.getEmail() != null && currentContact.getEmail() != null) { + if (duplicateField(addedContact.getEmail(), currentContact.getEmail())) { + duplicatedIndex.add(i); + continue; + } + } + if (addedContact.getTelegram() != null && currentContact.getTelegram() != null) { + if (duplicateField(addedContact.getTelegram(), currentContact.getTelegram())) { + duplicatedIndex.add(i); + continue; + } + } + if (addedContact.getLinkedin() != null && currentContact.getLinkedin() != null) { + if (duplicateField(addedContact.getLinkedin(), currentContact.getLinkedin())) { + duplicatedIndex.add(i); + continue; + } + } + if (addedContact.getTwitter() != null && currentContact.getTwitter() != null) { + if (duplicateField(addedContact.getTwitter(), currentContact.getTwitter())) { + duplicatedIndex.add(i); + } + } + } + if (!duplicatedIndex.isEmpty()) { + TextUi.confirmAddDuplicateMessage(duplicatedIndex, contactList); + String userAddConfirmation = UserInputTextUi.getUserConfirmation(); + return userAddConfirmation.equalsIgnoreCase("n"); + } + return false; + } } } From afab94decc20eb91f235c22084a9ccea1015f542 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Thu, 21 Oct 2021 03:21:48 +0800 Subject: [PATCH 360/756] Add string comparator to detect duplicates for add --- src/main/java/seedu/command/AddContactCommand.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/seedu/command/AddContactCommand.java b/src/main/java/seedu/command/AddContactCommand.java index 49ca9e0ab7..83c68fbf95 100644 --- a/src/main/java/seedu/command/AddContactCommand.java +++ b/src/main/java/seedu/command/AddContactCommand.java @@ -104,5 +104,10 @@ public Boolean duplicateCatcher(Contact addedContact, ContactList contactList) { } return false; } + + public Boolean duplicateField(String input, String saved) { + return stringCleaner(saved).equals(stringCleaner(input)); + } + } } From f68e47b9079ef904285ed23b77e3498df016979c Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Thu, 21 Oct 2021 03:27:27 +0800 Subject: [PATCH 361/756] Add string cleaner to remove spaces for add --- src/main/java/seedu/command/AddContactCommand.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/seedu/command/AddContactCommand.java b/src/main/java/seedu/command/AddContactCommand.java index 83c68fbf95..861aababed 100644 --- a/src/main/java/seedu/command/AddContactCommand.java +++ b/src/main/java/seedu/command/AddContactCommand.java @@ -109,5 +109,7 @@ public Boolean duplicateField(String input, String saved) { return stringCleaner(saved).equals(stringCleaner(input)); } + public String stringCleaner(String input) { + return input.replace(" ", "").toLowerCase(); } } From 67fcb2fc451a9d0370ccbf62054d2eb75ff2978b Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Thu, 21 Oct 2021 03:28:37 +0800 Subject: [PATCH 362/756] Add duplicate catcher in edit execution --- .../seedu/command/EditContactCommand.java | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index 6e74cf19bd..436af2a913 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -1,10 +1,21 @@ package seedu.command; +import seedu.contact.Contact; +import seedu.contact.ContactList; import seedu.exception.InvalidFlagException; import seedu.ui.TextUi; import seedu.ui.ExceptionTextUi; +import seedu.ui.UserInputTextUi; + +import java.util.ArrayList; public class EditContactCommand extends Command { + public static final int NAME_INDEX = 0; + public static final int GITHUB_INDEX = 1; + public static final int LINKEDIN_INDEX = 2; + public static final int TELEGRAM_INDEX = 3; + public static final int TWITTER_INDEX = 4; + public static final int EMAIL_INDEX = 5; String[] contactDetails; int contactIndex; @@ -15,8 +26,14 @@ public EditContactCommand(String[] contactDetails, int contactIndex) { public void execute() { try { - contactList.editContact(contactDetails, contactIndex); - TextUi.editContactMessage(contactList.getContactAtIndex(contactIndex)); + Contact preEditContact = duplicateContact(contactList.getContactAtIndex(contactIndex)); + Contact postEditContact = editTempContact(contactDetails,preEditContact); + if (duplicateCatcher(postEditContact, contactList, contactIndex)) { + TextUi.ignoreEditContact(); + } else { + contactList.editContact(contactDetails, contactIndex); + TextUi.editContactMessage(postEditContact); + } } catch (IndexOutOfBoundsException | InvalidFlagException e) { ExceptionTextUi.invalidIndexMessage(); } From 2677c3699a5d59c7d33d13098adae8fe0a9ffbad Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Thu, 21 Oct 2021 03:35:29 +0800 Subject: [PATCH 363/756] Add duplicate checker with all saved contacts for edit --- .../seedu/command/EditContactCommand.java | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index 436af2a913..205351faf5 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -38,4 +38,54 @@ public void execute() { ExceptionTextUi.invalidIndexMessage(); } } + + public Boolean duplicateCatcher(Contact postEditContact, ContactList contactList, int contactIndex) { + ArrayList duplicatedIndex = new ArrayList<>(); + for (int i = 0; i < contactList.getListSize(); i++) { + if (i == contactIndex) { + continue; + } + Contact currentContact = contactList.getContactAtIndex(i); + if (duplicateField(postEditContact.getName(), currentContact.getName())) { + duplicatedIndex.add(i); + continue; + } + if (postEditContact.getGithub() != null && currentContact.getGithub() != null) { + if (duplicateField(postEditContact.getGithub(), currentContact.getGithub())) { + duplicatedIndex.add(i); + continue; + } + } + if (postEditContact.getEmail() != null && currentContact.getEmail() != null) { + if (duplicateField(postEditContact.getEmail(), currentContact.getEmail())) { + duplicatedIndex.add(i); + continue; + } + } + if (postEditContact.getTelegram() != null && currentContact.getTelegram() != null) { + if (duplicateField(postEditContact.getTelegram(), currentContact.getTelegram())) { + duplicatedIndex.add(i); + continue; + } + } + if (postEditContact.getLinkedin() != null && currentContact.getLinkedin() != null) { + if (duplicateField(postEditContact.getLinkedin(), currentContact.getLinkedin())) { + duplicatedIndex.add(i); + continue; + } + } + if (postEditContact.getTwitter() != null && currentContact.getTwitter() != null) { + if (duplicateField(postEditContact.getTwitter(), currentContact.getTwitter())) { + duplicatedIndex.add(i); + } + } + } + if (!duplicatedIndex.isEmpty()) { + TextUi.confirmEditDuplicateMessage(duplicatedIndex, contactList); + String userEditConfirmation = UserInputTextUi.getUserConfirmation(); + return userEditConfirmation.equalsIgnoreCase("n"); + } + return false; + } + } From eddf2bd65955f5abb990816d404b4edc5ff19704 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Thu, 21 Oct 2021 03:36:35 +0800 Subject: [PATCH 364/756] Implement duplicate contact method --- src/main/java/seedu/command/EditContactCommand.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index 205351faf5..cdd04c290d 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -88,4 +88,14 @@ public Boolean duplicateCatcher(Contact postEditContact, ContactList contactList return false; } + public Contact duplicateContact(Contact contact) { + String name = contact.getName(); + String github = contact.getGithub(); + String linkedin = contact.getLinkedin(); + String telegram = contact.getTelegram(); + String twitter = contact.getTwitter(); + String email = contact.getEmail(); + return new Contact(name, github, linkedin, telegram, twitter, email); + } + } From 2ff8ff245f1d330e751fa1d9111b76b5829f792e Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Thu, 21 Oct 2021 03:38:06 +0800 Subject: [PATCH 365/756] Add string comparator to detect duplicates for edit --- src/main/java/seedu/command/EditContactCommand.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index cdd04c290d..a51aec2f7a 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -98,4 +98,8 @@ public Contact duplicateContact(Contact contact) { return new Contact(name, github, linkedin, telegram, twitter, email); } + public Boolean duplicateField(String input, String saved) { + return stringCleaner(saved).equals(stringCleaner(input)); + } + } From 255e32492d97059c9d72dd442fb943b0ea2b84d3 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Thu, 21 Oct 2021 03:38:41 +0800 Subject: [PATCH 366/756] Add string cleaner for edit --- src/main/java/seedu/command/EditContactCommand.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index a51aec2f7a..efd854d976 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -102,4 +102,9 @@ public Boolean duplicateField(String input, String saved) { return stringCleaner(saved).equals(stringCleaner(input)); } + public String stringCleaner(String input) { + return input.replace(" ", "").toLowerCase(); + } + + } From 7c10d802bf1ca9e5e14344de3744571ab5d378a6 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Thu, 21 Oct 2021 03:40:15 +0800 Subject: [PATCH 367/756] Add edit temporary contact method --- .../seedu/command/EditContactCommand.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index efd854d976..323fe75426 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -107,4 +107,36 @@ public String stringCleaner(String input) { } + public Contact editTempContact(String[] contactDetails, Contact preEditContact) throws InvalidFlagException { + Contact tempContact = duplicateContact(preEditContact); + for (int i = 0; i < contactDetails.length; i++) { + if (contactDetails[i] != null) { + switch (i) { + case NAME_INDEX: + tempContact.setName(contactDetails[i]); + break; + case GITHUB_INDEX: + tempContact.setGithub(contactDetails[i]); + break; + case LINKEDIN_INDEX: + tempContact.setLinkedin(contactDetails[i]); + break; + case TELEGRAM_INDEX: + tempContact.setTelegram(contactDetails[i]); + break; + case TWITTER_INDEX: + tempContact.setTwitter(contactDetails[i]); + break; + case EMAIL_INDEX: + tempContact.setEmail(contactDetails[i]); + break; + default: + //control should never reach here + assert false; + throw new InvalidFlagException(); + } + } + } + return tempContact; + } } From 7a4e3f96434ebb3834efb7501e64f6d74c5172d0 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Thu, 21 Oct 2021 04:12:30 +0800 Subject: [PATCH 368/756] Update to text-ui-test --- text-ui-test/ACTUAL.TXT | 53 +++++++++++++++++++++++++++++----- text-ui-test/EXPECTED-UNIX.TXT | 53 +++++++++++++++++++++++++++++----- text-ui-test/EXPECTED.TXT | 53 +++++++++++++++++++++++++++++----- text-ui-test/input.txt | 4 +++ 4 files changed, 139 insertions(+), 24 deletions(-) diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index d00244fb5d..307c154e54 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -150,6 +150,16 @@ Github: github.com/marcus You now have 4 contact(s). ____________________________________________________________ +____________________________________________________________ +One of your saved contacts has a duplicate field: + +3. ng andre +Github: github.com/ng-andre + +Do you still want to add the contact? (y/n) + +____________________________________________________________ + ____________________________________________________________ ConTech has added the specified contact: Name: andre @@ -413,6 +423,16 @@ ____________________________________________________________ Due to the storage nature of ConTech, we will remove commas (","), and attempt to parse it as: add -n lezong mun -g lezaimun +____________________________________________________________ +One of your saved contacts has a duplicate field: + +2. lezongmun +Github: github.com/lezong + +Do you still want to add the contact? (y/n) + +____________________________________________________________ + ____________________________________________________________ ConTech has added the specified contact: Name: lezong mun @@ -439,6 +459,16 @@ Github: github.com/nullptr You now have 8 contact(s). ____________________________________________________________ +____________________________________________________________ +One of your saved contacts has a duplicate field: + +4. lezongmun +Github: github.com/lezong + +Do you still want to edit the contact? (y/n) + +____________________________________________________________ + ____________________________________________________________ ConTech has edited the specified contact: Name: lezong mun @@ -453,6 +483,21 @@ Rules for Twitter username : * Maximum 15 characters allowed ____________________________________________________________ +____________________________________________________________ +ConTech is unable to understand your request. +Please try again with a valid command. +____________________________________________________________ + +____________________________________________________________ +One of your saved contacts has a duplicate field: + +0. asjoda sadfsd +Telegram: t.me/_123adad + +Do you still want to add the contact? (y/n) + +____________________________________________________________ + ____________________________________________________________ ConTech has added the specified contact: Name: asjoda sadfsd @@ -469,14 +514,6 @@ Rules for email id : * @ cannot be at the start or end ____________________________________________________________ -____________________________________________________________ -The email id is not correctly formatted, -Rules for email id : - * Lowercase letters only - * Numbers, underscore, hyphen and dot allowed - * @ cannot be at the start or end -____________________________________________________________ - ____________________________________________________________ There appears to be a flag that is not recognised. Please try again with a valid flag. diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index d00244fb5d..307c154e54 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -150,6 +150,16 @@ Github: github.com/marcus You now have 4 contact(s). ____________________________________________________________ +____________________________________________________________ +One of your saved contacts has a duplicate field: + +3. ng andre +Github: github.com/ng-andre + +Do you still want to add the contact? (y/n) + +____________________________________________________________ + ____________________________________________________________ ConTech has added the specified contact: Name: andre @@ -413,6 +423,16 @@ ____________________________________________________________ Due to the storage nature of ConTech, we will remove commas (","), and attempt to parse it as: add -n lezong mun -g lezaimun +____________________________________________________________ +One of your saved contacts has a duplicate field: + +2. lezongmun +Github: github.com/lezong + +Do you still want to add the contact? (y/n) + +____________________________________________________________ + ____________________________________________________________ ConTech has added the specified contact: Name: lezong mun @@ -439,6 +459,16 @@ Github: github.com/nullptr You now have 8 contact(s). ____________________________________________________________ +____________________________________________________________ +One of your saved contacts has a duplicate field: + +4. lezongmun +Github: github.com/lezong + +Do you still want to edit the contact? (y/n) + +____________________________________________________________ + ____________________________________________________________ ConTech has edited the specified contact: Name: lezong mun @@ -453,6 +483,21 @@ Rules for Twitter username : * Maximum 15 characters allowed ____________________________________________________________ +____________________________________________________________ +ConTech is unable to understand your request. +Please try again with a valid command. +____________________________________________________________ + +____________________________________________________________ +One of your saved contacts has a duplicate field: + +0. asjoda sadfsd +Telegram: t.me/_123adad + +Do you still want to add the contact? (y/n) + +____________________________________________________________ + ____________________________________________________________ ConTech has added the specified contact: Name: asjoda sadfsd @@ -469,14 +514,6 @@ Rules for email id : * @ cannot be at the start or end ____________________________________________________________ -____________________________________________________________ -The email id is not correctly formatted, -Rules for email id : - * Lowercase letters only - * Numbers, underscore, hyphen and dot allowed - * @ cannot be at the start or end -____________________________________________________________ - ____________________________________________________________ There appears to be a flag that is not recognised. Please try again with a valid flag. diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index d00244fb5d..307c154e54 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -150,6 +150,16 @@ Github: github.com/marcus You now have 4 contact(s). ____________________________________________________________ +____________________________________________________________ +One of your saved contacts has a duplicate field: + +3. ng andre +Github: github.com/ng-andre + +Do you still want to add the contact? (y/n) + +____________________________________________________________ + ____________________________________________________________ ConTech has added the specified contact: Name: andre @@ -413,6 +423,16 @@ ____________________________________________________________ Due to the storage nature of ConTech, we will remove commas (","), and attempt to parse it as: add -n lezong mun -g lezaimun +____________________________________________________________ +One of your saved contacts has a duplicate field: + +2. lezongmun +Github: github.com/lezong + +Do you still want to add the contact? (y/n) + +____________________________________________________________ + ____________________________________________________________ ConTech has added the specified contact: Name: lezong mun @@ -439,6 +459,16 @@ Github: github.com/nullptr You now have 8 contact(s). ____________________________________________________________ +____________________________________________________________ +One of your saved contacts has a duplicate field: + +4. lezongmun +Github: github.com/lezong + +Do you still want to edit the contact? (y/n) + +____________________________________________________________ + ____________________________________________________________ ConTech has edited the specified contact: Name: lezong mun @@ -453,6 +483,21 @@ Rules for Twitter username : * Maximum 15 characters allowed ____________________________________________________________ +____________________________________________________________ +ConTech is unable to understand your request. +Please try again with a valid command. +____________________________________________________________ + +____________________________________________________________ +One of your saved contacts has a duplicate field: + +0. asjoda sadfsd +Telegram: t.me/_123adad + +Do you still want to add the contact? (y/n) + +____________________________________________________________ + ____________________________________________________________ ConTech has added the specified contact: Name: asjoda sadfsd @@ -469,14 +514,6 @@ Rules for email id : * @ cannot be at the start or end ____________________________________________________________ -____________________________________________________________ -The email id is not correctly formatted, -Rules for email id : - * Lowercase letters only - * Numbers, underscore, hyphen and dot allowed - * @ cannot be at the start or end -____________________________________________________________ - ____________________________________________________________ There appears to be a flag that is not recognised. Please try again with a valid flag. diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index e2795e4175..893eb55360 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -19,6 +19,7 @@ add -n mayank -g mayankp123 rm 9909 add -n bory -g marcus add -n andre -g ng-andre +y list view 1 add -n bory -g @@ -53,11 +54,14 @@ add -n asjoda sadfsd -te _123adad view 0 add -n -g add -n le,zong, mun -g lezaimun + y add -n null -g legit add -n name -g null add -n dev -g nullptr edit 3 -g new-git + y add -n asjoda sadfsd -tw _123 adad + y add -n asjoda sadfsd -tw 123_adad add -n name -l linkedin -g github -e lasdas@ -tw twitter -te telegram add -n asdasd -l kusdd__ -g adasdas -e .adadas@com From 8ca42bf727cccc43ee1376d565581343f474a2a9 Mon Sep 17 00:00:00 2001 From: lezong Date: Thu, 21 Oct 2021 09:17:26 +0800 Subject: [PATCH 369/756] remove file' : --- src/main/java/seedu/command/Command.java | 6 ++++++ src/main/java/seedu/duke/Duke.java | 1 + 2 files changed, 7 insertions(+) diff --git a/src/main/java/seedu/command/Command.java b/src/main/java/seedu/command/Command.java index c9c6808d4b..185e6191ce 100644 --- a/src/main/java/seedu/command/Command.java +++ b/src/main/java/seedu/command/Command.java @@ -1,14 +1,20 @@ package seedu.command; +import seedu.contact.Contact; import seedu.contact.ContactList; public abstract class Command { protected ContactList contactList; + protected Contact personalContact; public void setContactList(ContactList contactList) { this.contactList = contactList; } + public void setPersonalContact(Contact personalContact) { + this.personalContact = personalContact; + } + public abstract void execute(); public boolean isExit() { diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 00be8a1467..8d09c34dff 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -45,6 +45,7 @@ private void runConTech() { private void runCommandProcedure(Command command) { try { command.setContactList(contactList); + command.setPersonalContact(personalContact); command.execute(); ContactsEncoder.saveContacts(contactFilePath, contactList); } catch (FileErrorException e) { From 6abcbf9915782a70850b8c8f629097dbf8c1d651 Mon Sep 17 00:00:00 2001 From: lezong Date: Thu, 21 Oct 2021 10:59:51 +0800 Subject: [PATCH 370/756] Minor edit to textui --- src/main/java/seedu/duke/Duke.java | 1 - src/main/java/seedu/ui/TextUi.java | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 8d09c34dff..9993950d1e 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -7,7 +7,6 @@ import seedu.parser.MainParser; import seedu.storage.ContactsEncoder; import seedu.storage.Storage; -import seedu.ui.TextUi; import seedu.ui.ExceptionTextUi; import seedu.ui.UserInputTextUi; diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index e8b190986c..55b8c6255b 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -42,7 +42,7 @@ public static void welcomeMessage() { public static void welcomeBackMessage(Contact personalContact) { printDoubleLineMessage(LOGO); String message = "Hello, " + personalContact.getName() + ". \nWelcome back to ConTech, " - + "your personal \ncontact tracker."; + + "your personal contact tracker."; printBottomLineMessage(message); } From 7a6f1e7a8210566878110aac7c034119afea5a2a Mon Sep 17 00:00:00 2001 From: lezong Date: Thu, 21 Oct 2021 11:26:32 +0800 Subject: [PATCH 371/756] Add a personalContactCommand to view personal contact info --- .../seedu/command/PersonalContactCommand.java | 9 ++++++++ src/main/java/seedu/parser/MainParser.java | 23 ++++++++++--------- .../java/seedu/storage/ContactsDecoder.java | 18 +++++++-------- src/main/java/seedu/ui/TextUi.java | 6 +++++ 4 files changed, 36 insertions(+), 20 deletions(-) create mode 100644 src/main/java/seedu/command/PersonalContactCommand.java diff --git a/src/main/java/seedu/command/PersonalContactCommand.java b/src/main/java/seedu/command/PersonalContactCommand.java new file mode 100644 index 0000000000..27e90f8b50 --- /dev/null +++ b/src/main/java/seedu/command/PersonalContactCommand.java @@ -0,0 +1,9 @@ +package seedu.command; + +import seedu.ui.TextUi; + +public class PersonalContactCommand extends Command { + public void execute() { + TextUi.viewPersonalContactMessage(this.personalContact); + } +} diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 0659681a8d..598fb60a96 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -1,16 +1,6 @@ package seedu.parser; -import seedu.command.AddContactCommand; -import seedu.command.EditContactCommand; -import seedu.command.DeleteContactCommand; -import seedu.command.Command; -import seedu.command.HelpCommand; -import seedu.command.InvalidDetailCommand; -import seedu.command.ViewContactCommand; -import seedu.command.FailedCommand; -import seedu.command.ExitCommand; -import seedu.command.ListContactsCommand; -import seedu.command.SearchContactCommand; +import seedu.command.*; import seedu.exception.ForbiddenDetailException; import seedu.exception.InvalidEmailException; @@ -35,6 +25,7 @@ public class MainParser { private static final String LIST_COMD = "list"; private static final String HELP_COMD = "help"; private static final String SEARCH_COMD = "search"; + private static final String PERSONAL_CONTACT_COMD = "me"; private static final int COMD_WORD_INDEX = 0; private static final int ISOLATE_COMD_WORD = 2; @@ -73,12 +64,16 @@ public Command parseCommand(String userInput) { case SEARCH_COMD: command = parseSearchCommand(userInput); break; + case PERSONAL_CONTACT_COMD: + command = parsePersonalContact(); + break; default: command = new FailedCommand(FailedCommandType.GENERAL); } return command; } + public String getCommandWord(String userInput) { String[] destructuredInputs = userInput.split(" ", ISOLATE_COMD_WORD); return destructuredInputs[COMD_WORD_INDEX]; @@ -171,6 +166,7 @@ private Command parseViewContact(String userInput) { } } + //@@author lezongmun private Command parseDeleteContact(String userInput) { try { int deletedIndex = IndexParser.getIndexFromInput(userInput); @@ -194,4 +190,9 @@ private Command parseSearchCommand(String userInput) { return new FailedCommand(FailedCommandType.INVALID_FLAG); } } + + //@author lezongmun + private Command parsePersonalContact() { + return new PersonalContactCommand(); + } } diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index 115ec4ca0d..fb1072904d 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -34,7 +34,7 @@ public static Contact readPersonalContact(File personalContactFile) throws FileE Scanner fileScanner = new Scanner(personalContactFile); if (fileScanner.hasNext()) { String contactText = fileScanner.nextLine(); - personalContact = decodePersonalContact(contactText, personalContact); + personalContact = decodePersonalContact(personalContact, contactText); } } catch (FileNotFoundException e) { throw new FileErrorException(); @@ -43,16 +43,16 @@ public static Contact readPersonalContact(File personalContactFile) throws FileE } - private static Contact decodePersonalContact(String contactText, Contact contact) { - String[] destructuredInputs = contactText.split(SEPARATOR); + private static Contact decodePersonalContact(Contact contact, String contactText) { Contact personalContact = contact; try { - String contactName = destructuredInputs[DetailType.NAME.getIndex()]; - String contactGithub = destructuredInputs[DetailType.GITHUB.getIndex()]; - String contactLinkedin = destructuredInputs[DetailType.LINKEDIN.getIndex()]; - String contactTelegram = destructuredInputs[DetailType.TELEGRAM.getIndex()]; - String contactTwitter = destructuredInputs[DetailType.TWITTER.getIndex()]; - String contactEmail = destructuredInputs[DetailType.EMAIL.getIndex()]; + String[] compiledDetails = decodeDetails(contactText); + String contactName = compiledDetails[DetailType.NAME.getIndex()]; + String contactGithub = compiledDetails[DetailType.GITHUB.getIndex()]; + String contactLinkedin = compiledDetails[DetailType.LINKEDIN.getIndex()]; + String contactTelegram = compiledDetails[DetailType.TELEGRAM.getIndex()]; + String contactTwitter = compiledDetails[DetailType.TWITTER.getIndex()]; + String contactEmail = compiledDetails[DetailType.EMAIL.getIndex()]; personalContact = new Contact(contactName, contactGithub, contactLinkedin, contactTelegram, contactTwitter, contactEmail); } catch (IndexOutOfBoundsException e) { diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 55b8c6255b..2f37f4819c 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -161,6 +161,12 @@ public static void searchNoResultsFoundMessage() { printDoubleLineMessage(message); } + public static void viewPersonalContactMessage(Contact personalContact) { + String personalName = ViewMessageFormatterUi.viewNameFormatter(personalContact); + String message = "Name: " + personalName + formatContactFields(personalContact); + printDoubleLineMessage(message); + } + public static void confirmDeleteMessage(Contact deletedContact, int deletedIndex) { String message = "Delete this contact? (y/n)\n" + deletedIndex + ". " + deletedContact.getName() + formatContactFields(deletedContact); From 0451186dfd6c927b9feee44df2c0198fb8cc1b20 Mon Sep 17 00:00:00 2001 From: lezong Date: Thu, 21 Oct 2021 11:30:37 +0800 Subject: [PATCH 372/756] Update text-ui-test --- text-ui-test/ACTUAL.TXT | 7 +++++++ text-ui-test/EXPECTED-UNIX.TXT | 7 +++++++ text-ui-test/EXPECTED.TXT | 7 +++++++ text-ui-test/input.txt | 1 + 4 files changed, 22 insertions(+) diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index d00244fb5d..c87c5ff95d 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -80,6 +80,13 @@ later on. To see what you can do with ConTech, enter "help". ____________________________________________________________ +____________________________________________________________ +Name: Le Zong +Github: github.com/lezongmun +Email: lezongmun@gmail.com +Telegram: t.me/lezongg +____________________________________________________________ + ____________________________________________________________ There are no contacts stored in ConTech. ____________________________________________________________ diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index d00244fb5d..c87c5ff95d 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -80,6 +80,13 @@ later on. To see what you can do with ConTech, enter "help". ____________________________________________________________ +____________________________________________________________ +Name: Le Zong +Github: github.com/lezongmun +Email: lezongmun@gmail.com +Telegram: t.me/lezongg +____________________________________________________________ + ____________________________________________________________ There are no contacts stored in ConTech. ____________________________________________________________ diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index d00244fb5d..c87c5ff95d 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -80,6 +80,13 @@ later on. To see what you can do with ConTech, enter "help". ____________________________________________________________ +____________________________________________________________ +Name: Le Zong +Github: github.com/lezongmun +Email: lezongmun@gmail.com +Telegram: t.me/lezongg +____________________________________________________________ + ____________________________________________________________ There are no contacts stored in ConTech. ____________________________________________________________ diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index e2795e4175..28ea20bcac 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -6,6 +6,7 @@ lezongg @gmail.com lezongmun@gmail.com +me rm 1 add -n ng andre -g ng-andre rm 2 From 358eb27c6ba875a99b76afe48185a12163e46eaa Mon Sep 17 00:00:00 2001 From: lezong Date: Thu, 21 Oct 2021 11:37:05 +0800 Subject: [PATCH 373/756] Fix checkstyle --- src/main/java/seedu/parser/MainParser.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 598fb60a96..bffe1cfc8d 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -1,7 +1,18 @@ package seedu.parser; -import seedu.command.*; +import seedu.command.AddContactCommand; +import seedu.command.Command; +import seedu.command.DeleteContactCommand; +import seedu.command.EditContactCommand; +import seedu.command.ExitCommand; +import seedu.command.FailedCommand; +import seedu.command.HelpCommand; +import seedu.command.InvalidDetailCommand; +import seedu.command.ListContactsCommand; +import seedu.command.PersonalContactCommand; +import seedu.command.SearchContactCommand; +import seedu.command.ViewContactCommand; import seedu.exception.ForbiddenDetailException; import seedu.exception.InvalidEmailException; import seedu.exception.InvalidFlagException; From 160e03668d72011c17311b044e2acfc16dee19c2 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Thu, 21 Oct 2021 12:28:49 +0800 Subject: [PATCH 374/756] Combine duplicate message for add and edit --- src/main/java/seedu/ui/TextUi.java | 38 +++++++++++++----------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index ea5e170b47..704ff8360f 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -213,30 +213,20 @@ public static void helpMessage() { printDoubleLineMessage(message); } - public static void confirmAddDuplicateMessage(ArrayList duplicatedIndex, ContactList contactList) { + public static void confirmDuplicateMessage(ArrayList duplicatedIndex, + ContactList contactList, String type) { if (duplicatedIndex.size() == 1) { Contact currentContact = contactList.getContactAtIndex(duplicatedIndex.get(0)); - String message = "One of your saved contacts has a duplicate field:\n" - + "\n" + duplicatedIndex.get(0) + ". " + currentContact.getName() - + formatContactFields(currentContact) + "\n\nDo you still want to add the contact? (y/n)\n"; - printDoubleLineMessage(message); - } else { - System.out.println(LINE); - System.out.println("These contacts have duplicate fields:\n"); - for (Integer index : duplicatedIndex) { - duplicatedContactsMessage(contactList.getContactAtIndex(index), index); + String message; + if (type.equals("add")) { + message = "One of your saved contacts has a duplicate field:\n" + + "\n" + duplicatedIndex.get(0) + ". " + currentContact.getName() + + formatContactFields(currentContact) + "\n\nDo you still want to add the contact? (y/n)\n"; + } else { + message = "One of your saved contacts has a duplicate field:\n" + + "\n" + duplicatedIndex.get(0) + ". " + currentContact.getName() + + formatContactFields(currentContact) + "\n\nDo you still want to edit the contact? (y/n)\n"; } - System.out.println("Do you still want to add the contact? (y/n)\n"); - System.out.println(LINE); - } - } - - public static void confirmEditDuplicateMessage(ArrayList duplicatedIndex, ContactList contactList) { - if (duplicatedIndex.size() == 1) { - Contact currentContact = contactList.getContactAtIndex(duplicatedIndex.get(0)); - String message = "One of your saved contacts has a duplicate field:\n" - + "\n" + duplicatedIndex.get(0) + ". " + currentContact.getName() - + formatContactFields(currentContact) + "\n\nDo you still want to edit the contact? (y/n)\n"; printDoubleLineMessage(message); } else { System.out.println(LINE); @@ -244,7 +234,11 @@ public static void confirmEditDuplicateMessage(ArrayList duplicatedInde for (Integer index : duplicatedIndex) { duplicatedContactsMessage(contactList.getContactAtIndex(index), index); } - System.out.println("Do you still want to edit the contact? (y/n)\n"); + if (type.equals("add")) { + System.out.println("Do you still want to add the contact? (y/n)\n"); + } else { + System.out.println("Do you still want to edit the contact? (y/n)\n"); + } System.out.println(LINE); } } From ccdf69faf90dba9de9061f22b59fd8f5ee5a0b33 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Thu, 21 Oct 2021 12:29:04 +0800 Subject: [PATCH 375/756] Combine ignore message for add and edit --- src/main/java/seedu/ui/TextUi.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 704ff8360f..1183120c52 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -249,13 +249,13 @@ public static void duplicatedContactsMessage(Contact viewingContact, int index) System.out.println(message + "\n"); } - public static void ignoreAddContact() { - String message = "Contact was not added."; - printDoubleLineMessage(message); - } - - public static void ignoreEditContact() { - String message = "Contact was not edited."; + public static void ignoreContact(String type) { + String message; + if (type.equals("add")) { + message = "Contact was not added."; + } else { + message = "Contact was not edited."; + } printDoubleLineMessage(message); } From 5db273b189f393426e8c2962f09e0ce6d270fa3e Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Thu, 21 Oct 2021 12:30:01 +0800 Subject: [PATCH 376/756] Refactor add duplicate catcher --- .../java/seedu/command/AddContactCommand.java | 71 ++++++++----------- 1 file changed, 31 insertions(+), 40 deletions(-) diff --git a/src/main/java/seedu/command/AddContactCommand.java b/src/main/java/seedu/command/AddContactCommand.java index 861aababed..d2df5fdeb4 100644 --- a/src/main/java/seedu/command/AddContactCommand.java +++ b/src/main/java/seedu/command/AddContactCommand.java @@ -1,12 +1,16 @@ package seedu.command; import seedu.contact.Contact; +import seedu.contact.ContactComparator; import seedu.contact.ContactList; import seedu.contact.DetailType; +import seedu.exception.InvalidFlagException; +import seedu.ui.ExceptionTextUi; import seedu.ui.TextUi; import seedu.ui.UserInputTextUi; import java.util.ArrayList; +import java.util.Arrays; public class AddContactCommand extends Command { private final String name; @@ -15,6 +19,13 @@ public class AddContactCommand extends Command { private final String telegram; private final String twitter; private final String email; + public static final int NUMBER_OF_FIELDS = 6; + public static final int NAME_INDEX = 0; + public static final int GITHUB_INDEX = 1; + public static final int LINKEDIN_INDEX = 2; + public static final int TELEGRAM_INDEX = 3; + public static final int TWITTER_INDEX = 4; + public static final int EMAIL_INDEX = 5; public String getLinkedin() { return linkedin; @@ -50,55 +61,35 @@ public AddContactCommand(String[] details) { } public void execute() { - Contact addedContact = new Contact(name, github, linkedin, telegram, twitter, email); - if (duplicateCatcher(addedContact, contactList)) { - TextUi.ignoreAddContact(); - } else { - contactList.addContact(addedContact); - TextUi.addContactMessage(addedContact, contactList.getListSize()); + try { + Contact addedContact = new Contact(name, github, linkedin, telegram, twitter, email); + if (hasDuplicates(addedContact, contactList)) { + TextUi.ignoreContact("add"); + } else { + contactList.addContact(addedContact); + TextUi.addContactMessage(addedContact, contactList.getListSize()); + } + } catch (InvalidFlagException e) { + ExceptionTextUi.invalidIndexMessage(); } } - public Boolean duplicateCatcher(Contact addedContact, ContactList contactList) { + private Boolean hasDuplicates(Contact addedContact, ContactList contactList) throws InvalidFlagException { ArrayList duplicatedIndex = new ArrayList<>(); + String[] addedContactDetails = extractContactDetails(addedContact); for (int i = 0; i < contactList.getListSize(); i++) { - Contact currentContact = contactList.getContactAtIndex(i); - if (duplicateField(addedContact.getName(), currentContact.getName())) { - duplicatedIndex.add(i); - continue; - } - if (addedContact.getGithub() != null && currentContact.getGithub() != null) { - if (duplicateField(addedContact.getGithub(), currentContact.getGithub())) { - duplicatedIndex.add(i); - continue; - } - } - if (addedContact.getEmail() != null && currentContact.getEmail() != null) { - if (duplicateField(addedContact.getEmail(), currentContact.getEmail())) { - duplicatedIndex.add(i); - continue; - } - } - if (addedContact.getTelegram() != null && currentContact.getTelegram() != null) { - if (duplicateField(addedContact.getTelegram(), currentContact.getTelegram())) { - duplicatedIndex.add(i); - continue; - } - } - if (addedContact.getLinkedin() != null && currentContact.getLinkedin() != null) { - if (duplicateField(addedContact.getLinkedin(), currentContact.getLinkedin())) { - duplicatedIndex.add(i); - continue; - } - } - if (addedContact.getTwitter() != null && currentContact.getTwitter() != null) { - if (duplicateField(addedContact.getTwitter(), currentContact.getTwitter())) { - duplicatedIndex.add(i); + String[] currentContactDetails = extractContactDetails(contactList.getContactAtIndex(i)); + for (int j = 0; j < NUMBER_OF_FIELDS; j++) { + if (addedContactDetails[j] != null && currentContactDetails[j] != null) { + if (hasDuplicateField(addedContactDetails[j], currentContactDetails[j])) { + duplicatedIndex.add(i); + break; + } } } } if (!duplicatedIndex.isEmpty()) { - TextUi.confirmAddDuplicateMessage(duplicatedIndex, contactList); + TextUi.confirmDuplicateMessage(duplicatedIndex, contactList, "add"); String userAddConfirmation = UserInputTextUi.getUserConfirmation(); return userAddConfirmation.equalsIgnoreCase("n"); } From 84b2c37d6b113145852faf06e8b416c226cb8d16 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Thu, 21 Oct 2021 12:30:33 +0800 Subject: [PATCH 377/756] Implement extract contact details into string array --- .../java/seedu/command/AddContactCommand.java | 34 +++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/command/AddContactCommand.java b/src/main/java/seedu/command/AddContactCommand.java index d2df5fdeb4..394c192ee4 100644 --- a/src/main/java/seedu/command/AddContactCommand.java +++ b/src/main/java/seedu/command/AddContactCommand.java @@ -96,11 +96,41 @@ private Boolean hasDuplicates(Contact addedContact, ContactList contactList) thr return false; } - public Boolean duplicateField(String input, String saved) { + private String[] extractContactDetails(Contact contact) throws InvalidFlagException { + String[] contactDetails = new String[NUMBER_OF_FIELDS]; + for (int i = 0; i < NUMBER_OF_FIELDS; i++) { + switch (i) { + case NAME_INDEX: + contactDetails[NAME_INDEX] = contact.getName(); + break; + case GITHUB_INDEX: + contactDetails[GITHUB_INDEX] = contact.getGithub(); + break; + case LINKEDIN_INDEX: + contactDetails[LINKEDIN_INDEX] = contact.getLinkedin(); + break; + case TELEGRAM_INDEX: + contactDetails[TELEGRAM_INDEX] = contact.getTelegram(); + break; + case TWITTER_INDEX: + contactDetails[TWITTER_INDEX] = contact.getTwitter(); + break; + case EMAIL_INDEX: + contactDetails[EMAIL_INDEX] = contact.getEmail(); + break; + default: + assert false; + throw new InvalidFlagException(); + } + } + return contactDetails; + } + + private Boolean hasDuplicateField(String input, String saved) { return stringCleaner(saved).equals(stringCleaner(input)); } - public String stringCleaner(String input) { + private String stringCleaner(String input) { return input.replace(" ", "").toLowerCase(); } } From 1450fa05077ab39be6a7e339da7c118109e22076 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Thu, 21 Oct 2021 12:31:24 +0800 Subject: [PATCH 378/756] Refactor for boolean naming convention --- src/main/java/seedu/command/EditContactCommand.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index 323fe75426..c9eea46349 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -16,6 +16,7 @@ public class EditContactCommand extends Command { public static final int TELEGRAM_INDEX = 3; public static final int TWITTER_INDEX = 4; public static final int EMAIL_INDEX = 5; + public static final int NUMBER_OF_FIELDS = 6; String[] contactDetails; int contactIndex; @@ -28,8 +29,8 @@ public void execute() { try { Contact preEditContact = duplicateContact(contactList.getContactAtIndex(contactIndex)); Contact postEditContact = editTempContact(contactDetails,preEditContact); - if (duplicateCatcher(postEditContact, contactList, contactIndex)) { - TextUi.ignoreEditContact(); + if (hasDuplicates(postEditContact, contactList, contactIndex)) { + TextUi.ignoreContact("edit"); } else { contactList.editContact(contactDetails, contactIndex); TextUi.editContactMessage(postEditContact); @@ -98,16 +99,16 @@ public Contact duplicateContact(Contact contact) { return new Contact(name, github, linkedin, telegram, twitter, email); } - public Boolean duplicateField(String input, String saved) { + private Boolean hasDuplicateField(String input, String saved) { return stringCleaner(saved).equals(stringCleaner(input)); } - public String stringCleaner(String input) { + private String stringCleaner(String input) { return input.replace(" ", "").toLowerCase(); } - public Contact editTempContact(String[] contactDetails, Contact preEditContact) throws InvalidFlagException { + private Contact editTempContact(String[] contactDetails, Contact preEditContact) throws InvalidFlagException { Contact tempContact = duplicateContact(preEditContact); for (int i = 0; i < contactDetails.length; i++) { if (contactDetails[i] != null) { @@ -131,7 +132,6 @@ public Contact editTempContact(String[] contactDetails, Contact preEditContact) tempContact.setEmail(contactDetails[i]); break; default: - //control should never reach here assert false; throw new InvalidFlagException(); } From 95b1b3b99644bd2f0155bf3a9d3711eec3e2949c Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Thu, 21 Oct 2021 12:31:54 +0800 Subject: [PATCH 379/756] Implement extract contact details for edit --- .../seedu/command/EditContactCommand.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index c9eea46349..b4155ffcc4 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -139,4 +139,34 @@ private Contact editTempContact(String[] contactDetails, Contact preEditContact) } return tempContact; } + + private String[] extractContactDetails(Contact contact) throws InvalidFlagException { + String[] contactDetails = new String[NUMBER_OF_FIELDS]; + for (int i = 0; i < NUMBER_OF_FIELDS; i++) { + switch (i) { + case NAME_INDEX: + contactDetails[NAME_INDEX] = contact.getName(); + break; + case GITHUB_INDEX: + contactDetails[GITHUB_INDEX] = contact.getGithub(); + break; + case LINKEDIN_INDEX: + contactDetails[LINKEDIN_INDEX] = contact.getLinkedin(); + break; + case TELEGRAM_INDEX: + contactDetails[TELEGRAM_INDEX] = contact.getTelegram(); + break; + case TWITTER_INDEX: + contactDetails[TWITTER_INDEX] = contact.getTwitter(); + break; + case EMAIL_INDEX: + contactDetails[EMAIL_INDEX] = contact.getEmail(); + break; + default: + assert false; + throw new InvalidFlagException(); + } + } + return contactDetails; + } } From 6635e332ee8540c2f2bc1000f63116e6bfca5f81 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Thu, 21 Oct 2021 12:32:46 +0800 Subject: [PATCH 380/756] Refactor duplicate catcher for edit using string array --- .../seedu/command/EditContactCommand.java | 48 +++++-------------- 1 file changed, 13 insertions(+), 35 deletions(-) diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index b4155ffcc4..e120b3bb9b 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -40,56 +40,34 @@ public void execute() { } } - public Boolean duplicateCatcher(Contact postEditContact, ContactList contactList, int contactIndex) { + private Boolean hasDuplicates(Contact postEditContact, ContactList contactList, int contactIndex) + throws InvalidFlagException { ArrayList duplicatedIndex = new ArrayList<>(); + String[] postEditContactDetails = extractContactDetails(postEditContact); for (int i = 0; i < contactList.getListSize(); i++) { if (i == contactIndex) { continue; } - Contact currentContact = contactList.getContactAtIndex(i); - if (duplicateField(postEditContact.getName(), currentContact.getName())) { - duplicatedIndex.add(i); - continue; - } - if (postEditContact.getGithub() != null && currentContact.getGithub() != null) { - if (duplicateField(postEditContact.getGithub(), currentContact.getGithub())) { - duplicatedIndex.add(i); - continue; - } - } - if (postEditContact.getEmail() != null && currentContact.getEmail() != null) { - if (duplicateField(postEditContact.getEmail(), currentContact.getEmail())) { - duplicatedIndex.add(i); - continue; - } - } - if (postEditContact.getTelegram() != null && currentContact.getTelegram() != null) { - if (duplicateField(postEditContact.getTelegram(), currentContact.getTelegram())) { - duplicatedIndex.add(i); - continue; - } - } - if (postEditContact.getLinkedin() != null && currentContact.getLinkedin() != null) { - if (duplicateField(postEditContact.getLinkedin(), currentContact.getLinkedin())) { - duplicatedIndex.add(i); - continue; - } - } - if (postEditContact.getTwitter() != null && currentContact.getTwitter() != null) { - if (duplicateField(postEditContact.getTwitter(), currentContact.getTwitter())) { - duplicatedIndex.add(i); + String[] currentContactDetails = extractContactDetails(contactList.getContactAtIndex(i)); + for (int j = 0; j < NUMBER_OF_FIELDS; j++) { + if (postEditContactDetails[j] != null && currentContactDetails[j] != null) { + if (hasDuplicateField(postEditContactDetails[j], currentContactDetails[j])) { + duplicatedIndex.add(i); + break; + } } } + } if (!duplicatedIndex.isEmpty()) { - TextUi.confirmEditDuplicateMessage(duplicatedIndex, contactList); + TextUi.confirmDuplicateMessage(duplicatedIndex, contactList, "edit"); String userEditConfirmation = UserInputTextUi.getUserConfirmation(); return userEditConfirmation.equalsIgnoreCase("n"); } return false; } - public Contact duplicateContact(Contact contact) { + private Contact duplicateContact(Contact contact) { String name = contact.getName(); String github = contact.getGithub(); String linkedin = contact.getLinkedin(); From f1b94a594c4ef59ed2eb067f152827780e3bafea Mon Sep 17 00:00:00 2001 From: lezong Date: Thu, 21 Oct 2021 13:29:36 +0800 Subject: [PATCH 381/756] Refactor AddPersonalContactParser --- .../seedu/command/EditContactCommand.java | 10 +- src/main/java/seedu/contact/ContactList.java | 1 + .../java/seedu/contact/PersonalContact.java | 21 ++++ .../parser/AddPersonalContactParser.java | 118 ++++++++++++------ src/main/java/seedu/parser/ContactParser.java | 3 +- .../java/seedu/parser/EditContactParser.java | 9 +- src/main/java/seedu/parser/IndexParser.java | 8 +- src/main/java/seedu/ui/TextUi.java | 2 +- 8 files changed, 124 insertions(+), 48 deletions(-) create mode 100644 src/main/java/seedu/contact/PersonalContact.java diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index 6e74cf19bd..e02daf271a 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -15,10 +15,14 @@ public EditContactCommand(String[] contactDetails, int contactIndex) { public void execute() { try { - contactList.editContact(contactDetails, contactIndex); - TextUi.editContactMessage(contactList.getContactAtIndex(contactIndex)); + if (contactIndex == -1) { + contactList.editPersonalContact(contactDetails); + } else { + contactList.editContact(contactDetails, contactIndex); + TextUi.editContactMessage(contactList.getContactAtIndex(contactIndex)); + } } catch (IndexOutOfBoundsException | InvalidFlagException e) { - ExceptionTextUi.invalidIndexMessage(); + ExceptionTextUi.numOutOfRangeMessage(contactList.getListSize()); } } } diff --git a/src/main/java/seedu/contact/ContactList.java b/src/main/java/seedu/contact/ContactList.java index 9a1a0496cf..cadd37c113 100644 --- a/src/main/java/seedu/contact/ContactList.java +++ b/src/main/java/seedu/contact/ContactList.java @@ -57,6 +57,7 @@ public void editContact(String[] contactDetails, int contactIndex) throws Invali } } + public void deleteContact(int deletedIndex) { contacts.remove(deletedIndex); } diff --git a/src/main/java/seedu/contact/PersonalContact.java b/src/main/java/seedu/contact/PersonalContact.java new file mode 100644 index 0000000000..42881e00e0 --- /dev/null +++ b/src/main/java/seedu/contact/PersonalContact.java @@ -0,0 +1,21 @@ +package seedu.contact; + +import seedu.exception.InvalidGithubUsernameException; + +//should be interface? +public class PersonalContact extends Contact { + public PersonalContact(String name, String github, String linkedin, String telegram, String twitter, String email) { + super(name, github, linkedin, telegram, twitter, email); + } + + private boolean setGithubIfValid(String userInput, Contact personalContact) throws InvalidGithubUsernameException { + if (userInput.isEmpty() || userInput == null) { + return true; + } else { + checkGithubUsernameRegex(userInput); + this.setGithub(userInput); + return true; + } + } + +} diff --git a/src/main/java/seedu/parser/AddPersonalContactParser.java b/src/main/java/seedu/parser/AddPersonalContactParser.java index 22c45d8354..fdc0f34dcd 100644 --- a/src/main/java/seedu/parser/AddPersonalContactParser.java +++ b/src/main/java/seedu/parser/AddPersonalContactParser.java @@ -14,7 +14,6 @@ public class AddPersonalContactParser extends RegexParser { private Contact personalContact = new Contact(null, null,null,null, null,null); - private boolean isValidDetail = false; public AddPersonalContactParser() { TextUi.welcomeMessage(); @@ -29,13 +28,13 @@ public void startCollectingPersonalDetails() { parsePersonalTelegramUsername(); parsePersonalTwitterUsername(); parsePersonalEmailAddress(); - parsePersonalLinkedInUsername(); + parsePersonalLinkedinUsername(); TextUi.finishSetUpMessage(); } } private void parsePersonalName() { - isValidDetail = false; + boolean isValidDetail = false; do { try { String personalName = UserInputTextUi.getUserInput(); @@ -50,120 +49,161 @@ private void parsePersonalName() { } private void parsePersonalGithubUsername() { - isValidDetail = false; + boolean isValidDetail = false; TextUi.promptPersonalGithubUsernameMessage(this.personalContact.getName()); do { try { String personalGithubUsername = UserInputTextUi.getUserInput(); - setGithubIfValid(personalGithubUsername); + isValidDetail = checkGithubValidity(personalGithubUsername); + setGithubUsername(personalGithubUsername); } catch (InvalidGithubUsernameException e) { ExceptionTextUi.invalidPersonalGithubUsernameErrorMessage(); } } while (!isValidDetail); } - private void setGithubIfValid(String userInput) throws InvalidGithubUsernameException { + private boolean checkGithubValidity(String userInput) throws InvalidGithubUsernameException { if (userInput.isEmpty() || userInput == null) { - isValidDetail = true; + return true; + } + // if exception is thrown in there, it will not return true, so isValidDetail will remain false + checkGithubUsernameRegex(userInput); + return true; + } + + private void setGithubUsername(String userInput) { + if (userInput.isEmpty() || userInput == null) { + this.personalContact.setGithub(null); } else { - checkGithubUsernameRegex(userInput); - isValidDetail = true; this.personalContact.setGithub(userInput); } } private void parsePersonalTelegramUsername() { - isValidDetail = false; + boolean isValidDetail = false; TextUi.promptPersonalTelegramUsernameMessage(); do { try { - String personalTelegram = UserInputTextUi.getUserInput(); - setTelegramIfValid(personalTelegram); + String personalTelegramUsername = UserInputTextUi.getUserInput(); + isValidDetail = checkTelegramValidity(personalTelegramUsername); + setTelegramUsername(personalTelegramUsername); } catch (InvalidTelegramUsernameException e) { ExceptionTextUi.invalidPersonalTelegramUsernameErrorMessage(); } } while (!isValidDetail); } - private void setTelegramIfValid(String userInput) throws InvalidTelegramUsernameException { + private boolean checkTelegramValidity(String userInput) throws InvalidTelegramUsernameException { if (userInput.isEmpty() || userInput == null) { - isValidDetail = true; + return true; + } + // if exception is thrown in there, it will not return true, so isValidDetail will remain false + checkTelegramUsernameRegex(userInput); + return true; + } + + private void setTelegramUsername(String userInput) { + if (userInput.isEmpty() || userInput == null) { + this.personalContact.setTelegram(null); } else { - checkTelegramUsernameRegex(userInput); - isValidDetail = true; this.personalContact.setTelegram(userInput); } } private void parsePersonalTwitterUsername() { - isValidDetail = false; + boolean isValidDetail = false; TextUi.promptPersonalTwitterUsernameMessage(); do { try { - String personalTwitter = UserInputTextUi.getUserInput(); - setTwitterIfValid(personalTwitter); + String personalTwitterUsername = UserInputTextUi.getUserInput(); + isValidDetail = checkTwitterValidity(personalTwitterUsername); + setTwitterUsername(personalTwitterUsername); } catch (InvalidTwitterUsernameException e) { ExceptionTextUi.invalidPersonalTwitterUsernameErrorMessage(); } } while (!isValidDetail); } - private void setTwitterIfValid(String userInput) throws InvalidTwitterUsernameException { + private boolean checkTwitterValidity(String userInput) throws InvalidTwitterUsernameException { if (userInput.isEmpty() || userInput == null) { - isValidDetail = true; + return true; + } + // if exception is thrown in there, it will not return true, so isValidDetail will remain false + checkTwitterUsernameRegex(userInput); + return true; + } + + private void setTwitterUsername(String userInput) { + if (userInput.isEmpty() || userInput == null) { + this.personalContact.setTwitter(null); } else { - checkTwitterUsernameRegex(userInput); - isValidDetail = true; this.personalContact.setTwitter(userInput); } } private void parsePersonalEmailAddress() { - isValidDetail = false; + boolean isValidDetail = false; TextUi.promptPersonalEmailMessage(); do { try { - String personalEmail = UserInputTextUi.getUserInput(); - setEmailIfValid(personalEmail); + String personalEmailAddress = UserInputTextUi.getUserInput(); + isValidDetail = checkEmailValidity(personalEmailAddress); + setEmailAddress(personalEmailAddress); } catch (InvalidEmailException e) { ExceptionTextUi.invalidPersonalEmailErrorMessage(); } } while (!isValidDetail); } - private void setEmailIfValid(String userInput) throws InvalidEmailException { + private boolean checkEmailValidity(String userInput) throws InvalidEmailException { + if (userInput.isEmpty() || userInput == null) { + return true; + } + // if exception is thrown in there, it will not return true, so isValidDetail will remain false + checkEmailRegex(userInput); + return true; + } + + private void setEmailAddress(String userInput) { if (userInput.isEmpty() || userInput == null) { - isValidDetail = true; + this.personalContact.setEmail(null); } else { - checkEmailRegex(userInput); - isValidDetail = true; this.personalContact.setEmail(userInput); } } - private void parsePersonalLinkedInUsername() { - isValidDetail = false; - TextUi.promptPersonalLinkedInUsernameMessage(); + private void parsePersonalLinkedinUsername() { + boolean isValidDetail = false; + TextUi.promptPersonalLinkedinUsernameMessage(); do { try { - String personalLinkedIn = UserInputTextUi.getUserInput(); - setLinkedInIfValid(personalLinkedIn); + String personalLinkedinUsername = UserInputTextUi.getUserInput(); + isValidDetail = checkLinkedinValidity(personalLinkedinUsername); + setLinkedinUsername(personalLinkedinUsername); } catch (InvalidLinkedinUsernameException e) { ExceptionTextUi.invalidPersonalLinkedinUsernameErrorMessage(); } } while (!isValidDetail); } - private void setLinkedInIfValid(String userInput) throws InvalidLinkedinUsernameException { + private boolean checkLinkedinValidity(String userInput) throws InvalidLinkedinUsernameException { if (userInput.isEmpty() || userInput == null) { - isValidDetail = true; + return true; + } + // if exception is thrown in there, it will not return true, so isValidDetail will remain false + checkLinkedinUsernameRegex(userInput); + return true; + } + + private void setLinkedinUsername(String userInput) { + if (userInput.isEmpty() || userInput == null) { + this.personalContact.setLinkedin(null); } else { - checkLinkedinUsernameRegex(userInput); - isValidDetail = true; this.personalContact.setLinkedin(userInput); } } + public Contact getPersonalContact() { return personalContact; } diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index 48ed4c22c4..6530b37d23 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -62,9 +62,8 @@ public void parseDetail(String[] contactDetails, String detail) if (detailToStore.equals("null")) { throw new ForbiddenDetailException(); } - int indexToStore; checkRegex(flag, detailToStore); - indexToStore = getIndexToStore(flag); + int indexToStore = getIndexToStore(flag); contactDetails[indexToStore] = detailToStore; } } diff --git a/src/main/java/seedu/parser/EditContactParser.java b/src/main/java/seedu/parser/EditContactParser.java index 034204dfd7..eab541d548 100644 --- a/src/main/java/seedu/parser/EditContactParser.java +++ b/src/main/java/seedu/parser/EditContactParser.java @@ -18,13 +18,15 @@ public String[] parseContactDetails(String userInput) throws InvalidFlagException, MissingDetailException, MissingArgException, ForbiddenDetailException, InvalidNameException, InvalidGithubUsernameException, InvalidTelegramUsernameException, InvalidLinkedinUsernameException, InvalidTwitterUsernameException, InvalidEmailException { + String[] inputDetails = userInput.split(" ", NUMBER_OF_EDIT_ARGS); if (inputDetails.length < NUMBER_OF_EDIT_ARGS) { //if arguments are missing e.g. edit 2 throw new MissingArgException(); } + assert (inputDetails.length == NUMBER_OF_EDIT_ARGS); - String[] contactDetails = new String[NUMBER_OF_FIELDS]; //initialise null array of strings + //buffer is used to ensure first flag can be read String[] destructuredInputs = (BUFFER + inputDetails[USER_INFO_INDEX]).split(DETAIL_SEPARATOR); //handles illegal input "edit 0 -" and "edit 0 [invalid string]" @@ -32,10 +34,13 @@ public String[] parseContactDetails(String userInput) if (destructuredInputs.length < 2) { throw new MissingArgException(); } + + //initialise null array of strings + String[] contactDetails = new String[NUMBER_OF_FIELDS]; for (int i = CONTACT_PARAMS_START_INDEX; i < destructuredInputs.length; i++) { parseDetail(contactDetails, destructuredInputs[i]); } + return contactDetails; } - } diff --git a/src/main/java/seedu/parser/IndexParser.java b/src/main/java/seedu/parser/IndexParser.java index 660576cab9..bfca60cd65 100644 --- a/src/main/java/seedu/parser/IndexParser.java +++ b/src/main/java/seedu/parser/IndexParser.java @@ -22,8 +22,14 @@ public static int getIndexFromInput(String userInput) assert destructuredInputs.length == 2; // split index string into words String[] indexSplit = destructuredInputs[INDEX_POSITION].trim().split(" "); + // contact index that is important and what we want + // can be "me" or an integer + String significantIndex = indexSplit[SIGNIFICANT_INDEX_POSITION].trim(); + if (significantIndex.equalsIgnoreCase("me")) { + return -1; + } // takes only the first word/ element as given user input, and throws NumberFormatExcept if it is not integer - return Integer.parseInt(indexSplit[SIGNIFICANT_INDEX_POSITION].trim()); + return Integer.parseInt(significantIndex); } public static Contact getContactFromIndex(int index, ContactList contactList) throws IndexOutOfBoundsException { diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 2f37f4819c..215256efc4 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -92,7 +92,7 @@ public static void promptPersonalEmailMessage() { System.out.print("Email Address: "); } - public static void promptPersonalLinkedInUsernameMessage() { + public static void promptPersonalLinkedinUsernameMessage() { String message = "Please provide us with your LinkedIn Username\n" + "or press ENTER if you would like to skip."; printDoubleLineMessage(message); From 051368c2bc183beb9f42c4fd0219f4d732c64cb1 Mon Sep 17 00:00:00 2001 From: lezong Date: Thu, 21 Oct 2021 13:46:20 +0800 Subject: [PATCH 382/756] Add PersonalContact class that inherits from Contact --- src/main/java/seedu/command/Command.java | 6 +-- .../seedu/command/EditContactCommand.java | 3 +- .../java/seedu/contact/PersonalContact.java | 46 +++++++++++++++---- src/main/java/seedu/duke/Duke.java | 3 +- .../parser/AddPersonalContactParser.java | 5 +- .../java/seedu/storage/ContactsDecoder.java | 11 +++-- src/main/java/seedu/storage/Storage.java | 7 +-- src/main/java/seedu/ui/TextUi.java | 14 ++++-- 8 files changed, 69 insertions(+), 26 deletions(-) diff --git a/src/main/java/seedu/command/Command.java b/src/main/java/seedu/command/Command.java index 185e6191ce..c5be696e04 100644 --- a/src/main/java/seedu/command/Command.java +++ b/src/main/java/seedu/command/Command.java @@ -1,17 +1,17 @@ package seedu.command; -import seedu.contact.Contact; import seedu.contact.ContactList; +import seedu.contact.PersonalContact; public abstract class Command { protected ContactList contactList; - protected Contact personalContact; + protected PersonalContact personalContact; public void setContactList(ContactList contactList) { this.contactList = contactList; } - public void setPersonalContact(Contact personalContact) { + public void setPersonalContact(PersonalContact personalContact) { this.personalContact = personalContact; } diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index e02daf271a..3e824ae64c 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -16,7 +16,8 @@ public EditContactCommand(String[] contactDetails, int contactIndex) { public void execute() { try { if (contactIndex == -1) { - contactList.editPersonalContact(contactDetails); + personalContact.editPersonalContact(contactDetails); + TextUi.editPersonalContactMessage(personalContact); } else { contactList.editContact(contactDetails, contactIndex); TextUi.editContactMessage(contactList.getContactAtIndex(contactIndex)); diff --git a/src/main/java/seedu/contact/PersonalContact.java b/src/main/java/seedu/contact/PersonalContact.java index 42881e00e0..af3abf8787 100644 --- a/src/main/java/seedu/contact/PersonalContact.java +++ b/src/main/java/seedu/contact/PersonalContact.java @@ -1,21 +1,51 @@ package seedu.contact; -import seedu.exception.InvalidGithubUsernameException; +import seedu.exception.InvalidFlagException; //should be interface? public class PersonalContact extends Contact { + public static final int NAME_INDEX = 0; + public static final int GITHUB_INDEX = 1; + public static final int LINKEDIN_INDEX = 2; + public static final int TELEGRAM_INDEX = 3; + public static final int TWITTER_INDEX = 4; + public static final int EMAIL_INDEX = 5; + public PersonalContact(String name, String github, String linkedin, String telegram, String twitter, String email) { super(name, github, linkedin, telegram, twitter, email); } - private boolean setGithubIfValid(String userInput, Contact personalContact) throws InvalidGithubUsernameException { - if (userInput.isEmpty() || userInput == null) { - return true; - } else { - checkGithubUsernameRegex(userInput); - this.setGithub(userInput); - return true; + public void editPersonalContact(String[] contactDetails) { + for (int i = 0; i < contactDetails.length; i++) { + if (contactDetails[i] != null) { + switch (i) { + case NAME_INDEX: + setName(contactDetails[i]); + break; + case GITHUB_INDEX: + setGithub(contactDetails[i]); + break; + case LINKEDIN_INDEX: + setLinkedin(contactDetails[i]); + break; + case TELEGRAM_INDEX: + setTelegram(contactDetails[i]); + break; + case TWITTER_INDEX: + setTwitter(contactDetails[i]); + break; + case EMAIL_INDEX: + setEmail(contactDetails[i]); + break; + default: + //control should never reach here + assert false; + break; + } + } } } + + } diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 9993950d1e..7b920b48f1 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -3,6 +3,7 @@ import seedu.command.Command; import seedu.contact.Contact; import seedu.contact.ContactList; +import seedu.contact.PersonalContact; import seedu.exception.FileErrorException; import seedu.parser.MainParser; import seedu.storage.ContactsEncoder; @@ -16,7 +17,7 @@ public class Duke { private MainParser parser; private ContactList contactList; private String personalContactFilePath; - private Contact personalContact; + private PersonalContact personalContact; public Duke(String contactFilePath, String personalContactFilePath) { this.contactFilePath = contactFilePath; diff --git a/src/main/java/seedu/parser/AddPersonalContactParser.java b/src/main/java/seedu/parser/AddPersonalContactParser.java index fdc0f34dcd..f1fa440c9d 100644 --- a/src/main/java/seedu/parser/AddPersonalContactParser.java +++ b/src/main/java/seedu/parser/AddPersonalContactParser.java @@ -1,6 +1,7 @@ package seedu.parser; import seedu.contact.Contact; +import seedu.contact.PersonalContact; import seedu.exception.InvalidGithubUsernameException; import seedu.exception.InvalidNameException; import seedu.exception.InvalidTelegramUsernameException; @@ -12,7 +13,7 @@ import seedu.ui.UserInputTextUi; public class AddPersonalContactParser extends RegexParser { - private Contact personalContact = new Contact(null, null,null,null, + private PersonalContact personalContact = new PersonalContact(null, null,null,null, null,null); public AddPersonalContactParser() { @@ -204,7 +205,7 @@ private void setLinkedinUsername(String userInput) { } - public Contact getPersonalContact() { + public PersonalContact getPersonalContact() { return personalContact; } } \ No newline at end of file diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index fb1072904d..7d595692a5 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -3,6 +3,7 @@ import seedu.contact.Contact; import seedu.contact.ContactList; import seedu.contact.DetailType; +import seedu.contact.PersonalContact; import seedu.exception.FileErrorException; import seedu.ui.ExceptionTextUi; @@ -28,8 +29,8 @@ public static ContactList readContacts(File contactFile) throws FileErrorExcepti return updatedContactList; } - public static Contact readPersonalContact(File personalContactFile) throws FileErrorException { - Contact personalContact = new Contact(null, null, null, null, null, null); + public static PersonalContact readPersonalContact(File personalContactFile) throws FileErrorException { + PersonalContact personalContact = new PersonalContact(null, null, null, null, null, null); try { Scanner fileScanner = new Scanner(personalContactFile); if (fileScanner.hasNext()) { @@ -43,8 +44,8 @@ public static Contact readPersonalContact(File personalContactFile) throws FileE } - private static Contact decodePersonalContact(Contact contact, String contactText) { - Contact personalContact = contact; + private static PersonalContact decodePersonalContact(PersonalContact contact, String contactText) { + PersonalContact personalContact = contact; try { String[] compiledDetails = decodeDetails(contactText); String contactName = compiledDetails[DetailType.NAME.getIndex()]; @@ -53,7 +54,7 @@ private static Contact decodePersonalContact(Contact contact, String contactText String contactTelegram = compiledDetails[DetailType.TELEGRAM.getIndex()]; String contactTwitter = compiledDetails[DetailType.TWITTER.getIndex()]; String contactEmail = compiledDetails[DetailType.EMAIL.getIndex()]; - personalContact = new Contact(contactName, contactGithub, contactLinkedin, contactTelegram, + personalContact = new PersonalContact(contactName, contactGithub, contactLinkedin, contactTelegram, contactTwitter, contactEmail); } catch (IndexOutOfBoundsException e) { ExceptionTextUi.corruptLineMessage(contactText); diff --git a/src/main/java/seedu/storage/Storage.java b/src/main/java/seedu/storage/Storage.java index 1260f8aa5c..b3342a60df 100644 --- a/src/main/java/seedu/storage/Storage.java +++ b/src/main/java/seedu/storage/Storage.java @@ -2,6 +2,7 @@ import seedu.contact.Contact; import seedu.contact.ContactList; +import seedu.contact.PersonalContact; import seedu.exception.FileErrorException; import seedu.parser.AddPersonalContactParser; import seedu.ui.TextUi; @@ -74,17 +75,17 @@ public ContactList loadExistingContacts() throws FileErrorException { return ContactsDecoder.readContacts(contactFile); } - public Contact loadExistingPersonalContact() throws FileErrorException { + public PersonalContact loadExistingPersonalContact() throws FileErrorException { if (!hasExistingPersonalContactFile() || hasEmptyExistingPersonalContactFile()) { isFirstRun = true; // get new contact's name AddPersonalContactParser addPersonalContactParser = new AddPersonalContactParser(); addPersonalContactParser.startCollectingPersonalDetails(); - Contact personalContact = addPersonalContactParser.getPersonalContact(); + PersonalContact personalContact = addPersonalContactParser.getPersonalContact(); ContactsEncoder.savePersonalContact(personalContactFilePath, personalContact); return personalContact; } - Contact personalContact = ContactsDecoder.readPersonalContact(personalContactFile); + PersonalContact personalContact = ContactsDecoder.readPersonalContact(personalContactFile); TextUi.welcomeBackMessage(personalContact); return personalContact; } diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 215256efc4..ec5615164c 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -1,6 +1,7 @@ package seedu.ui; import seedu.contact.Contact; +import seedu.contact.PersonalContact; import java.util.Scanner; @@ -39,14 +40,14 @@ public static void welcomeMessage() { System.out.print("Name: "); } - public static void welcomeBackMessage(Contact personalContact) { + public static void welcomeBackMessage(PersonalContact personalContact) { printDoubleLineMessage(LOGO); String message = "Hello, " + personalContact.getName() + ". \nWelcome back to ConTech, " + "your personal contact tracker."; printBottomLineMessage(message); } - public static void greetingMessage(Contact personalContact) { + public static void greetingMessage(PersonalContact personalContact) { String message = "Hello there, " + personalContact.getName() + ".\n\n" + "This is ConTech, your very own contact tracking application\n" + "to manage tech-related contacts, like GitHub Accounts or\n" @@ -161,12 +162,19 @@ public static void searchNoResultsFoundMessage() { printDoubleLineMessage(message); } - public static void viewPersonalContactMessage(Contact personalContact) { + public static void viewPersonalContactMessage(PersonalContact personalContact) { String personalName = ViewMessageFormatterUi.viewNameFormatter(personalContact); String message = "Name: " + personalName + formatContactFields(personalContact); printDoubleLineMessage(message); } + public static void editPersonalContactMessage(PersonalContact personalContact) { + String message = "ConTech has edited your personal contact:\n" + + "Name: " + personalContact.getName() + + formatContactFields(personalContact); + printDoubleLineMessage(message); + } + public static void confirmDeleteMessage(Contact deletedContact, int deletedIndex) { String message = "Delete this contact? (y/n)\n" + deletedIndex + ". " + deletedContact.getName() + formatContactFields(deletedContact); From c6fe2356fb6eb5f4d34f6255683763c313a1d917 Mon Sep 17 00:00:00 2001 From: lezong Date: Thu, 21 Oct 2021 13:52:00 +0800 Subject: [PATCH 383/756] Added editPersonalContact which lets you edit personal contact --- src/main/java/seedu/contact/ContactList.java | 1 - src/main/java/seedu/contact/PersonalContact.java | 5 ----- 2 files changed, 6 deletions(-) diff --git a/src/main/java/seedu/contact/ContactList.java b/src/main/java/seedu/contact/ContactList.java index cadd37c113..9a1a0496cf 100644 --- a/src/main/java/seedu/contact/ContactList.java +++ b/src/main/java/seedu/contact/ContactList.java @@ -57,7 +57,6 @@ public void editContact(String[] contactDetails, int contactIndex) throws Invali } } - public void deleteContact(int deletedIndex) { contacts.remove(deletedIndex); } diff --git a/src/main/java/seedu/contact/PersonalContact.java b/src/main/java/seedu/contact/PersonalContact.java index af3abf8787..1984e9dcbd 100644 --- a/src/main/java/seedu/contact/PersonalContact.java +++ b/src/main/java/seedu/contact/PersonalContact.java @@ -1,8 +1,5 @@ package seedu.contact; -import seedu.exception.InvalidFlagException; - -//should be interface? public class PersonalContact extends Contact { public static final int NAME_INDEX = 0; public static final int GITHUB_INDEX = 1; @@ -46,6 +43,4 @@ public void editPersonalContact(String[] contactDetails) { } } - - } From 9a030a78040d8c6e661f58a4af6c98faa6d3cfd6 Mon Sep 17 00:00:00 2001 From: lezong Date: Thu, 21 Oct 2021 14:16:26 +0800 Subject: [PATCH 384/756] Minor edits to AddPersonalContactParser and include execution for editing personalContact --- .../parser/AddPersonalContactParser.java | 30 +++++++++---------- src/main/java/seedu/storage/Storage.java | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/main/java/seedu/parser/AddPersonalContactParser.java b/src/main/java/seedu/parser/AddPersonalContactParser.java index f1fa440c9d..593e576657 100644 --- a/src/main/java/seedu/parser/AddPersonalContactParser.java +++ b/src/main/java/seedu/parser/AddPersonalContactParser.java @@ -13,14 +13,15 @@ import seedu.ui.UserInputTextUi; public class AddPersonalContactParser extends RegexParser { - private PersonalContact personalContact = new PersonalContact(null, null,null,null, - null,null); + private PersonalContact personalContact; public AddPersonalContactParser() { - TextUi.welcomeMessage(); + personalContact = new PersonalContact(null, null,null,null, + null,null); } - public void startCollectingPersonalDetails() { + public void collectPersonalDetails() { + TextUi.welcomeMessage(); parsePersonalName(); TextUi.greetingMessage(personalContact); String userConfirmation = UserInputTextUi.getUserConfirmation(); @@ -56,7 +57,7 @@ private void parsePersonalGithubUsername() { try { String personalGithubUsername = UserInputTextUi.getUserInput(); isValidDetail = checkGithubValidity(personalGithubUsername); - setGithubUsername(personalGithubUsername); + setParsedGithubUsername(personalGithubUsername); } catch (InvalidGithubUsernameException e) { ExceptionTextUi.invalidPersonalGithubUsernameErrorMessage(); } @@ -72,7 +73,7 @@ private boolean checkGithubValidity(String userInput) throws InvalidGithubUserna return true; } - private void setGithubUsername(String userInput) { + private void setParsedGithubUsername(String userInput) { if (userInput.isEmpty() || userInput == null) { this.personalContact.setGithub(null); } else { @@ -87,7 +88,7 @@ private void parsePersonalTelegramUsername() { try { String personalTelegramUsername = UserInputTextUi.getUserInput(); isValidDetail = checkTelegramValidity(personalTelegramUsername); - setTelegramUsername(personalTelegramUsername); + setParsedTelegramUsername(personalTelegramUsername); } catch (InvalidTelegramUsernameException e) { ExceptionTextUi.invalidPersonalTelegramUsernameErrorMessage(); } @@ -103,7 +104,7 @@ private boolean checkTelegramValidity(String userInput) throws InvalidTelegramUs return true; } - private void setTelegramUsername(String userInput) { + private void setParsedTelegramUsername(String userInput) { if (userInput.isEmpty() || userInput == null) { this.personalContact.setTelegram(null); } else { @@ -118,7 +119,7 @@ private void parsePersonalTwitterUsername() { try { String personalTwitterUsername = UserInputTextUi.getUserInput(); isValidDetail = checkTwitterValidity(personalTwitterUsername); - setTwitterUsername(personalTwitterUsername); + setParsedTwitterUsername(personalTwitterUsername); } catch (InvalidTwitterUsernameException e) { ExceptionTextUi.invalidPersonalTwitterUsernameErrorMessage(); } @@ -134,7 +135,7 @@ private boolean checkTwitterValidity(String userInput) throws InvalidTwitterUser return true; } - private void setTwitterUsername(String userInput) { + private void setParsedTwitterUsername(String userInput) { if (userInput.isEmpty() || userInput == null) { this.personalContact.setTwitter(null); } else { @@ -149,7 +150,7 @@ private void parsePersonalEmailAddress() { try { String personalEmailAddress = UserInputTextUi.getUserInput(); isValidDetail = checkEmailValidity(personalEmailAddress); - setEmailAddress(personalEmailAddress); + setParsedEmailAddress(personalEmailAddress); } catch (InvalidEmailException e) { ExceptionTextUi.invalidPersonalEmailErrorMessage(); } @@ -165,7 +166,7 @@ private boolean checkEmailValidity(String userInput) throws InvalidEmailExceptio return true; } - private void setEmailAddress(String userInput) { + private void setParsedEmailAddress(String userInput) { if (userInput.isEmpty() || userInput == null) { this.personalContact.setEmail(null); } else { @@ -180,7 +181,7 @@ private void parsePersonalLinkedinUsername() { try { String personalLinkedinUsername = UserInputTextUi.getUserInput(); isValidDetail = checkLinkedinValidity(personalLinkedinUsername); - setLinkedinUsername(personalLinkedinUsername); + setParsedLinkedinUsername(personalLinkedinUsername); } catch (InvalidLinkedinUsernameException e) { ExceptionTextUi.invalidPersonalLinkedinUsernameErrorMessage(); } @@ -196,7 +197,7 @@ private boolean checkLinkedinValidity(String userInput) throws InvalidLinkedinUs return true; } - private void setLinkedinUsername(String userInput) { + private void setParsedLinkedinUsername(String userInput) { if (userInput.isEmpty() || userInput == null) { this.personalContact.setLinkedin(null); } else { @@ -204,7 +205,6 @@ private void setLinkedinUsername(String userInput) { } } - public PersonalContact getPersonalContact() { return personalContact; } diff --git a/src/main/java/seedu/storage/Storage.java b/src/main/java/seedu/storage/Storage.java index b3342a60df..ae4cbd21f0 100644 --- a/src/main/java/seedu/storage/Storage.java +++ b/src/main/java/seedu/storage/Storage.java @@ -80,7 +80,7 @@ public PersonalContact loadExistingPersonalContact() throws FileErrorException { isFirstRun = true; // get new contact's name AddPersonalContactParser addPersonalContactParser = new AddPersonalContactParser(); - addPersonalContactParser.startCollectingPersonalDetails(); + addPersonalContactParser.collectPersonalDetails(); PersonalContact personalContact = addPersonalContactParser.getPersonalContact(); ContactsEncoder.savePersonalContact(personalContactFilePath, personalContact); return personalContact; From 2b00b95f7f182e8acc146394465ec62a4587b7ad Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 21 Oct 2021 17:11:34 +0800 Subject: [PATCH 385/756] Update gitignore to retain import file to be used in testing and programming --- .gitignore | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 4ae120efc6..d04b9c5c84 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,8 @@ src/main/resources/docs/ bin/ -/data -# ensure that no existing data exists on remote, so that runtest.sh is always on fresh build -/text-ui-test/data/ +/data/contacts.txt +/data/me.txt +# ensure that no existing contact data exists on remote, so that runtest.sh is always on fresh build +/text-ui-test/data/contacts.txt +/text-ui-test/data/me.txt From 7ebff560ef16a4786202685a96161298c6055246 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 21 Oct 2021 17:11:48 +0800 Subject: [PATCH 386/756] Create general import data dump --- data/import.txt | 5 +++++ text-ui-test/data/import.txt | 5 +++++ 2 files changed, 10 insertions(+) create mode 100644 data/import.txt create mode 100644 text-ui-test/data/import.txt diff --git a/data/import.txt b/data/import.txt new file mode 100644 index 0000000000..45cc5b79ec --- /dev/null +++ b/data/import.txt @@ -0,0 +1,5 @@ +ashraf,ashrafjfr,null,null,null,null +lezai,lezongmun,null,null,null,null +andre,null +marcus,null,null,null,null,null +badgithub,@@github,null,null,null,null \ No newline at end of file diff --git a/text-ui-test/data/import.txt b/text-ui-test/data/import.txt new file mode 100644 index 0000000000..45cc5b79ec --- /dev/null +++ b/text-ui-test/data/import.txt @@ -0,0 +1,5 @@ +ashraf,ashrafjfr,null,null,null,null +lezai,lezongmun,null,null,null,null +andre,null +marcus,null,null,null,null,null +badgithub,@@github,null,null,null,null \ No newline at end of file From 98a20c7b6c1c107f9ffdb4cda93c2d8336da0e0e Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 21 Oct 2021 17:12:59 +0800 Subject: [PATCH 387/756] Change ContactsEncoder to non static class requiring instantiation --- src/main/java/seedu/storage/ContactsEncoder.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/storage/ContactsEncoder.java b/src/main/java/seedu/storage/ContactsEncoder.java index 9e0c707973..90e9ce7b39 100644 --- a/src/main/java/seedu/storage/ContactsEncoder.java +++ b/src/main/java/seedu/storage/ContactsEncoder.java @@ -10,7 +10,7 @@ import static seedu.storage.Storage.SEPARATOR; public class ContactsEncoder { - public static void savePersonalContact(String contactFilePath, Contact personalContact) throws FileErrorException { + public void savePersonalContact(String contactFilePath, Contact personalContact) throws FileErrorException { try { FileWriter fileWriter = new FileWriter(contactFilePath); String encodedContact = encodeContact(personalContact); @@ -21,7 +21,7 @@ public static void savePersonalContact(String contactFilePath, Contact personalC } } - public static void saveContacts(String contactFilePath, ContactList contactList) throws FileErrorException { + public void saveContacts(String contactFilePath, ContactList contactList) throws FileErrorException { try { FileWriter fileWriter = new FileWriter(contactFilePath); for (int i = 0; i < contactList.getListSize(); i++) { @@ -35,7 +35,7 @@ public static void saveContacts(String contactFilePath, ContactList contactList) } } - private static String encodeContact(Contact contact) { + private String encodeContact(Contact contact) { String stringifiedContact = contact.getName() + SEPARATOR + contact.getGithub() + SEPARATOR + contact.getLinkedin() + SEPARATOR + contact.getTelegram() + SEPARATOR + contact.getTwitter() + SEPARATOR + contact.getEmail() + "\n"; From d9edd8230e6da14ba3996e3f2c9206f287178002 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 21 Oct 2021 17:13:56 +0800 Subject: [PATCH 388/756] Change ContactsDecoder to non static class requiring instantiation --- src/main/java/seedu/storage/ContactsDecoder.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index 115ec4ca0d..33f5a71402 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -14,7 +14,6 @@ import java.util.Scanner; public class ContactsDecoder { - public static ContactList readContacts(File contactFile) throws FileErrorException { ContactList updatedContactList = new ContactList(); try { Scanner fileScanner = new Scanner(contactFile); @@ -28,7 +27,7 @@ public static ContactList readContacts(File contactFile) throws FileErrorExcepti return updatedContactList; } - public static Contact readPersonalContact(File personalContactFile) throws FileErrorException { + public Contact readPersonalContact(File personalContactFile) throws FileErrorException { Contact personalContact = new Contact(null, null, null, null, null, null); try { Scanner fileScanner = new Scanner(personalContactFile); @@ -43,7 +42,7 @@ public static Contact readPersonalContact(File personalContactFile) throws FileE } - private static Contact decodePersonalContact(String contactText, Contact contact) { + private Contact decodePersonalContact(String contactText, Contact contact) { String[] destructuredInputs = contactText.split(SEPARATOR); Contact personalContact = contact; try { @@ -61,7 +60,7 @@ private static Contact decodePersonalContact(String contactText, Contact contact return personalContact; } - private static void decodeContact(ContactList contactList, String contactText) { + private void decodeContact(ContactList contactList, String contactText, int lineIndex, String contactFilePath) { // Add the decoded details into the contact list try { String[] compiledDetails = decodeDetails(contactText); @@ -79,7 +78,6 @@ private static void decodeContact(ContactList contactList, String contactText) { } } - private static String[] decodeDetails(String contactText) throws IndexOutOfBoundsException { String[] destructuredInputs = contactText.split(SEPARATOR); String[] compiledDetails = new String[NUMBER_OF_FIELDS]; for (int i = 0; i < NUMBER_OF_FIELDS; i++) { From 3fdccc16baa6526050a9b41744ffc258ea214956 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 21 Oct 2021 17:14:30 +0800 Subject: [PATCH 389/756] Update MainParser to include import command --- src/main/java/seedu/parser/MainParser.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 0659681a8d..cb353b120a 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -5,6 +5,7 @@ import seedu.command.DeleteContactCommand; import seedu.command.Command; import seedu.command.HelpCommand; +import seedu.command.ImportContactCommand; import seedu.command.InvalidDetailCommand; import seedu.command.ViewContactCommand; import seedu.command.FailedCommand; @@ -35,6 +36,7 @@ public class MainParser { private static final String LIST_COMD = "list"; private static final String HELP_COMD = "help"; private static final String SEARCH_COMD = "search"; + private static final String IMPORT_COMD = "import"; private static final int COMD_WORD_INDEX = 0; private static final int ISOLATE_COMD_WORD = 2; @@ -73,6 +75,9 @@ public Command parseCommand(String userInput) { case SEARCH_COMD: command = parseSearchCommand(userInput); break; + case IMPORT_COMD: + command = new ImportContactCommand(); + break; default: command = new FailedCommand(FailedCommandType.GENERAL); } From e1e9afd5b703fea68570ab09bc9790d0f8f5d932 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 21 Oct 2021 17:14:47 +0800 Subject: [PATCH 390/756] Implement FLAG_SEQUENCE in regex parser for import purposes --- src/main/java/seedu/parser/RegexParser.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/parser/RegexParser.java b/src/main/java/seedu/parser/RegexParser.java index 07e4efe976..31fae56071 100644 --- a/src/main/java/seedu/parser/RegexParser.java +++ b/src/main/java/seedu/parser/RegexParser.java @@ -13,14 +13,15 @@ import java.util.logging.Logger; public abstract class RegexParser { - public static final String NAME_FLAG = "n"; public static final String GITHUB_FLAG = "g"; + public static final String LINKEDIN_FLAG = "l"; public static final String TELEGRAM_FLAG = "te"; public static final String TWITTER_FLAG = "tw"; public static final String EMAIL_FLAG = "e"; - public static final String LINKEDIN_FLAG = "l"; + protected static final String[] FLAG_SEQUENCE = {NAME_FLAG, GITHUB_FLAG, LINKEDIN_FLAG, + TELEGRAM_FLAG, TWITTER_FLAG, EMAIL_FLAG}; private static final Logger LOGGER = Logger.getLogger(RegexParser.class.getName()); public void checkRegex(String flag, String detailToParse) From 19d6d371343d3f7e7baa26bf7098521b612b96ce Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 21 Oct 2021 17:15:09 +0800 Subject: [PATCH 391/756] Update Duke.java to include instantiation code for contact encoder and decoder --- src/main/java/seedu/duke/Duke.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 00be8a1467..4511159b6b 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -5,6 +5,7 @@ import seedu.contact.ContactList; import seedu.exception.FileErrorException; import seedu.parser.MainParser; +import seedu.storage.ContactsDecoder; import seedu.storage.ContactsEncoder; import seedu.storage.Storage; import seedu.ui.TextUi; @@ -18,12 +19,16 @@ public class Duke { private ContactList contactList; private String personalContactFilePath; private Contact personalContact; + private final ContactsDecoder contactsDecoder; + private final ContactsEncoder contactsEncoder; public Duke(String contactFilePath, String personalContactFilePath) { this.contactFilePath = contactFilePath; this.personalContactFilePath = personalContactFilePath; this.parser = new MainParser(); - this.storage = new Storage(contactFilePath, personalContactFilePath); + this.contactsDecoder = new ContactsDecoder(); + this.contactsEncoder = new ContactsEncoder(); + this.storage = new Storage(contactFilePath, personalContactFilePath, contactsDecoder, contactsEncoder); try { this.contactList = storage.loadExistingContacts(); @@ -46,7 +51,7 @@ private void runCommandProcedure(Command command) { try { command.setContactList(contactList); command.execute(); - ContactsEncoder.saveContacts(contactFilePath, contactList); + contactsEncoder.saveContacts(contactFilePath, contactList); } catch (FileErrorException e) { ExceptionTextUi.fileErrorMessage(contactFilePath); } From 91755ea243c882c2009e2cfb7d4ed142db056384 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 21 Oct 2021 17:15:33 +0800 Subject: [PATCH 392/756] Update TextUi help message to include import --- src/main/java/seedu/ui/TextUi.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 1183120c52..65a027655d 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -209,7 +209,10 @@ public static void helpMessage() { + " If no flag is specified, contact name is searched by default.\n" + " Example: search -g QUERY\n\n" + "help: Displays application usage instructions.\n" - + " Example: help"; + + " Example: help\n\n" + + "import: Imports contacts from a CSV Text File.\n" + + " Note: Please ensure that data is saved in data/import.txt\n" + + " Example: import"; printDoubleLineMessage(message); } From 4aabdb70bd026c496cc0dcfa16d9292fc80191dc Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 21 Oct 2021 17:15:51 +0800 Subject: [PATCH 393/756] Update TextUi to include successful import message --- src/main/java/seedu/ui/TextUi.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 65a027655d..308c76560b 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -262,4 +262,9 @@ public static void ignoreContact(String type) { printDoubleLineMessage(message); } + public static void successfulImportMessage(int numberOfLines) { + String message = "ConTech has successfully imported " + numberOfLines + " lines"; + printDoubleLineMessage(message); + } + } From 8002a4f88ddb7a788e11161a7c5f4cce5b52637d Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 21 Oct 2021 17:16:35 +0800 Subject: [PATCH 394/756] Update CorruptPersonalContactMessage in ExceptionTextUi --- src/main/java/seedu/ui/ExceptionTextUi.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index cc572c715c..f743dd97b1 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -166,6 +166,8 @@ public static void numOutOfRangeMessage(int listSize) { public static void corruptLineMessage(String line) { printBottomLineMessage("Line \"" + line + "\" is corrupted and not loaded."); + public static void corruptPersonalContactMessage() { + printBottomLineMessage("Your personal contact file at data/me.txt is corrupted and not loaded."); } public static void forbiddenInputCommaMessage(String newUserInput) { From bbe7f2e67140b6211fa4b80f326130aab856a836 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 21 Oct 2021 17:17:08 +0800 Subject: [PATCH 395/756] Implement ExceptionTextUi to include file path and line number when flagging errors --- src/main/java/seedu/ui/ExceptionTextUi.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index f743dd97b1..b4f2838f6a 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -164,8 +164,10 @@ public static void numOutOfRangeMessage(int listSize) { printDoubleLineMessage(message); } - public static void corruptLineMessage(String line) { - printBottomLineMessage("Line \"" + line + "\" is corrupted and not loaded."); + public static void corruptLineMessage(String line, int lineIndex, String contactFilePath) { + System.out.println(contactFilePath + ":" + lineIndex + " - \"" + line + "\" is corrupted and not loaded."); + } + public static void corruptPersonalContactMessage() { printBottomLineMessage("Your personal contact file at data/me.txt is corrupted and not loaded."); } @@ -183,6 +185,10 @@ public static void forbiddenDetailMessage() { printDoubleLineMessage(message); } + public static void invalidLoadedLineMessage(int lineIndex, String contactFilePath) { + System.out.println(contactFilePath + ":" + lineIndex + " - There is an invalid field."); + } + //@@author mayankp291 public static void invalidNameInput() { String message = "The name is not correctly formatted,\n" From 30e87bd9f9f2d14b6c616dc56e4e2b6182e6a714 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 21 Oct 2021 17:17:23 +0800 Subject: [PATCH 396/756] Implement missing import file message in ExceptionTextUi --- src/main/java/seedu/ui/ExceptionTextUi.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index b4f2838f6a..8f42059cb2 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -189,6 +189,12 @@ public static void invalidLoadedLineMessage(int lineIndex, String contactFilePat System.out.println(contactFilePath + ":" + lineIndex + " - There is an invalid field."); } + public static void missingImportFileMessage() { + String message = "ConTech is unable to find the import file.\n" + + "Please kindly ensure that you have saved the file as data/import.txt."; + printDoubleLineMessage(message); + } + //@@author mayankp291 public static void invalidNameInput() { String message = "The name is not correctly formatted,\n" From e2a9566e92a615996da67a72777b7758f96eaddb Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 21 Oct 2021 17:18:01 +0800 Subject: [PATCH 397/756] Update Storage class attributes due to changes to ContactsEncoder and ContactsDecoder --- src/main/java/seedu/storage/Storage.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/storage/Storage.java b/src/main/java/seedu/storage/Storage.java index 1260f8aa5c..63c6a4cac7 100644 --- a/src/main/java/seedu/storage/Storage.java +++ b/src/main/java/seedu/storage/Storage.java @@ -5,7 +5,6 @@ import seedu.exception.FileErrorException; import seedu.parser.AddPersonalContactParser; import seedu.ui.TextUi; -import seedu.ui.UserInputTextUi; import java.io.File; import java.io.IOException; @@ -15,14 +14,19 @@ public class Storage { private final File contactFile; private final String personalContactFilePath; private final File personalContactFile; + private final ContactsDecoder contactsDecoder; + private final ContactsEncoder contactsEncoder; public static final String SEPARATOR = ","; private static boolean isFirstRun = false; - public Storage(String contactFilePath, String personalContactFilePath) { + public Storage(String contactFilePath, String personalContactFilePath, ContactsDecoder contactsDecoder, + ContactsEncoder contactsEncoder) { this.contactFilePath = contactFilePath; this.contactFile = new File(contactFilePath); this.personalContactFilePath = personalContactFilePath; this.personalContactFile = new File(personalContactFilePath); + this.contactsDecoder = contactsDecoder; + this.contactsEncoder = contactsEncoder; } public static boolean getIsFirstRun() { @@ -71,7 +75,7 @@ public ContactList loadExistingContacts() throws FileErrorException { if (!hasExistingContactFile()) { return new ContactList(); } - return ContactsDecoder.readContacts(contactFile); + return contactsDecoder.readContacts(contactFile, contactFilePath); } public Contact loadExistingPersonalContact() throws FileErrorException { @@ -81,10 +85,10 @@ public Contact loadExistingPersonalContact() throws FileErrorException { AddPersonalContactParser addPersonalContactParser = new AddPersonalContactParser(); addPersonalContactParser.startCollectingPersonalDetails(); Contact personalContact = addPersonalContactParser.getPersonalContact(); - ContactsEncoder.savePersonalContact(personalContactFilePath, personalContact); + contactsEncoder.savePersonalContact(personalContactFilePath, personalContact); return personalContact; } - Contact personalContact = ContactsDecoder.readPersonalContact(personalContactFile); + Contact personalContact = contactsDecoder.readPersonalContact(personalContactFile); TextUi.welcomeBackMessage(personalContact); return personalContact; } From c147b8442941f281039391f03fe4c244e3b57eb0 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 21 Oct 2021 17:22:57 +0800 Subject: [PATCH 398/756] Implement new CorruptPersonalContactMessage in contacts decoder --- src/main/java/seedu/storage/ContactsDecoder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index 33f5a71402..894c0f8e6f 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -55,7 +55,7 @@ private Contact decodePersonalContact(String contactText, Contact contact) { personalContact = new Contact(contactName, contactGithub, contactLinkedin, contactTelegram, contactTwitter, contactEmail); } catch (IndexOutOfBoundsException e) { - ExceptionTextUi.corruptLineMessage(contactText); + ExceptionTextUi.corruptPersonalContactMessage(); } return personalContact; } From 91a428c98f3f812e340c2e66d177c8dba05c0176 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 21 Oct 2021 17:23:41 +0800 Subject: [PATCH 399/756] Inherit RegexParser using ContactsDecoder for regex checks while parsing/decoding --- src/main/java/seedu/storage/ContactsDecoder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index 894c0f8e6f..3bfd7de6bf 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -13,7 +13,7 @@ import java.io.FileNotFoundException; import java.util.Scanner; -public class ContactsDecoder { +public class ContactsDecoder extends RegexParser { ContactList updatedContactList = new ContactList(); try { Scanner fileScanner = new Scanner(contactFile); From 2a36632eda08df9ae76ae97c57144a3af7c25318 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 21 Oct 2021 17:24:11 +0800 Subject: [PATCH 400/756] Implement line counter and file path reference in ReadContacts --- src/main/java/seedu/storage/ContactsDecoder.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index 3bfd7de6bf..006d22bee6 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -14,12 +14,15 @@ import java.util.Scanner; public class ContactsDecoder extends RegexParser { + public ContactList readContacts(File contactFile, String contactFilePath) throws FileErrorException { ContactList updatedContactList = new ContactList(); try { Scanner fileScanner = new Scanner(contactFile); + int lineIndex = 1; while (fileScanner.hasNext()) { String contactText = fileScanner.nextLine(); - decodeContact(updatedContactList, contactText); + decodeContact(updatedContactList, contactText, lineIndex, contactFilePath); + lineIndex++; } } catch (FileNotFoundException e) { throw new FileErrorException(); From 9becaa56aa9bea6ca685cc169d41ec7365e2c9b2 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 21 Oct 2021 17:24:54 +0800 Subject: [PATCH 401/756] Implement error messages due to regex checks from loading/importing --- .../java/seedu/storage/ContactsDecoder.java | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index 006d22bee6..ac65e178d4 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -4,6 +4,14 @@ import seedu.contact.ContactList; import seedu.contact.DetailType; import seedu.exception.FileErrorException; +import seedu.exception.InvalidEmailException; +import seedu.exception.InvalidFlagException; +import seedu.exception.InvalidGithubUsernameException; +import seedu.exception.InvalidLinkedinUsernameException; +import seedu.exception.InvalidNameException; +import seedu.exception.InvalidTelegramUsernameException; +import seedu.exception.InvalidTwitterUsernameException; +import seedu.parser.RegexParser; import seedu.ui.ExceptionTextUi; import static seedu.storage.Storage.SEPARATOR; @@ -77,7 +85,30 @@ private void decodeContact(ContactList contactList, String contactText, int line contactTwitter, contactEmail); contactList.addContact(newContact); } catch (IndexOutOfBoundsException e) { - ExceptionTextUi.corruptLineMessage(contactText); + ExceptionTextUi.corruptLineMessage(contactText, lineIndex, contactFilePath); + } catch (InvalidFlagException e) { + assert false; // Control should not arrive here since flags are predetermined by FLAG_SEQUENCE + ExceptionTextUi.invalidFlagMessage(); + } catch (InvalidGithubUsernameException | InvalidNameException | InvalidTelegramUsernameException + | InvalidLinkedinUsernameException | InvalidTwitterUsernameException | InvalidEmailException e) { + handleInvalidNames(e, lineIndex, contactFilePath); + } + } + + private void handleInvalidNames(Exception e, int lineIndex, String contactFilePath) { + ExceptionTextUi.invalidLoadedLineMessage(lineIndex, contactFilePath); + if (e instanceof InvalidNameException) { + ExceptionTextUi.invalidNameInput(); + } else if (e instanceof InvalidGithubUsernameException) { + ExceptionTextUi.invalidGithubUsernameInput(); + } else if (e instanceof InvalidEmailException) { + ExceptionTextUi.invalidEmailInput(); + } else if (e instanceof InvalidTelegramUsernameException) { + ExceptionTextUi.invalidTelegramUsernameInput(); + } else if (e instanceof InvalidTwitterUsernameException) { + ExceptionTextUi.invalidTelegramUsernameInput(); + } else if (e instanceof InvalidLinkedinUsernameException) { + ExceptionTextUi.invalidLinkedinUsernameInput(); } } From 1afdecd8b0130c953c36ce896a20574e78c1bdcb Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 21 Oct 2021 17:25:15 +0800 Subject: [PATCH 402/756] Implement Regex checkers in contactsdecoder --- src/main/java/seedu/storage/ContactsDecoder.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index ac65e178d4..243ddfee6d 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -112,12 +112,17 @@ private void handleInvalidNames(Exception e, int lineIndex, String contactFilePa } } + private String[] decodeDetails(String contactText) throws IndexOutOfBoundsException, + InvalidGithubUsernameException, InvalidNameException, InvalidFlagException, + InvalidTelegramUsernameException, InvalidTwitterUsernameException, + InvalidLinkedinUsernameException, InvalidEmailException { String[] destructuredInputs = contactText.split(SEPARATOR); String[] compiledDetails = new String[NUMBER_OF_FIELDS]; for (int i = 0; i < NUMBER_OF_FIELDS; i++) { if (destructuredInputs[i].equals("null")) { compiledDetails[i] = null; } else { + checkRegex(FLAG_SEQUENCE[i], destructuredInputs[i]); compiledDetails[i] = destructuredInputs[i]; } } From 31328c145ad1a235b32c8638dddb2b06710d4904 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 21 Oct 2021 17:33:06 +0800 Subject: [PATCH 403/756] Implement ImportContactCommand that appends imported contacts to existing contactlist (with sort) --- .../seedu/command/ImportContactCommand.java | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/main/java/seedu/command/ImportContactCommand.java diff --git a/src/main/java/seedu/command/ImportContactCommand.java b/src/main/java/seedu/command/ImportContactCommand.java new file mode 100644 index 0000000000..0ce4a5dc8b --- /dev/null +++ b/src/main/java/seedu/command/ImportContactCommand.java @@ -0,0 +1,50 @@ +package seedu.command; + +import seedu.contact.ContactList; +import seedu.exception.FileErrorException; +import seedu.storage.ContactsDecoder; +import seedu.ui.ExceptionTextUi; +import seedu.ui.TextUi; + +import java.io.File; + +public class ImportContactCommand extends Command { + private ContactList importedContacts; + private String importFilePath; + private File importFile; + + public ImportContactCommand() { + importFilePath = "data/import.txt"; + importFile = new File(importFilePath); + } + + public void execute() { + if (foundImportFile()) { + importContacts(); + appendImportedContacts(); + TextUi.successfulImportMessage(importedContacts.getListSize()); + } else { + ExceptionTextUi.missingImportFileMessage(); + } + } + + private boolean foundImportFile() { + return importFile.exists(); + } + + private void importContacts() { + assert importFile.exists(); + try { + ContactsDecoder contactsDecoder = new ContactsDecoder(); + importedContacts = contactsDecoder.readContacts(importFile, importFilePath); + } catch (FileErrorException e) { + ExceptionTextUi.fileErrorMessage(importFilePath); + } + } + + private void appendImportedContacts() { + for (int i = 0; i < importedContacts.getListSize(); i++) { + contactList.addContact(importedContacts.getContactAtIndex(i)); + } + } +} From 48a3e4cea4e77d182c1bab922305929439769113 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 21 Oct 2021 17:33:17 +0800 Subject: [PATCH 404/756] Update Text Ui Test with imports --- text-ui-test/ACTUAL.TXT | 25 +++++++++++++++++++++++++ text-ui-test/EXPECTED-UNIX.TXT | 25 +++++++++++++++++++++++++ text-ui-test/EXPECTED.TXT | 25 +++++++++++++++++++++++++ text-ui-test/input.txt | 3 +++ 4 files changed, 78 insertions(+) diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index 307c154e54..215e437787 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -582,6 +582,31 @@ Please try again with a valid flag. -e EMAIL ____________________________________________________________ +data/import.txt:3 - "andre,null" is corrupted and not loaded. +data/import.txt:5 - There is an invalid field. +____________________________________________________________ +The github username is not correctly formatted, +Rules for Github username : + * Only contain alphanumeric characters or hyphens + * Only lowercase allowed + * Maximum 39 characters allowed + * Cannot have multiple consecutive hyphens + * Cannot begin or end with a hyphen +____________________________________________________________ + +____________________________________________________________ +ConTech has successfully imported 3 lines +____________________________________________________________ + +____________________________________________________________ +5. lezai +Github: github.com/lezongmun +____________________________________________________________ + +____________________________________________________________ +No search results found. +____________________________________________________________ + ____________________________________________________________ ConTech will now shutdown. We hope you have enjoyed using it. diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index 307c154e54..215e437787 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -582,6 +582,31 @@ Please try again with a valid flag. -e EMAIL ____________________________________________________________ +data/import.txt:3 - "andre,null" is corrupted and not loaded. +data/import.txt:5 - There is an invalid field. +____________________________________________________________ +The github username is not correctly formatted, +Rules for Github username : + * Only contain alphanumeric characters or hyphens + * Only lowercase allowed + * Maximum 39 characters allowed + * Cannot have multiple consecutive hyphens + * Cannot begin or end with a hyphen +____________________________________________________________ + +____________________________________________________________ +ConTech has successfully imported 3 lines +____________________________________________________________ + +____________________________________________________________ +5. lezai +Github: github.com/lezongmun +____________________________________________________________ + +____________________________________________________________ +No search results found. +____________________________________________________________ + ____________________________________________________________ ConTech will now shutdown. We hope you have enjoyed using it. diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 307c154e54..215e437787 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -582,6 +582,31 @@ Please try again with a valid flag. -e EMAIL ____________________________________________________________ +data/import.txt:3 - "andre,null" is corrupted and not loaded. +data/import.txt:5 - There is an invalid field. +____________________________________________________________ +The github username is not correctly formatted, +Rules for Github username : + * Only contain alphanumeric characters or hyphens + * Only lowercase allowed + * Maximum 39 characters allowed + * Cannot have multiple consecutive hyphens + * Cannot begin or end with a hyphen +____________________________________________________________ + +____________________________________________________________ +ConTech has successfully imported 3 lines +____________________________________________________________ + +____________________________________________________________ +5. lezai +Github: github.com/lezongmun +____________________________________________________________ + +____________________________________________________________ +No search results found. +____________________________________________________________ + ____________________________________________________________ ConTech will now shutdown. We hope you have enjoyed using it. diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index 893eb55360..54d6c3235f 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -75,4 +75,7 @@ search boris search -n bory search -g lezong search -zxca lezong +import +search -n lezai +search -n badgithub exit \ No newline at end of file From 852e27865894b7d08845b52d3811cf3a47665359 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Thu, 21 Oct 2021 17:57:15 +0800 Subject: [PATCH 405/756] Sequence Diagram for ViewContactCommand --- .../ViewContactCommandSequenceDiagram.puml | 18 ++++++++++++++++++ .../ViewContactCommandSequenceDiagram.png | Bin 0 -> 12545 bytes 2 files changed, 18 insertions(+) create mode 100644 docs/diagrams/ViewContactCommandSequenceDiagram.puml create mode 100644 docs/images/ViewContactCommandSequenceDiagram.png diff --git a/docs/diagrams/ViewContactCommandSequenceDiagram.puml b/docs/diagrams/ViewContactCommandSequenceDiagram.puml new file mode 100644 index 0000000000..e56a8ced57 --- /dev/null +++ b/docs/diagrams/ViewContactCommandSequenceDiagram.puml @@ -0,0 +1,18 @@ +@startuml +hide footbox +'https://plantuml.com/sequence-diagram +-> ":ViewContactCommand": execute() +activate ":ViewContactCommand" + +":ViewContactCommand" -> ":IndexParser" :getContactFromIndex(contactIndex:int, contactList:ContactList) +activate ":IndexParser" +":IndexParser" --> ":ViewContactCommand" :viewingContact:Contact +deactivate ":IndexParser" + +":ViewContactCommand" -> ":TextUi":viewContactMessage(viewingContact:Contact, contactIndex:int) +activate ":TextUi" +":TextUi" --> ":ViewContactCommand" +deactivate ":TextUi" + +deactivate ":ViewContactCommand" +@enduml \ No newline at end of file diff --git a/docs/images/ViewContactCommandSequenceDiagram.png b/docs/images/ViewContactCommandSequenceDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..6b8f21218fce26a8149208524ecd42443d39ef36 GIT binary patch literal 12545 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 Date: Thu, 21 Oct 2021 17:57:48 +0800 Subject: [PATCH 406/756] Update DG for ViewContactCommand Implementation --- docs/DeveloperGuide.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 7969d3312c..7e827ec781 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -81,6 +81,14 @@ corresponding `ContactList` and `Contact` objects. It is thus dependent on the c {NOT DONE} +### Viewing a contact: `view` +This feature is processed using `ViewContactCommand`. Whenever a user wants to view a specific contact from the +contact list, user can input `view [INDEX]` with the index of the desired contact displayed from the `list` feature. +`ViewContactCommand` is then created in the `MainParser` and executed in `Duke`. +The sequence diagram below illustrates the `execute()` function in `ViewContactCommand`. + +![View Sequence Diagram](images/ViewContactCommandSequenceDiagram.png) + ### Editing a contact: `edit` This feature is processed using `EditContactParser` under `MainParser`. In order to edit a contact in the contact list, a user must enter a command in the form `edit [CONTACT INDEX] [DETAILS WITH FLAGS]` where the details with flags are From a139dd232501abd03014c0cbdfc6a749304f81a4 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Thu, 21 Oct 2021 17:58:29 +0800 Subject: [PATCH 407/756] Add DG user stories V1.0 and V2.0 --- docs/DeveloperGuide.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 7e827ec781..b20bd13b55 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -142,12 +142,17 @@ additional devices or platforms. ## User Stories -{NOT DONE} - |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| +|v1.0|programmer|add my colleague's account usernames|easily access it| +|v1.0|programmer|edit my colleague's account usernames|update it if there is a change| +|v1.0|programmer|save contact data locally on my hard drive|access it without internet| +|v1.0|programmer|view various contact details of my colleague|contact him easily on different platforms| +|v1.0|programmer|see the names and index of saved contacts|know the contacts I have saved| +|v1.0|programmer|delete a specific contact|| +|v1.0|programmer|be able to copy and paste the displayed contact's URLs|visit the contact's accounts| +|v2.0|programmer|save my personal details|the application is aware of the user| +|v2.0|forgetful user|be able to search for my contacts by name|find their contact details| ## Non-Functional Requirements From 9b628acc2e68c11a2d2f2cc94875ed91f21c5d4c Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 21 Oct 2021 19:48:10 +0800 Subject: [PATCH 408/756] Refactor search contact code --- src/main/java/seedu/contact/Contact.java | 5 ++ src/main/java/seedu/contact/ContactList.java | 60 ++++++-------------- 2 files changed, 22 insertions(+), 43 deletions(-) diff --git a/src/main/java/seedu/contact/Contact.java b/src/main/java/seedu/contact/Contact.java index b1ba302b8b..743a946833 100644 --- a/src/main/java/seedu/contact/Contact.java +++ b/src/main/java/seedu/contact/Contact.java @@ -64,4 +64,9 @@ public String getTelegram() { public void setTelegram(String telegram) { this.telegram = telegram; } + + //@@author ng-andre + public String[] getContactStringArray() { + return new String[]{ name, github, linkedin, telegram, twitter, email }; + } } diff --git a/src/main/java/seedu/contact/ContactList.java b/src/main/java/seedu/contact/ContactList.java index 9a1a0496cf..f863285231 100644 --- a/src/main/java/seedu/contact/ContactList.java +++ b/src/main/java/seedu/contact/ContactList.java @@ -5,6 +5,8 @@ import java.util.ArrayList; +import static seedu.parser.ContactParser.NUMBER_OF_FIELDS; + public class ContactList { public static final int NAME_INDEX = 0; public static final int GITHUB_INDEX = 1; @@ -61,55 +63,27 @@ public void deleteContact(int deletedIndex) { contacts.remove(deletedIndex); } + //@@author ng-andre + private boolean hasDetailMatches(String query, int detailType, int index, Contact contact) { + String[] contactStringArray = contact.getContactStringArray(); + if (contactStringArray[detailType] != null && + contactStringArray[detailType].toLowerCase().contains(query)) { + TextUi.viewContactMessage(contact, index); + return true; + } + return false; + } + //@@author ng-andre public void searchContact(String query, int detailType) throws InvalidFlagException { - boolean searchResult = false; + int matches = 0; for (int i = 0; i < contacts.size(); i++) { Contact contact = getContactAtIndex(i); - switch (detailType) { - case NAME_INDEX: - if (contact.getName() != null && contact.getName().toLowerCase().contains(query)) { - TextUi.viewContactMessage(contact, i); - searchResult = true; - } - break; - case GITHUB_INDEX: - if (contact.getGithub() != null && contact.getGithub().toLowerCase().contains(query)) { - TextUi.viewContactMessage(contact, i); - searchResult = true; - } - break; - case LINKEDIN_INDEX: - if (contact.getLinkedin() != null && contact.getLinkedin().toLowerCase().contains(query)) { - TextUi.viewContactMessage(contact, i); - searchResult = true; - } - break; - case TELEGRAM_INDEX: - if (contact.getTelegram() != null && contact.getTelegram().toLowerCase().contains(query)) { - TextUi.viewContactMessage(contact, i); - searchResult = true; - } - break; - case TWITTER_INDEX: - if (contact.getTwitter() != null && contact.getTwitter().toLowerCase().contains(query)) { - TextUi.viewContactMessage(contact, i); - searchResult = true; - } - break; - case EMAIL_INDEX: - if (contact.getEmail() != null && contact.getEmail().toLowerCase().contains(query)) { - TextUi.viewContactMessage(contact, i); - searchResult = true; - } - break; - default: - //control should never reach here - assert false; - throw new InvalidFlagException(); + if(hasDetailMatches(query, detailType, i, contact)) { + matches++; } } - if (!searchResult) { + if (matches == 0) { TextUi.searchNoResultsFoundMessage(); } } From 70327f1817807de9e8c785df02dd294e2152ff46 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 21 Oct 2021 20:04:22 +0800 Subject: [PATCH 409/756] Update to fulfill checkstyle --- src/main/java/seedu/contact/ContactList.java | 6 +++--- src/main/java/seedu/parser/RegexParser.java | 2 +- src/main/java/seedu/storage/ContactsDecoder.java | 3 ++- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/contact/ContactList.java b/src/main/java/seedu/contact/ContactList.java index f863285231..0df54368c5 100644 --- a/src/main/java/seedu/contact/ContactList.java +++ b/src/main/java/seedu/contact/ContactList.java @@ -66,8 +66,8 @@ public void deleteContact(int deletedIndex) { //@@author ng-andre private boolean hasDetailMatches(String query, int detailType, int index, Contact contact) { String[] contactStringArray = contact.getContactStringArray(); - if (contactStringArray[detailType] != null && - contactStringArray[detailType].toLowerCase().contains(query)) { + if (contactStringArray[detailType] != null + && contactStringArray[detailType].toLowerCase().contains(query)) { TextUi.viewContactMessage(contact, index); return true; } @@ -79,7 +79,7 @@ public void searchContact(String query, int detailType) throws InvalidFlagExcept int matches = 0; for (int i = 0; i < contacts.size(); i++) { Contact contact = getContactAtIndex(i); - if(hasDetailMatches(query, detailType, i, contact)) { + if (hasDetailMatches(query, detailType, i, contact)) { matches++; } } diff --git a/src/main/java/seedu/parser/RegexParser.java b/src/main/java/seedu/parser/RegexParser.java index 31fae56071..f126ac8518 100644 --- a/src/main/java/seedu/parser/RegexParser.java +++ b/src/main/java/seedu/parser/RegexParser.java @@ -21,7 +21,7 @@ public abstract class RegexParser { public static final String EMAIL_FLAG = "e"; protected static final String[] FLAG_SEQUENCE = {NAME_FLAG, GITHUB_FLAG, LINKEDIN_FLAG, - TELEGRAM_FLAG, TWITTER_FLAG, EMAIL_FLAG}; + TELEGRAM_FLAG, TWITTER_FLAG, EMAIL_FLAG}; private static final Logger LOGGER = Logger.getLogger(RegexParser.class.getName()); public void checkRegex(String flag, String detailToParse) diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index c423f70092..8eb2a8c8dc 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -72,7 +72,8 @@ private Contact decodePersonalContact(String contactText, Contact contact) { ExceptionTextUi.invalidFlagMessage(); } catch (InvalidGithubUsernameException | InvalidNameException | InvalidTelegramUsernameException | InvalidLinkedinUsernameException | InvalidTwitterUsernameException | InvalidEmailException e) { - + // For @lezongmun, from @marcusbory + ExceptionTextUi.invalidNameInput(); } return personalContact; } From 052d8caebee42282e130efb7f459645e3741fd49 Mon Sep 17 00:00:00 2001 From: lezong Date: Thu, 21 Oct 2021 20:05:41 +0800 Subject: [PATCH 410/756] Merge and refactor --- .../seedu/command/EditContactCommand.java | 47 +++++++------------ 1 file changed, 17 insertions(+), 30 deletions(-) diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index c474765a25..75f9b9eaa7 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -2,7 +2,6 @@ import seedu.contact.Contact; import seedu.contact.ContactList; -import seedu.exception.InvalidEmailException; import seedu.exception.InvalidFlagException; import seedu.ui.TextUi; import seedu.ui.ExceptionTextUi; @@ -19,6 +18,7 @@ public class EditContactCommand extends Command { public static final int TWITTER_INDEX = 4; public static final int EMAIL_INDEX = 5; public static final int NUMBER_OF_FIELDS = 6; + public static final String EDIT_TYPE = "edit"; String[] contactDetails; int contactIndex; @@ -48,7 +48,7 @@ private void updatePersonalContact() { private void handleDuplicates(Contact postEditContact) throws IndexOutOfBoundsException, InvalidFlagException { if (hasDuplicates(postEditContact, contactList, contactIndex)) { - TextUi.ignoreContact("edit"); + TextUi.ignoreContact(EDIT_TYPE); } else { updateContact(postEditContact); } @@ -62,44 +62,31 @@ private void updateContact(Contact postEditContact) private Boolean hasDuplicates(Contact postEditContact, ContactList contactList, int contactIndex) throws InvalidFlagException { - ArrayList duplicatedIndexes = new ArrayList<>(); + ArrayList duplicatedIndex = new ArrayList<>(); String[] postEditContactDetails = extractContactDetails(postEditContact); for (int i = 0; i < contactList.getListSize(); i++) { if (i == contactIndex) { continue; } - String[] currContactDetails = extractContactDetails(contactList.getContactAtIndex(i)); - //check for any field that is duplicated for all the fields in contact details - checkCurrContactDetails(duplicatedIndexes, i, postEditContactDetails, currContactDetails); + String[] currentContactDetails = extractContactDetails(contactList.getContactAtIndex(i)); + for (int j = 0; j < NUMBER_OF_FIELDS; j++) { + if (postEditContactDetails[j] != null && currentContactDetails[j] != null) { + if (hasDuplicateField(postEditContactDetails[j], currentContactDetails[j])) { + duplicatedIndex.add(i); + break; + } + } + } + } - if (!duplicatedIndexes.isEmpty()) { - TextUi.confirmDuplicateMessage(duplicatedIndexes, contactList, "edit"); + if (!duplicatedIndex.isEmpty()) { + TextUi.confirmDuplicateMessage(duplicatedIndex, contactList, EDIT_TYPE); String userEditConfirmation = UserInputTextUi.getUserConfirmation(); return userEditConfirmation.equalsIgnoreCase("n"); } return false; } - private void checkCurrContactDetails(ArrayList duplicatedIndexes, int currContactIndex, - String[] postEditContactDetails, String[] currContactDetails) { - for (int j = 0; j < NUMBER_OF_FIELDS; j++) { - boolean isDuplicatedField = - checkDuplicatedField(postEditContactDetails[j], currContactDetails[j]); - if (isDuplicatedField) { - duplicatedIndexes.add(currContactIndex); - break; - } - } - } - - private boolean checkDuplicatedField(String postEditField, String currentField) { - if (postEditField != null && currentField != null) { - return (hasDuplicateField(postEditField, currentField)); - } - return false; - } - - private Contact duplicateContact(Contact contact) { String name = contact.getName(); String github = contact.getGithub(); @@ -111,10 +98,10 @@ private Contact duplicateContact(Contact contact) { } private Boolean hasDuplicateField(String input, String saved) { - return cleanString(saved).equals(cleanString(input)); + return stringCleaner(saved).equals(stringCleaner(input)); } - private String cleanString(String input) { + private String stringCleaner(String input) { return input.replace(" ", "").toLowerCase(); } From 87f57b77ff6ecb06cf6064d3dc61cc1fd50efd72 Mon Sep 17 00:00:00 2001 From: lezong Date: Thu, 21 Oct 2021 20:09:26 +0800 Subject: [PATCH 411/756] Save personal contact to local file after editing --- src/main/java/seedu/duke/Duke.java | 1 + src/main/java/seedu/storage/ContactsEncoder.java | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 7b920b48f1..81195dde21 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -48,6 +48,7 @@ private void runCommandProcedure(Command command) { command.setPersonalContact(personalContact); command.execute(); ContactsEncoder.saveContacts(contactFilePath, contactList); + ContactsEncoder.savePersonalContact(personalContactFilePath, personalContact); } catch (FileErrorException e) { ExceptionTextUi.fileErrorMessage(contactFilePath); } diff --git a/src/main/java/seedu/storage/ContactsEncoder.java b/src/main/java/seedu/storage/ContactsEncoder.java index 9e0c707973..e5e4f2c1fe 100644 --- a/src/main/java/seedu/storage/ContactsEncoder.java +++ b/src/main/java/seedu/storage/ContactsEncoder.java @@ -2,6 +2,7 @@ import seedu.contact.Contact; import seedu.contact.ContactList; +import seedu.contact.PersonalContact; import seedu.exception.FileErrorException; import java.io.FileWriter; @@ -10,7 +11,7 @@ import static seedu.storage.Storage.SEPARATOR; public class ContactsEncoder { - public static void savePersonalContact(String contactFilePath, Contact personalContact) throws FileErrorException { + public static void savePersonalContact(String contactFilePath, PersonalContact personalContact) throws FileErrorException { try { FileWriter fileWriter = new FileWriter(contactFilePath); String encodedContact = encodeContact(personalContact); From d415623539bd86d9493da0a0e8517a0026ccc56f Mon Sep 17 00:00:00 2001 From: lezong Date: Thu, 21 Oct 2021 20:37:01 +0800 Subject: [PATCH 412/756] Minor edits to Developer Guide for DeleteCommand Sequence Diagram --- docs/diagrams/DeleteContactCommand.puml | 6 ++++++ .../DeleteContactCommandSequenceDiagram.png | Bin 42335 -> 41809 bytes .../seedu/command/EditContactCommand.java | 1 - 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/diagrams/DeleteContactCommand.puml b/docs/diagrams/DeleteContactCommand.puml index d9637c1118..a2c00a9d1c 100644 --- a/docs/diagrams/DeleteContactCommand.puml +++ b/docs/diagrams/DeleteContactCommand.puml @@ -13,6 +13,7 @@ deactivate ":IndexParser" activate ":DeleteContactCommand" ":DeleteContactCommand" -> ":TextUi":ConfirmDeleteMessage(deletedContact:Contact, contactIndex:int) activate ":TextUi" +":TextUi" --> ":DeleteContactCommand" deactivate ":TextUi" ":DeleteContactCommand" -> ":UserInputTextUi":getUserConfirmation() @@ -23,6 +24,7 @@ deactivate ":UserInputTextUi" alt#gold #lightgreen userConfirmation.equalsIgnoreCase("y") ":DeleteContactCommand" -> ":ContactList": deleteContact(contactIndex:int) activate ":ContactList" + ":ContactList" --> ":DeleteContactCommand" deactivate ":ContactList" ":DeleteContactCommand" -> ":Contact" :getName() activate ":Contact" @@ -36,12 +38,16 @@ alt#gold #lightgreen userConfirmation.equalsIgnoreCase("y") ":DeleteContactCommand" -> ":TextUi":deleteContactMessage(deletedName:String, contactListSize:int) activate ":TextUi" + ":TextUi" --> ":DeleteContactCommand" deactivate ":TextUi" + else #lightblue else ":DeleteContactCommand" -> ":TextUi":cancelDeleteContactMessage() activate ":TextUi" + ":TextUi" --> ":DeleteContactCommand" deactivate ":TextUi" + end deactivate ":DeleteContactCommand" deactivate ":DeleteContactCommand" diff --git a/docs/images/DeleteContactCommandSequenceDiagram.png b/docs/images/DeleteContactCommandSequenceDiagram.png index 981f3510e9a19b9a4d7ad1c39f5df931eb79b5a8..ce6e6dbeb218d95b875b2cb70d635edc7fc3194f 100644 GIT binary patch literal 41809 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'cB>a+%Ea$g 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%0A+B=ItvQ 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%0ALjya zh*Dv|DioyHt@fs2U#cy)jb#O6s`h;1_oe zy8G;JzyEhY1q1zsK>^UhYh~nHsSU55)v(mh_}PEAWivL-J?X+)Ih(a+!@k|erWBxF ze`6wua#cAbp~HZcz*{)BBPLVTFl4A43ayx6*KNefDh6+sFW6aL>w5u!lEWs3`J`ai zH(XDzo#bA5!PpK1zZVyr(z7syjAC)p2_|IvXfg(JlN-P%uhVJ7mHSPhd;Q=$Wbt`< z8;lFfngv_pV5dvSKw%aPHUy&pcl3OQJw>tiG?!iMXR0k*?rLSCSAnmm zW=@p?)gW+%3i;ur^6lmIlU6wF;m%oAyt>@`tIt+3jvzgIn|1k)Q6n8fm z1&Zg5yOqoM>h_v#Hef{;DRh4Yd~BWWIn}!z_b;XX}go^^%8|gR(Ur@wkpns)6^<>-!8`<=kt94i9J|5M=rSL~=7L@bhZnQu` z)Cx>g!FF+A(;EjNU`V{A+pR*IpA8^^m2$BvVuTYx;U;WY9rEWju$+W$91J7i>UOPj zK%IHnlaam)e8%0`Hx>q0dt1?*W~1P9HRTIPqa04CO%YZ?#+My?{<&d&#bOJvg{L9- z=q}jovnx$`3w%|| Date: Thu, 21 Oct 2021 22:44:17 +0800 Subject: [PATCH 413/756] Update scripts to work with dummy import data --- text-ui-test/runtest.bat | 8 +++++++- text-ui-test/runtest.sh | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/text-ui-test/runtest.bat b/text-ui-test/runtest.bat index 25ac7a2989..902b146db1 100644 --- a/text-ui-test/runtest.bat +++ b/text-ui-test/runtest.bat @@ -12,8 +12,14 @@ for /f "tokens=*" %%a in ( set jarloc=%%a ) -java -jar %jarloc% < ..\..\text-ui-test\input.txt > ..\..\text-ui-test\ACTUAL.TXT +xcopy duke.jar ..\..\text-ui-test cd ..\..\text-ui-test +java -jar duke.jar < input.txt > ACTUAL.TXT + FC ACTUAL.TXT EXPECTED.TXT >NUL && ECHO Test passed! || Echo Test failed! + +del data\contacts.txt +del data\me.txt +del duke.jar \ No newline at end of file diff --git a/text-ui-test/runtest.sh b/text-ui-test/runtest.sh index 1dcbd12021..04d6b8e9c2 100755 --- a/text-ui-test/runtest.sh +++ b/text-ui-test/runtest.sh @@ -13,6 +13,8 @@ java -jar $(find ../build/libs/ -mindepth 1 -print -quit) < input.txt > ACTUAL. cp EXPECTED.TXT EXPECTED-UNIX.TXT dos2unix EXPECTED-UNIX.TXT ACTUAL.TXT diff EXPECTED-UNIX.TXT ACTUAL.TXT +rm data/contacts.txt +rm data/me.txt if [ $? -eq 0 ] then echo "Test passed!" From 26b98a6509b88f644b365417d523078e14b066af Mon Sep 17 00:00:00 2001 From: lezong Date: Fri, 22 Oct 2021 00:27:56 +0800 Subject: [PATCH 414/756] Update text-ui-test --- text-ui-test/ACTUAL.TXT | 25 +++++++++++++++++++++++-- text-ui-test/EXPECTED-UNIX.TXT | 25 +++++++++++++++++++++++-- text-ui-test/EXPECTED.TXT | 25 +++++++++++++++++++++++-- 3 files changed, 69 insertions(+), 6 deletions(-) diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index 78a07e4358..19c9b0e826 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -9,6 +9,7 @@ data/me.txt ____________________________________________________________ ____________________________________________________________ + _____ _______ _ / ____| |__ __| | | | | ___ _ __ | | ___ ___| |__ @@ -18,9 +19,8 @@ ____________________________________________________________ ____________________________________________________________ - Welcome to ConTech, your personal contact tracker. -Can I get your name? +Please provide us with your Name. ____________________________________________________________ Name: ____________________________________________________________ @@ -87,6 +87,27 @@ Email: lezongmun@gmail.com Telegram: t.me/lezongg ____________________________________________________________ +____________________________________________________________ +ConTech has edited your personal contact: +Name: Marcus Bory +Github: github.com/lezongmun +Email: lezongmun@gmail.com +Telegram: t.me/lezongg +____________________________________________________________ + +____________________________________________________________ +There seems to be missing parameters in your request. +Please specify your command. +____________________________________________________________ + +____________________________________________________________ +The email id is not correctly formatted, +Rules for email id : + * Lowercase letters only + * Numbers, underscore, hyphen and dot allowed + * @ cannot be at the start or end +____________________________________________________________ + ____________________________________________________________ There are no contacts stored in ConTech. ____________________________________________________________ diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index 78a07e4358..19c9b0e826 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -9,6 +9,7 @@ data/me.txt ____________________________________________________________ ____________________________________________________________ + _____ _______ _ / ____| |__ __| | | | | ___ _ __ | | ___ ___| |__ @@ -18,9 +19,8 @@ ____________________________________________________________ ____________________________________________________________ - Welcome to ConTech, your personal contact tracker. -Can I get your name? +Please provide us with your Name. ____________________________________________________________ Name: ____________________________________________________________ @@ -87,6 +87,27 @@ Email: lezongmun@gmail.com Telegram: t.me/lezongg ____________________________________________________________ +____________________________________________________________ +ConTech has edited your personal contact: +Name: Marcus Bory +Github: github.com/lezongmun +Email: lezongmun@gmail.com +Telegram: t.me/lezongg +____________________________________________________________ + +____________________________________________________________ +There seems to be missing parameters in your request. +Please specify your command. +____________________________________________________________ + +____________________________________________________________ +The email id is not correctly formatted, +Rules for email id : + * Lowercase letters only + * Numbers, underscore, hyphen and dot allowed + * @ cannot be at the start or end +____________________________________________________________ + ____________________________________________________________ There are no contacts stored in ConTech. ____________________________________________________________ diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 78a07e4358..19c9b0e826 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -9,6 +9,7 @@ data/me.txt ____________________________________________________________ ____________________________________________________________ + _____ _______ _ / ____| |__ __| | | | | ___ _ __ | | ___ ___| |__ @@ -18,9 +19,8 @@ ____________________________________________________________ ____________________________________________________________ - Welcome to ConTech, your personal contact tracker. -Can I get your name? +Please provide us with your Name. ____________________________________________________________ Name: ____________________________________________________________ @@ -87,6 +87,27 @@ Email: lezongmun@gmail.com Telegram: t.me/lezongg ____________________________________________________________ +____________________________________________________________ +ConTech has edited your personal contact: +Name: Marcus Bory +Github: github.com/lezongmun +Email: lezongmun@gmail.com +Telegram: t.me/lezongg +____________________________________________________________ + +____________________________________________________________ +There seems to be missing parameters in your request. +Please specify your command. +____________________________________________________________ + +____________________________________________________________ +The email id is not correctly formatted, +Rules for email id : + * Lowercase letters only + * Numbers, underscore, hyphen and dot allowed + * @ cannot be at the start or end +____________________________________________________________ + ____________________________________________________________ There are no contacts stored in ConTech. ____________________________________________________________ From b411db38f00d182133ca8ba0c006119cc761a50b Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Fri, 22 Oct 2021 01:47:18 +0800 Subject: [PATCH 415/756] Edit duplicate check to skip non-edited fields --- src/main/java/seedu/command/EditContactCommand.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index e120b3bb9b..b9829b9ecb 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -7,7 +7,9 @@ import seedu.ui.ExceptionTextUi; import seedu.ui.UserInputTextUi; +import java.lang.reflect.Array; import java.util.ArrayList; +import java.util.Arrays; public class EditContactCommand extends Command { public static final int NAME_INDEX = 0; @@ -43,6 +45,7 @@ public void execute() { private Boolean hasDuplicates(Contact postEditContact, ContactList contactList, int contactIndex) throws InvalidFlagException { ArrayList duplicatedIndex = new ArrayList<>(); + Boolean[] hasEditedField = hasEditedFieldChecker(contactDetails); String[] postEditContactDetails = extractContactDetails(postEditContact); for (int i = 0; i < contactList.getListSize(); i++) { if (i == contactIndex) { @@ -50,6 +53,9 @@ private Boolean hasDuplicates(Contact postEditContact, ContactList contactList, } String[] currentContactDetails = extractContactDetails(contactList.getContactAtIndex(i)); for (int j = 0; j < NUMBER_OF_FIELDS; j++) { + if (!hasEditedField[j]) { + continue; + } if (postEditContactDetails[j] != null && currentContactDetails[j] != null) { if (hasDuplicateField(postEditContactDetails[j], currentContactDetails[j])) { duplicatedIndex.add(i); @@ -57,7 +63,6 @@ private Boolean hasDuplicates(Contact postEditContact, ContactList contactList, } } } - } if (!duplicatedIndex.isEmpty()) { TextUi.confirmDuplicateMessage(duplicatedIndex, contactList, "edit"); From e88d1c88203535b2a54b777627f74bca03bd6688 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Fri, 22 Oct 2021 01:47:50 +0800 Subject: [PATCH 416/756] Add hasEditedFieldChecker to return boolean array --- src/main/java/seedu/command/EditContactCommand.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index b9829b9ecb..51159f8bdd 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -72,6 +72,14 @@ private Boolean hasDuplicates(Contact postEditContact, ContactList contactList, return false; } + private Boolean[] hasEditedFieldChecker(String[] contactDetails) { + Boolean[] hasEditedField = new Boolean[NUMBER_OF_FIELDS]; + for (int i = 0; i < NUMBER_OF_FIELDS; i++) { + hasEditedField[i] = (contactDetails[i] != null); + } + return hasEditedField; + } + private Contact duplicateContact(Contact contact) { String name = contact.getName(); String github = contact.getGithub(); From fd5ac1f4579ca88713cebeeb0053c4aeff6f0e61 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Fri, 22 Oct 2021 01:48:18 +0800 Subject: [PATCH 417/756] Add new inputs to test edit duplicate checker --- text-ui-test/input.txt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index e2e1b475eb..7bbedfce97 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -60,7 +60,6 @@ view 0 add -n name -g null add -n dev -g nullptr edit 3 -g new-git - y add -n asjoda sadfsd -tw _123 adad y add -n asjoda sadfsd -tw 123_adad @@ -76,4 +75,12 @@ search boris search -n bory search -g lezong search -zxca lezong +list +add -n ashraf -g ashrafjfr +add -n ashraf -te ashrafjfr +y +edit 0 -te ashrafjfr +y +edit 0 -e ashrafjfr@gmail.com +view 0 exit \ No newline at end of file From a8cd73446806def650f0a6706f66003f78d95cd7 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Fri, 22 Oct 2021 01:48:37 +0800 Subject: [PATCH 418/756] Updates to text-ui-test --- text-ui-test/ACTUAL.TXT | 86 ++++++++++++++++++++++++++++++---- text-ui-test/EXPECTED-UNIX.TXT | 86 ++++++++++++++++++++++++++++++---- text-ui-test/EXPECTED.TXT | 86 ++++++++++++++++++++++++++++++---- 3 files changed, 228 insertions(+), 30 deletions(-) diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index 2825add5f2..5308b0ec89 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -466,16 +466,6 @@ Github: github.com/nullptr You now have 8 contact(s). ____________________________________________________________ -____________________________________________________________ -One of your saved contacts has a duplicate field: - -4. lezongmun -Github: github.com/lezong - -Do you still want to edit the contact? (y/n) - -____________________________________________________________ - ____________________________________________________________ ConTech has edited the specified contact: Name: lezong mun @@ -589,6 +579,82 @@ Please try again with a valid flag. -e EMAIL ____________________________________________________________ +____________________________________________________________ +ConTech has 10 contacts stored. +Here's the list : +____________________________________________________________ + +0. asjoda sadfsd +1. asjoda sadfsd +2. bory +3. dev +4. lezong mun +5. lezongggg +6. lezongmun +7. mayank +8. ng andre +9. yusdhsdsd + +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: +Name: ashraf +Github: github.com/ashrafjfr + +You now have 11 contact(s). +____________________________________________________________ + +____________________________________________________________ +One of your saved contacts has a duplicate field: + +0. ashraf +Github: github.com/ashrafjfr + +Do you still want to add the contact? (y/n) + +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: +Name: ashraf +Telegram: t.me/ashrafjfr + +You now have 12 contact(s). +____________________________________________________________ + +____________________________________________________________ +One of your saved contacts has a duplicate field: + +1. ashraf +Telegram: t.me/ashrafjfr + +Do you still want to edit the contact? (y/n) + +____________________________________________________________ + +____________________________________________________________ +ConTech has edited the specified contact: +Name: ashraf +Github: github.com/ashrafjfr +Telegram: t.me/ashrafjfr +____________________________________________________________ + +____________________________________________________________ +ConTech has edited the specified contact: +Name: ashraf +Github: github.com/ashrafjfr +Email: ashrafjfr@gmail.com +Telegram: t.me/ashrafjfr +____________________________________________________________ + +____________________________________________________________ +0. ashraf +Github: github.com/ashrafjfr +Email: ashrafjfr@gmail.com +Telegram: t.me/ashrafjfr +____________________________________________________________ + ____________________________________________________________ ConTech will now shutdown. We hope you have enjoyed using it. diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index 2825add5f2..5308b0ec89 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -466,16 +466,6 @@ Github: github.com/nullptr You now have 8 contact(s). ____________________________________________________________ -____________________________________________________________ -One of your saved contacts has a duplicate field: - -4. lezongmun -Github: github.com/lezong - -Do you still want to edit the contact? (y/n) - -____________________________________________________________ - ____________________________________________________________ ConTech has edited the specified contact: Name: lezong mun @@ -589,6 +579,82 @@ Please try again with a valid flag. -e EMAIL ____________________________________________________________ +____________________________________________________________ +ConTech has 10 contacts stored. +Here's the list : +____________________________________________________________ + +0. asjoda sadfsd +1. asjoda sadfsd +2. bory +3. dev +4. lezong mun +5. lezongggg +6. lezongmun +7. mayank +8. ng andre +9. yusdhsdsd + +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: +Name: ashraf +Github: github.com/ashrafjfr + +You now have 11 contact(s). +____________________________________________________________ + +____________________________________________________________ +One of your saved contacts has a duplicate field: + +0. ashraf +Github: github.com/ashrafjfr + +Do you still want to add the contact? (y/n) + +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: +Name: ashraf +Telegram: t.me/ashrafjfr + +You now have 12 contact(s). +____________________________________________________________ + +____________________________________________________________ +One of your saved contacts has a duplicate field: + +1. ashraf +Telegram: t.me/ashrafjfr + +Do you still want to edit the contact? (y/n) + +____________________________________________________________ + +____________________________________________________________ +ConTech has edited the specified contact: +Name: ashraf +Github: github.com/ashrafjfr +Telegram: t.me/ashrafjfr +____________________________________________________________ + +____________________________________________________________ +ConTech has edited the specified contact: +Name: ashraf +Github: github.com/ashrafjfr +Email: ashrafjfr@gmail.com +Telegram: t.me/ashrafjfr +____________________________________________________________ + +____________________________________________________________ +0. ashraf +Github: github.com/ashrafjfr +Email: ashrafjfr@gmail.com +Telegram: t.me/ashrafjfr +____________________________________________________________ + ____________________________________________________________ ConTech will now shutdown. We hope you have enjoyed using it. diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 2825add5f2..5308b0ec89 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -466,16 +466,6 @@ Github: github.com/nullptr You now have 8 contact(s). ____________________________________________________________ -____________________________________________________________ -One of your saved contacts has a duplicate field: - -4. lezongmun -Github: github.com/lezong - -Do you still want to edit the contact? (y/n) - -____________________________________________________________ - ____________________________________________________________ ConTech has edited the specified contact: Name: lezong mun @@ -589,6 +579,82 @@ Please try again with a valid flag. -e EMAIL ____________________________________________________________ +____________________________________________________________ +ConTech has 10 contacts stored. +Here's the list : +____________________________________________________________ + +0. asjoda sadfsd +1. asjoda sadfsd +2. bory +3. dev +4. lezong mun +5. lezongggg +6. lezongmun +7. mayank +8. ng andre +9. yusdhsdsd + +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: +Name: ashraf +Github: github.com/ashrafjfr + +You now have 11 contact(s). +____________________________________________________________ + +____________________________________________________________ +One of your saved contacts has a duplicate field: + +0. ashraf +Github: github.com/ashrafjfr + +Do you still want to add the contact? (y/n) + +____________________________________________________________ + +____________________________________________________________ +ConTech has added the specified contact: +Name: ashraf +Telegram: t.me/ashrafjfr + +You now have 12 contact(s). +____________________________________________________________ + +____________________________________________________________ +One of your saved contacts has a duplicate field: + +1. ashraf +Telegram: t.me/ashrafjfr + +Do you still want to edit the contact? (y/n) + +____________________________________________________________ + +____________________________________________________________ +ConTech has edited the specified contact: +Name: ashraf +Github: github.com/ashrafjfr +Telegram: t.me/ashrafjfr +____________________________________________________________ + +____________________________________________________________ +ConTech has edited the specified contact: +Name: ashraf +Github: github.com/ashrafjfr +Email: ashrafjfr@gmail.com +Telegram: t.me/ashrafjfr +____________________________________________________________ + +____________________________________________________________ +0. ashraf +Github: github.com/ashrafjfr +Email: ashrafjfr@gmail.com +Telegram: t.me/ashrafjfr +____________________________________________________________ + ____________________________________________________________ ConTech will now shutdown. We hope you have enjoyed using it. From 7599bcdec18675df5e49bd3e84b179b36dffa6cc Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Fri, 22 Oct 2021 11:47:36 +0800 Subject: [PATCH 419/756] Refactor boolean duplicate checkers --- src/main/java/seedu/command/AddContactCommand.java | 5 ++--- src/main/java/seedu/command/EditContactCommand.java | 10 +++++----- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/main/java/seedu/command/AddContactCommand.java b/src/main/java/seedu/command/AddContactCommand.java index 394c192ee4..b6912c41d7 100644 --- a/src/main/java/seedu/command/AddContactCommand.java +++ b/src/main/java/seedu/command/AddContactCommand.java @@ -10,7 +10,6 @@ import seedu.ui.UserInputTextUi; import java.util.ArrayList; -import java.util.Arrays; public class AddContactCommand extends Command { private final String name; @@ -74,7 +73,7 @@ public void execute() { } } - private Boolean hasDuplicates(Contact addedContact, ContactList contactList) throws InvalidFlagException { + private boolean hasDuplicates(Contact addedContact, ContactList contactList) throws InvalidFlagException { ArrayList duplicatedIndex = new ArrayList<>(); String[] addedContactDetails = extractContactDetails(addedContact); for (int i = 0; i < contactList.getListSize(); i++) { @@ -126,7 +125,7 @@ private String[] extractContactDetails(Contact contact) throws InvalidFlagExcept return contactDetails; } - private Boolean hasDuplicateField(String input, String saved) { + private boolean hasDuplicateField(String input, String saved) { return stringCleaner(saved).equals(stringCleaner(input)); } diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index 51159f8bdd..4d9b80aaee 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -42,10 +42,10 @@ public void execute() { } } - private Boolean hasDuplicates(Contact postEditContact, ContactList contactList, int contactIndex) + private boolean hasDuplicates(Contact postEditContact, ContactList contactList, int contactIndex) throws InvalidFlagException { ArrayList duplicatedIndex = new ArrayList<>(); - Boolean[] hasEditedField = hasEditedFieldChecker(contactDetails); + boolean[] hasEditedField = hasEditedFields(contactDetails); String[] postEditContactDetails = extractContactDetails(postEditContact); for (int i = 0; i < contactList.getListSize(); i++) { if (i == contactIndex) { @@ -72,8 +72,8 @@ private Boolean hasDuplicates(Contact postEditContact, ContactList contactList, return false; } - private Boolean[] hasEditedFieldChecker(String[] contactDetails) { - Boolean[] hasEditedField = new Boolean[NUMBER_OF_FIELDS]; + private boolean[] hasEditedFields(String[] contactDetails) { + boolean[] hasEditedField = new boolean[NUMBER_OF_FIELDS]; for (int i = 0; i < NUMBER_OF_FIELDS; i++) { hasEditedField[i] = (contactDetails[i] != null); } @@ -90,7 +90,7 @@ private Contact duplicateContact(Contact contact) { return new Contact(name, github, linkedin, telegram, twitter, email); } - private Boolean hasDuplicateField(String input, String saved) { + private boolean hasDuplicateField(String input, String saved) { return stringCleaner(saved).equals(stringCleaner(input)); } From 8adeaa23b0386600bdef5367cd1c109bbce32642 Mon Sep 17 00:00:00 2001 From: lezong Date: Fri, 22 Oct 2021 11:51:01 +0800 Subject: [PATCH 420/756] Refactor editContact in ContactList to Contact --- src/main/java/seedu/command/Command.java | 6 +- .../seedu/command/EditContactCommand.java | 48 ++++----------- src/main/java/seedu/contact/Contact.java | 40 +++++++++++++ src/main/java/seedu/contact/ContactList.java | 59 +++++-------------- .../java/seedu/contact/PersonalContact.java | 46 --------------- src/main/java/seedu/duke/Duke.java | 6 +- .../parser/AddPersonalContactParser.java | 9 ++- .../java/seedu/storage/ContactsDecoder.java | 12 ++-- .../java/seedu/storage/ContactsEncoder.java | 3 +- src/main/java/seedu/storage/Storage.java | 7 +-- src/main/java/seedu/ui/TextUi.java | 9 ++- 11 files changed, 88 insertions(+), 157 deletions(-) delete mode 100644 src/main/java/seedu/contact/PersonalContact.java diff --git a/src/main/java/seedu/command/Command.java b/src/main/java/seedu/command/Command.java index c5be696e04..185e6191ce 100644 --- a/src/main/java/seedu/command/Command.java +++ b/src/main/java/seedu/command/Command.java @@ -1,17 +1,17 @@ package seedu.command; +import seedu.contact.Contact; import seedu.contact.ContactList; -import seedu.contact.PersonalContact; public abstract class Command { protected ContactList contactList; - protected PersonalContact personalContact; + protected Contact personalContact; public void setContactList(ContactList contactList) { this.contactList = contactList; } - public void setPersonalContact(PersonalContact personalContact) { + public void setPersonalContact(Contact personalContact) { this.personalContact = personalContact; } diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index e801520aee..fc522785ae 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -1,6 +1,7 @@ package seedu.command; import seedu.contact.Contact; +import seedu.contact.ContactComparator; import seedu.contact.ContactList; import seedu.exception.InvalidFlagException; import seedu.ui.TextUi; @@ -33,7 +34,8 @@ public void execute() { updatePersonalContact(); } else { Contact preEditContact = duplicateContact(contactList.getContactAtIndex(contactIndex)); - Contact postEditContact = editTempContact(contactDetails,preEditContact); + preEditContact.editContact(contactDetails); + Contact postEditContact = preEditContact; handleDuplicates(postEditContact); } } catch (IndexOutOfBoundsException | InvalidFlagException e) { @@ -41,8 +43,8 @@ public void execute() { } } - private void updatePersonalContact() { - personalContact.editPersonalContact(contactDetails); + private void updatePersonalContact() throws InvalidFlagException { + personalContact.editContact(contactDetails); TextUi.editPersonalContactMessage(personalContact); } @@ -55,11 +57,14 @@ private void handleDuplicates(Contact postEditContact) throws IndexOutOfBoundsEx } private void updateContact(Contact postEditContact) - throws IndexOutOfBoundsException, InvalidFlagException { - contactList.editContact(contactDetails, contactIndex); + throws IndexOutOfBoundsException { + contactList.editContact(contactDetails,contactIndex); + //sort the contact list based on name after a contact has been edited + contactList.sortContacts(); TextUi.editContactMessage(postEditContact); } + private Boolean hasDuplicates(Contact postEditContact, ContactList contactList, int contactIndex) throws InvalidFlagException { ArrayList duplicatedIndex = new ArrayList<>(); @@ -104,39 +109,6 @@ private String stringCleaner(String input) { return input.replace(" ", "").toLowerCase(); } - - private Contact editTempContact(String[] contactDetails, Contact preEditContact) throws InvalidFlagException { - Contact tempContact = duplicateContact(preEditContact); - for (int i = 0; i < contactDetails.length; i++) { - if (contactDetails[i] != null) { - switch (i) { - case NAME_INDEX: - tempContact.setName(contactDetails[i]); - break; - case GITHUB_INDEX: - tempContact.setGithub(contactDetails[i]); - break; - case LINKEDIN_INDEX: - tempContact.setLinkedin(contactDetails[i]); - break; - case TELEGRAM_INDEX: - tempContact.setTelegram(contactDetails[i]); - break; - case TWITTER_INDEX: - tempContact.setTwitter(contactDetails[i]); - break; - case EMAIL_INDEX: - tempContact.setEmail(contactDetails[i]); - break; - default: - assert false; - throw new InvalidFlagException(); - } - } - } - return tempContact; - } - private String[] extractContactDetails(Contact contact) throws InvalidFlagException { String[] contactDetails = new String[NUMBER_OF_FIELDS]; for (int i = 0; i < NUMBER_OF_FIELDS; i++) { diff --git a/src/main/java/seedu/contact/Contact.java b/src/main/java/seedu/contact/Contact.java index 743a946833..f71bc8bf9f 100644 --- a/src/main/java/seedu/contact/Contact.java +++ b/src/main/java/seedu/contact/Contact.java @@ -1,6 +1,14 @@ package seedu.contact; +import seedu.exception.InvalidFlagException; + public class Contact { + public static final int NAME_INDEX = 0; + public static final int GITHUB_INDEX = 1; + public static final int LINKEDIN_INDEX = 2; + public static final int TELEGRAM_INDEX = 3; + public static final int TWITTER_INDEX = 4; + public static final int EMAIL_INDEX = 5; private String name; private String github; private String linkedin; @@ -17,6 +25,38 @@ public Contact(String name, String github, String linkedin, String telegram, Str this.email = email; } + //@@author ng-andre + public void editContact(String[] contactDetails) { + for (int i = 0; i < contactDetails.length; i++) { + if (contactDetails[i] != null) { + switch (i) { + case NAME_INDEX: + setName(contactDetails[i]); + break; + case GITHUB_INDEX: + setGithub(contactDetails[i]); + break; + case LINKEDIN_INDEX: + setLinkedin(contactDetails[i]); + break; + case TELEGRAM_INDEX: + setTelegram(contactDetails[i]); + break; + case TWITTER_INDEX: + setTwitter(contactDetails[i]); + break; + case EMAIL_INDEX: + setEmail(contactDetails[i]); + break; + default: + //control should never reach here + assert false; + } + } + } + } + + public String getName() { return name; } diff --git a/src/main/java/seedu/contact/ContactList.java b/src/main/java/seedu/contact/ContactList.java index 0df54368c5..a52076a194 100644 --- a/src/main/java/seedu/contact/ContactList.java +++ b/src/main/java/seedu/contact/ContactList.java @@ -5,16 +5,7 @@ import java.util.ArrayList; -import static seedu.parser.ContactParser.NUMBER_OF_FIELDS; - public class ContactList { - public static final int NAME_INDEX = 0; - public static final int GITHUB_INDEX = 1; - public static final int LINKEDIN_INDEX = 2; - public static final int TELEGRAM_INDEX = 3; - public static final int TWITTER_INDEX = 4; - public static final int EMAIL_INDEX = 5; - private ArrayList contacts; public ContactList() { @@ -23,46 +14,18 @@ public ContactList() { public void addContact(Contact contact) { contacts.add(contact); - contacts.sort(new ContactComparator()); - } - - //@@author ng-andre - public void editContact(String[] contactDetails, int contactIndex) throws InvalidFlagException { - for (int i = 0; i < contactDetails.length; i++) { - if (contactDetails[i] != null) { - switch (i) { - case NAME_INDEX: - contacts.get(contactIndex).setName(contactDetails[i]); - contacts.sort(new ContactComparator()); - break; - case GITHUB_INDEX: - contacts.get(contactIndex).setGithub(contactDetails[i]); - break; - case LINKEDIN_INDEX: - contacts.get(contactIndex).setLinkedin(contactDetails[i]); - break; - case TELEGRAM_INDEX: - contacts.get(contactIndex).setTelegram(contactDetails[i]); - break; - case TWITTER_INDEX: - contacts.get(contactIndex).setTwitter(contactDetails[i]); - break; - case EMAIL_INDEX: - contacts.get(contactIndex).setEmail(contactDetails[i]); - break; - default: - //control should never reach here - assert false; - throw new InvalidFlagException(); - } - } - } + sortContacts(); } public void deleteContact(int deletedIndex) { contacts.remove(deletedIndex); } + public void editContact(String[] contactDetails, int editIndex) { + Contact contactToEdit = getContactAtIndex(editIndex); + contactToEdit.editContact(contactDetails); + } + //@@author ng-andre private boolean hasDetailMatches(String query, int detailType, int index, Contact contact) { String[] contactStringArray = contact.getContactStringArray(); @@ -93,10 +56,18 @@ public int getIndexOfContact(Contact contact) { } public Contact getContactAtIndex(int index) { - contacts.sort(new ContactComparator()); + sortContacts(); return contacts.get(index); } + public ArrayList getContactList() { + return contacts; + } + + public void sortContacts() { + contacts.sort(new ContactComparator()); + } + public int getListSize() { return contacts.size(); } diff --git a/src/main/java/seedu/contact/PersonalContact.java b/src/main/java/seedu/contact/PersonalContact.java deleted file mode 100644 index 1984e9dcbd..0000000000 --- a/src/main/java/seedu/contact/PersonalContact.java +++ /dev/null @@ -1,46 +0,0 @@ -package seedu.contact; - -public class PersonalContact extends Contact { - public static final int NAME_INDEX = 0; - public static final int GITHUB_INDEX = 1; - public static final int LINKEDIN_INDEX = 2; - public static final int TELEGRAM_INDEX = 3; - public static final int TWITTER_INDEX = 4; - public static final int EMAIL_INDEX = 5; - - public PersonalContact(String name, String github, String linkedin, String telegram, String twitter, String email) { - super(name, github, linkedin, telegram, twitter, email); - } - - public void editPersonalContact(String[] contactDetails) { - for (int i = 0; i < contactDetails.length; i++) { - if (contactDetails[i] != null) { - switch (i) { - case NAME_INDEX: - setName(contactDetails[i]); - break; - case GITHUB_INDEX: - setGithub(contactDetails[i]); - break; - case LINKEDIN_INDEX: - setLinkedin(contactDetails[i]); - break; - case TELEGRAM_INDEX: - setTelegram(contactDetails[i]); - break; - case TWITTER_INDEX: - setTwitter(contactDetails[i]); - break; - case EMAIL_INDEX: - setEmail(contactDetails[i]); - break; - default: - //control should never reach here - assert false; - break; - } - } - } - } - -} diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index bc0d7931d2..ad96c926e8 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -3,7 +3,6 @@ import seedu.command.Command; import seedu.contact.Contact; import seedu.contact.ContactList; -import seedu.contact.PersonalContact; import seedu.exception.FileErrorException; import seedu.parser.MainParser; import seedu.storage.ContactsDecoder; @@ -18,7 +17,7 @@ public class Duke { private MainParser parser; private ContactList contactList; private String personalContactFilePath; - private PersonalContact personalContact; + private Contact personalContact; private final ContactsDecoder contactsDecoder; private final ContactsEncoder contactsEncoder; @@ -64,6 +63,7 @@ private void runCommandProcedure(Command command) { * Main entry-point for the java.duke.Duke application. */ public static void main(String[] args) { - new Duke("data/contacts.txt", "data/me.txt").runConTech(); + new Duke("data/contacts.txt", + "data/me.txt").runConTech(); } } diff --git a/src/main/java/seedu/parser/AddPersonalContactParser.java b/src/main/java/seedu/parser/AddPersonalContactParser.java index 66d0a50cd8..e92b30747d 100644 --- a/src/main/java/seedu/parser/AddPersonalContactParser.java +++ b/src/main/java/seedu/parser/AddPersonalContactParser.java @@ -1,7 +1,7 @@ package seedu.parser; import seedu.contact.Contact; -import seedu.contact.PersonalContact; + import seedu.exception.InvalidGithubUsernameException; import seedu.exception.InvalidNameException; import seedu.exception.InvalidTelegramUsernameException; @@ -13,11 +13,10 @@ import seedu.ui.UserInputTextUi; public class AddPersonalContactParser extends RegexParser { - private PersonalContact personalContact; + private Contact personalContact; public AddPersonalContactParser() { - personalContact = new PersonalContact(null, null,null,null, - null,null); + personalContact = new Contact(null, null,null,null, null,null); } public void collectPersonalDetails() { @@ -218,7 +217,7 @@ private void setParsedLinkedinUsername(String userInput) { } } - public PersonalContact getPersonalContact() { + public Contact getPersonalContact() { return personalContact; } } \ No newline at end of file diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index fae10b0818..a391aa156e 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -3,7 +3,6 @@ import seedu.contact.Contact; import seedu.contact.ContactList; import seedu.contact.DetailType; -import seedu.contact.PersonalContact; import seedu.exception.FileErrorException; import seedu.exception.InvalidEmailException; import seedu.exception.InvalidFlagException; @@ -40,10 +39,9 @@ public ContactList readContacts(File contactFile, String contactFilePath) throws return updatedContactList; } - public PersonalContact readPersonalContact(File personalContactFile) + public Contact readPersonalContact(File personalContactFile) throws FileErrorException { - PersonalContact personalContact = new PersonalContact(null, null, null, null, - null, null); + Contact personalContact = new Contact(null, null, null, null, null, null); try { Scanner fileScanner = new Scanner(personalContactFile); if (fileScanner.hasNext()) { @@ -57,8 +55,8 @@ public PersonalContact readPersonalContact(File personalContactFile) } - private PersonalContact decodePersonalContact(String contactText, PersonalContact contact) { - PersonalContact personalContact = contact; + private Contact decodePersonalContact(String contactText, Contact contact) { + Contact personalContact = contact; try { String[] compiledDetails = decodeDetails(contactText); String contactName = compiledDetails[DetailType.NAME.getIndex()]; @@ -67,7 +65,7 @@ private PersonalContact decodePersonalContact(String contactText, PersonalContac String contactTelegram = compiledDetails[DetailType.TELEGRAM.getIndex()]; String contactTwitter = compiledDetails[DetailType.TWITTER.getIndex()]; String contactEmail = compiledDetails[DetailType.EMAIL.getIndex()]; - personalContact = new PersonalContact(contactName, contactGithub, contactLinkedin, contactTelegram, + personalContact = new Contact(contactName, contactGithub, contactLinkedin, contactTelegram, contactTwitter, contactEmail); } catch (IndexOutOfBoundsException e) { ExceptionTextUi.corruptPersonalContactMessage(); diff --git a/src/main/java/seedu/storage/ContactsEncoder.java b/src/main/java/seedu/storage/ContactsEncoder.java index 4012b45b6e..90e9ce7b39 100644 --- a/src/main/java/seedu/storage/ContactsEncoder.java +++ b/src/main/java/seedu/storage/ContactsEncoder.java @@ -2,7 +2,6 @@ import seedu.contact.Contact; import seedu.contact.ContactList; -import seedu.contact.PersonalContact; import seedu.exception.FileErrorException; import java.io.FileWriter; @@ -11,7 +10,7 @@ import static seedu.storage.Storage.SEPARATOR; public class ContactsEncoder { - public void savePersonalContact(String contactFilePath, PersonalContact personalContact) throws FileErrorException { + public void savePersonalContact(String contactFilePath, Contact personalContact) throws FileErrorException { try { FileWriter fileWriter = new FileWriter(contactFilePath); String encodedContact = encodeContact(personalContact); diff --git a/src/main/java/seedu/storage/Storage.java b/src/main/java/seedu/storage/Storage.java index 52fec09137..d96bcbe97f 100644 --- a/src/main/java/seedu/storage/Storage.java +++ b/src/main/java/seedu/storage/Storage.java @@ -2,7 +2,6 @@ import seedu.contact.Contact; import seedu.contact.ContactList; -import seedu.contact.PersonalContact; import seedu.exception.FileErrorException; import seedu.parser.AddPersonalContactParser; import seedu.ui.TextUi; @@ -78,17 +77,17 @@ public ContactList loadExistingContacts() throws FileErrorException { return contactsDecoder.readContacts(contactFile, contactFilePath); } - public PersonalContact loadExistingPersonalContact() throws FileErrorException { + public Contact loadExistingPersonalContact() throws FileErrorException { if (!hasExistingPersonalContactFile() || hasEmptyExistingPersonalContactFile()) { isFirstRun = true; // get new contact's name AddPersonalContactParser addPersonalContactParser = new AddPersonalContactParser(); addPersonalContactParser.collectPersonalDetails(); - PersonalContact personalContact = addPersonalContactParser.getPersonalContact(); + Contact personalContact = addPersonalContactParser.getPersonalContact(); contactsEncoder.savePersonalContact(personalContactFilePath, personalContact); return personalContact; } - PersonalContact personalContact = contactsDecoder.readPersonalContact(personalContactFile); + Contact personalContact = contactsDecoder.readPersonalContact(personalContactFile); contactsEncoder.savePersonalContact(personalContactFilePath, personalContact); TextUi.welcomeBackMessage(personalContact); return personalContact; diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index c91ecfbacb..86c8148af7 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -1,7 +1,6 @@ package seedu.ui; import seedu.contact.Contact; -import seedu.contact.PersonalContact; import seedu.contact.ContactList; import java.util.ArrayList; @@ -36,14 +35,14 @@ public static void welcomeMessage() { printTopLineMessage(LOGO); } - public static void welcomeBackMessage(PersonalContact personalContact) { + public static void welcomeBackMessage(Contact personalContact) { printDoubleLineMessage(LOGO); String message = "Hello, " + personalContact.getName() + ". \nWelcome back to ConTech, " + "your personal contact tracker."; printBottomLineMessage(message); } - public static void greetingMessage(PersonalContact personalContact) { + public static void greetingMessage(Contact personalContact) { String message = "Hello there, " + personalContact.getName() + ".\n\n" + "This is ConTech, your very own contact tracking application\n" + "to manage tech-related contacts, like GitHub Accounts or\n" @@ -170,13 +169,13 @@ public static void searchNoResultsFoundMessage() { printDoubleLineMessage(message); } - public static void viewPersonalContactMessage(PersonalContact personalContact) { + public static void viewPersonalContactMessage(Contact personalContact) { String personalName = ViewMessageFormatterUi.viewNameFormatter(personalContact); String message = "Name: " + personalName + formatContactFields(personalContact); printDoubleLineMessage(message); } - public static void editPersonalContactMessage(PersonalContact personalContact) { + public static void editPersonalContactMessage(Contact personalContact) { String message = "ConTech has edited your personal contact:\n" + "Name: " + personalContact.getName() + formatContactFields(personalContact); From 0cb8ac131fe74b5b93c7f2640925c416e4d45f7f Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Fri, 22 Oct 2021 12:18:25 +0800 Subject: [PATCH 421/756] Add getSearchInput method for obtaining input without flag --- .../seedu/parser/SearchContactParser.java | 54 +++++++++++-------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/src/main/java/seedu/parser/SearchContactParser.java b/src/main/java/seedu/parser/SearchContactParser.java index 04930c06b6..f5b80f7420 100644 --- a/src/main/java/seedu/parser/SearchContactParser.java +++ b/src/main/java/seedu/parser/SearchContactParser.java @@ -4,39 +4,51 @@ import seedu.exception.InvalidFlagException; import seedu.exception.MissingArgException; +import java.util.Locale; + +import static seedu.parser.ContactParser.NUMBER_OF_DETAILS; import static seedu.parser.ContactParser.NUMBER_OF_SEARCH_ARGS; public class SearchContactParser implements ContactDetails { //return only search query as a String - public String parseSearchQuery(String userInput) throws MissingArgException { - String[] destructuredInputs = userInput.trim().split(" ", NUMBER_OF_SEARCH_ARGS); - if (destructuredInputs.length == 2) { //search for name if no flag specified - if (destructuredInputs[1].trim().charAt(0) == '-') { //if only flag is specified + public String parseSearchQuery(String searchInput) throws MissingArgException { + String[] destructuredInputs = searchInput.trim().split(" ", NUMBER_OF_SEARCH_ARGS); + if (searchInput.trim().charAt(0) == '-') { //if there is a flag, remove it + if (destructuredInputs.length < 2) { //input starts with - but only flag or weird input throw new MissingArgException(); } + //contains flag and search query return destructuredInputs[1].toLowerCase().trim(); - } else if (destructuredInputs.length == NUMBER_OF_SEARCH_ARGS) { //search for name with flag - return destructuredInputs[2].toLowerCase().trim(); } - //no query specified - //destructuredInputs.length < 2 - throw new MissingArgException(); + //assert no flag exists therefore searchInput is the search query + return searchInput; + } + + public int getDetailFlag(String searchInput) throws MissingArgException, InvalidFlagException { + //userInput is not null since searchInput was obtained from getSearchInput + System.out.println(searchInput.trim().charAt(0)); + if (searchInput.trim().charAt(0) == '-') { + //if a flag is specified then parse the flag + //handles inputs "search -g" which is missing search query + String[] destructuredInputs = searchInput.trim().split(" ", NUMBER_OF_DETAILS); + if (destructuredInputs.length < 2) { //input starts with - but only flag or weird input + throw new MissingArgException(); + } + String flag = destructuredInputs[0].trim().substring(1); + return getIndexToStore(flag); + } + //no flag is specified + return DetailType.NAME.getIndex(); //search names } - public int getDetailFlag(String userInput) throws MissingArgException, InvalidFlagException { - String[] destructuredInputs = userInput.trim().split(" ", NUMBER_OF_SEARCH_ARGS); - //"search " with one or two spaces should not have an issue since the input is trimmed + public String getSearchInput(String userInput) throws MissingArgException { + //remove the search command + String[] destructuredInputs = userInput.trim().split(" ", NUMBER_OF_DETAILS); if (destructuredInputs.length < 2) { //no arguments specified, only "search" throw new MissingArgException(); - } else if (destructuredInputs.length == 2) { //no flag specified - return DetailType.NAME.getIndex(); //search names - } else { - assert destructuredInputs.length == 3; - if (destructuredInputs[1].contains("-")) { //check for flag - String flag = destructuredInputs[1].trim().substring(1); - return getIndexToStore(flag); - } - throw new InvalidFlagException(); } + assert destructuredInputs.length == 2; + return destructuredInputs[1]; } + } From 2c843f3aedfbbb6a86c705c3864685593a9b0c8d Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Fri, 22 Oct 2021 12:18:36 +0800 Subject: [PATCH 422/756] Update MainParser to use searchInput --- src/main/java/seedu/parser/MainParser.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 0ecaac17c6..0a9630e4ed 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -197,8 +197,10 @@ private Command parseDeleteContact(String userInput) { //@@author ng-andre private Command parseSearchCommand(String userInput) { try { - String query = searchContactParser.parseSearchQuery(userInput); - int detailFlag = searchContactParser.getDetailFlag(userInput); + //string contains at least "search" + String searchInput = searchContactParser.getSearchInput(userInput); + int detailFlag = searchContactParser.getDetailFlag(searchInput); + String query = searchContactParser.parseSearchQuery(searchInput); return new SearchContactCommand(query, detailFlag); } catch (MissingArgException e) { return new FailedCommand(FailedCommandType.MISSING_ARG); From b99d5ea07cddb4bf06e3f622a8e05475a91f3f7a Mon Sep 17 00:00:00 2001 From: lezong Date: Fri, 22 Oct 2021 12:20:44 +0800 Subject: [PATCH 423/756] Minor edits to ContactList --- src/main/java/seedu/command/EditContactCommand.java | 2 +- src/main/java/seedu/contact/ContactList.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index fc522785ae..97f86c4fc2 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -58,7 +58,7 @@ private void handleDuplicates(Contact postEditContact) throws IndexOutOfBoundsEx private void updateContact(Contact postEditContact) throws IndexOutOfBoundsException { - contactList.editContact(contactDetails,contactIndex); + contactList.editContactAtIndex(contactDetails,contactIndex); //sort the contact list based on name after a contact has been edited contactList.sortContacts(); TextUi.editContactMessage(postEditContact); diff --git a/src/main/java/seedu/contact/ContactList.java b/src/main/java/seedu/contact/ContactList.java index a52076a194..99ef408aea 100644 --- a/src/main/java/seedu/contact/ContactList.java +++ b/src/main/java/seedu/contact/ContactList.java @@ -21,7 +21,7 @@ public void deleteContact(int deletedIndex) { contacts.remove(deletedIndex); } - public void editContact(String[] contactDetails, int editIndex) { + public void editContactAtIndex(String[] contactDetails, int editIndex) { Contact contactToEdit = getContactAtIndex(editIndex); contactToEdit.editContact(contactDetails); } From cc334d0d1130b9e792c4eed058c8732065ef1480 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Fri, 22 Oct 2021 12:31:18 +0800 Subject: [PATCH 424/756] Update logger level to FINE --- src/main/java/seedu/parser/RegexParser.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/seedu/parser/RegexParser.java b/src/main/java/seedu/parser/RegexParser.java index f126ac8518..d4ecf8d1c4 100644 --- a/src/main/java/seedu/parser/RegexParser.java +++ b/src/main/java/seedu/parser/RegexParser.java @@ -58,7 +58,7 @@ protected void checkEmailRegex(String detailToParse) throws InvalidEmailExceptio //allow lowercase email ids String emailRegex = "^([\\w-\\.]+){1,64}@([\\w&&[^_]]+){2,255}.[a-z]{2,}$"; if (!detailToParse.matches(emailRegex)) { - LOGGER.log(Level.INFO, "Regex check for Email id failed"); + //LOGGER.log(Level.INFO, "Regex check for Email id failed"); throw new InvalidEmailException(); } } @@ -67,7 +67,7 @@ protected void checkLinkedinUsernameRegex(String detailToParse) throws InvalidLi //allows lowercase, numbers, underscore and hyphen. Length must be 3-100 characters String linkedinRegex = "^[a-z0-9-_]{3,100}$"; if (!detailToParse.matches(linkedinRegex)) { - LOGGER.log(Level.INFO, "Regex check for Linkedin failed"); + LOGGER.log(Level.FINE, "Regex check for Linkedin failed"); throw new InvalidLinkedinUsernameException(); } } @@ -76,7 +76,7 @@ protected void checkTwitterUsernameRegex(String detailToParse) throws InvalidTwi //allows lowercase, numbers and underscore. Length must be max 15 characters String twitterRegex = "^[a-z0-9_]{1,15}$"; if (!detailToParse.matches(twitterRegex)) { - LOGGER.log(Level.INFO, "Regex check for Name failed"); + LOGGER.log(Level.FINE, "Regex check for Name failed"); throw new InvalidTwitterUsernameException(); } } @@ -85,7 +85,7 @@ protected void checkTelegramUsernameRegex(String detailToParse) throws InvalidTe //allows uppercase, lowercase, numbers and underscore. Length must be atleast 5 characters String telegramRegex = "^[a-zA-Z0-9_]{5,}$"; if (!detailToParse.matches(telegramRegex)) { - LOGGER.log(Level.INFO, "Regex check for Telegram username failed"); + LOGGER.log(Level.FINE, "Regex check for Telegram username failed"); throw new InvalidTelegramUsernameException(); } } @@ -97,7 +97,7 @@ protected void checkGithubUsernameRegex(String detailToParse) throws InvalidGith //Maximum is 39 characters. String githubUsernameRegex = "^[a-z\\d](?:[a-z\\d]|-(?=[a-z\\d])){0,39}$"; if (!detailToParse.matches(githubUsernameRegex)) { - LOGGER.log(Level.INFO, "Regex check for Github username failed"); + LOGGER.log(Level.FINE, "Regex check for Github username failed"); throw new InvalidGithubUsernameException(); } } @@ -106,7 +106,7 @@ protected void checkNameRegex(String detailToParse) throws InvalidNameException //only letters and spaces allowed String nameRegex = "^[ A-Za-z]+$"; if (!detailToParse.matches(nameRegex)) { - LOGGER.log(Level.INFO, "Regex check for name failed"); + LOGGER.log(Level.FINE, "Regex check for name failed"); throw new InvalidNameException(); } } From 4f28881c723b0cbf4e77b6422bcfec53227a9885 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Fri, 22 Oct 2021 12:31:45 +0800 Subject: [PATCH 425/756] Update constants for search parser --- src/main/java/seedu/parser/SearchContactParser.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/seedu/parser/SearchContactParser.java b/src/main/java/seedu/parser/SearchContactParser.java index f5b80f7420..6f50430445 100644 --- a/src/main/java/seedu/parser/SearchContactParser.java +++ b/src/main/java/seedu/parser/SearchContactParser.java @@ -6,14 +6,15 @@ import java.util.Locale; +import static seedu.parser.ContactParser.FLAG_INDEX_IN_DETAILS; import static seedu.parser.ContactParser.NUMBER_OF_DETAILS; import static seedu.parser.ContactParser.NUMBER_OF_SEARCH_ARGS; public class SearchContactParser implements ContactDetails { //return only search query as a String public String parseSearchQuery(String searchInput) throws MissingArgException { - String[] destructuredInputs = searchInput.trim().split(" ", NUMBER_OF_SEARCH_ARGS); - if (searchInput.trim().charAt(0) == '-') { //if there is a flag, remove it + String[] destructuredInputs = searchInput.trim().split(" ", NUMBER_OF_DETAILS); + if (searchInput.trim().charAt(FLAG_INDEX_IN_DETAILS) == '-') { //if there is a flag, remove it if (destructuredInputs.length < 2) { //input starts with - but only flag or weird input throw new MissingArgException(); } @@ -26,8 +27,7 @@ public String parseSearchQuery(String searchInput) throws MissingArgException { public int getDetailFlag(String searchInput) throws MissingArgException, InvalidFlagException { //userInput is not null since searchInput was obtained from getSearchInput - System.out.println(searchInput.trim().charAt(0)); - if (searchInput.trim().charAt(0) == '-') { + if (searchInput.trim().charAt(FLAG_INDEX_IN_DETAILS) == '-') { //if a flag is specified then parse the flag //handles inputs "search -g" which is missing search query String[] destructuredInputs = searchInput.trim().split(" ", NUMBER_OF_DETAILS); From 4e2add6fd66ca997e2160036ed27052429edde88 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Fri, 22 Oct 2021 14:56:36 +0800 Subject: [PATCH 426/756] Update constant for search parser --- .../java/seedu/parser/SearchContactParser.java | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/main/java/seedu/parser/SearchContactParser.java b/src/main/java/seedu/parser/SearchContactParser.java index 6f50430445..acd1560887 100644 --- a/src/main/java/seedu/parser/SearchContactParser.java +++ b/src/main/java/seedu/parser/SearchContactParser.java @@ -4,22 +4,19 @@ import seedu.exception.InvalidFlagException; import seedu.exception.MissingArgException; -import java.util.Locale; - import static seedu.parser.ContactParser.FLAG_INDEX_IN_DETAILS; import static seedu.parser.ContactParser.NUMBER_OF_DETAILS; -import static seedu.parser.ContactParser.NUMBER_OF_SEARCH_ARGS; public class SearchContactParser implements ContactDetails { //return only search query as a String public String parseSearchQuery(String searchInput) throws MissingArgException { String[] destructuredInputs = searchInput.trim().split(" ", NUMBER_OF_DETAILS); if (searchInput.trim().charAt(FLAG_INDEX_IN_DETAILS) == '-') { //if there is a flag, remove it - if (destructuredInputs.length < 2) { //input starts with - but only flag or weird input + if (destructuredInputs.length < NUMBER_OF_DETAILS) { //input starts with - but only flag or weird input throw new MissingArgException(); } //contains flag and search query - return destructuredInputs[1].toLowerCase().trim(); + return destructuredInputs[NUMBER_OF_DETAILS - 1].toLowerCase().trim(); } //assert no flag exists therefore searchInput is the search query return searchInput; @@ -31,10 +28,10 @@ public int getDetailFlag(String searchInput) throws MissingArgException, Invalid //if a flag is specified then parse the flag //handles inputs "search -g" which is missing search query String[] destructuredInputs = searchInput.trim().split(" ", NUMBER_OF_DETAILS); - if (destructuredInputs.length < 2) { //input starts with - but only flag or weird input + if (destructuredInputs.length < NUMBER_OF_DETAILS) { //input starts with - but only flag or weird input throw new MissingArgException(); } - String flag = destructuredInputs[0].trim().substring(1); + String flag = destructuredInputs[FLAG_INDEX_IN_DETAILS].trim().substring(1); return getIndexToStore(flag); } //no flag is specified @@ -44,11 +41,11 @@ public int getDetailFlag(String searchInput) throws MissingArgException, Invalid public String getSearchInput(String userInput) throws MissingArgException { //remove the search command String[] destructuredInputs = userInput.trim().split(" ", NUMBER_OF_DETAILS); - if (destructuredInputs.length < 2) { //no arguments specified, only "search" + if (destructuredInputs.length < NUMBER_OF_DETAILS) { //no arguments specified, only "search" throw new MissingArgException(); } - assert destructuredInputs.length == 2; - return destructuredInputs[1]; + assert destructuredInputs.length == NUMBER_OF_DETAILS; + return destructuredInputs[NUMBER_OF_DETAILS - 1]; } } From f9947adab8b3ed39961ddcb51cf39a115e048861 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Fri, 22 Oct 2021 14:57:50 +0800 Subject: [PATCH 427/756] Optimise imports --- src/main/java/seedu/command/AddContactCommand.java | 2 -- src/main/java/seedu/command/EditContactCommand.java | 1 - src/main/java/seedu/command/SearchContactCommand.java | 1 - src/main/java/seedu/contact/Contact.java | 3 --- src/main/java/seedu/parser/ContactParser.java | 3 --- src/main/java/seedu/parser/EditContactParser.java | 2 +- 6 files changed, 1 insertion(+), 11 deletions(-) diff --git a/src/main/java/seedu/command/AddContactCommand.java b/src/main/java/seedu/command/AddContactCommand.java index 394c192ee4..c6f63a6577 100644 --- a/src/main/java/seedu/command/AddContactCommand.java +++ b/src/main/java/seedu/command/AddContactCommand.java @@ -1,7 +1,6 @@ package seedu.command; import seedu.contact.Contact; -import seedu.contact.ContactComparator; import seedu.contact.ContactList; import seedu.contact.DetailType; import seedu.exception.InvalidFlagException; @@ -10,7 +9,6 @@ import seedu.ui.UserInputTextUi; import java.util.ArrayList; -import java.util.Arrays; public class AddContactCommand extends Command { private final String name; diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index 97f86c4fc2..5781271615 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -1,7 +1,6 @@ package seedu.command; import seedu.contact.Contact; -import seedu.contact.ContactComparator; import seedu.contact.ContactList; import seedu.exception.InvalidFlagException; import seedu.ui.TextUi; diff --git a/src/main/java/seedu/command/SearchContactCommand.java b/src/main/java/seedu/command/SearchContactCommand.java index 4caf5d93b3..de0d2e197c 100644 --- a/src/main/java/seedu/command/SearchContactCommand.java +++ b/src/main/java/seedu/command/SearchContactCommand.java @@ -1,7 +1,6 @@ package seedu.command; import seedu.exception.InvalidFlagException; -import seedu.exception.MissingDetailException; import seedu.ui.ExceptionTextUi; public class SearchContactCommand extends Command { diff --git a/src/main/java/seedu/contact/Contact.java b/src/main/java/seedu/contact/Contact.java index f71bc8bf9f..7403356249 100644 --- a/src/main/java/seedu/contact/Contact.java +++ b/src/main/java/seedu/contact/Contact.java @@ -1,7 +1,5 @@ package seedu.contact; -import seedu.exception.InvalidFlagException; - public class Contact { public static final int NAME_INDEX = 0; public static final int GITHUB_INDEX = 1; @@ -56,7 +54,6 @@ public void editContact(String[] contactDetails) { } } - public String getName() { return name; } diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index 6530b37d23..b73eb5b258 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -1,6 +1,5 @@ package seedu.parser; -import seedu.contact.DetailType; import seedu.exception.ForbiddenDetailException; import seedu.exception.InvalidEmailException; import seedu.exception.InvalidFlagException; @@ -12,7 +11,6 @@ import seedu.exception.MissingArgException; import seedu.exception.MissingDetailException; -import java.util.logging.Level; import java.util.logging.Logger; public abstract class ContactParser extends RegexParser implements ContactDetails { @@ -20,7 +18,6 @@ public abstract class ContactParser extends RegexParser implements ContactDetail public static final int NUMBER_OF_DETAILS = 2; public static final int NUMBER_OF_ADD_ARGS = 2; public static final int NUMBER_OF_EDIT_ARGS = 3; - public static final int NUMBER_OF_SEARCH_ARGS = 3; public static final int NUMBER_OF_FIELDS = 6; public static final String DETAIL_SEPARATOR = " -"; diff --git a/src/main/java/seedu/parser/EditContactParser.java b/src/main/java/seedu/parser/EditContactParser.java index eab541d548..d1b07d4051 100644 --- a/src/main/java/seedu/parser/EditContactParser.java +++ b/src/main/java/seedu/parser/EditContactParser.java @@ -31,7 +31,7 @@ public String[] parseContactDetails(String userInput) String[] destructuredInputs = (BUFFER + inputDetails[USER_INFO_INDEX]).split(DETAIL_SEPARATOR); //handles illegal input "edit 0 -" and "edit 0 [invalid string]" //valid input will take the form of [, -flag input] so min length should be 2 - if (destructuredInputs.length < 2) { + if (destructuredInputs.length < NUMBER_OF_EDIT_ARGS - 1) { throw new MissingArgException(); } From ba101f79a07fe4b0a79a11921a5d3489a1482d6e Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Fri, 22 Oct 2021 14:58:07 +0800 Subject: [PATCH 428/756] Simplify return statement for storage method --- src/main/java/seedu/storage/Storage.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/java/seedu/storage/Storage.java b/src/main/java/seedu/storage/Storage.java index d96bcbe97f..a41b9029b5 100644 --- a/src/main/java/seedu/storage/Storage.java +++ b/src/main/java/seedu/storage/Storage.java @@ -49,10 +49,7 @@ private boolean hasExistingPersonalContactFile() throws FileErrorException { } private boolean hasEmptyExistingPersonalContactFile() { - if (personalContactFile.exists() && personalContactFile.length() == 0) { - return true; - } - return false; + return personalContactFile.exists() && personalContactFile.length() == 0; } private boolean hasExistingContactFile() throws FileErrorException { From 55b282919d964033df38ae22d8ae30fe9e58adf6 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Fri, 22 Oct 2021 14:58:33 +0800 Subject: [PATCH 429/756] Update if conditions with IDE recommendation --- .../parser/AddPersonalContactParser.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/java/seedu/parser/AddPersonalContactParser.java b/src/main/java/seedu/parser/AddPersonalContactParser.java index e92b30747d..002631d7f7 100644 --- a/src/main/java/seedu/parser/AddPersonalContactParser.java +++ b/src/main/java/seedu/parser/AddPersonalContactParser.java @@ -24,7 +24,7 @@ public void collectPersonalDetails() { parsePersonalName(true); TextUi.greetingMessage(personalContact); String userConfirmation = UserInputTextUi.getUserConfirmation(); - if (userConfirmation != null || userConfirmation.isBlank()) { + if (userConfirmation.isBlank()) { parsePersonalGithubUsername(); parsePersonalTelegramUsername(); parsePersonalTwitterUsername(); @@ -36,7 +36,7 @@ public void collectPersonalDetails() { public void recallPersonalDetails() { String userConfirmation = UserInputTextUi.getUserConfirmation(); - if (userConfirmation != null || userConfirmation.isBlank()) { + if (userConfirmation.isBlank()) { parsePersonalName(false); parsePersonalGithubUsername(); parsePersonalTelegramUsername(); @@ -77,7 +77,7 @@ private void parsePersonalGithubUsername() { } private boolean checkGithubValidity(String userInput) throws InvalidGithubUsernameException { - if (userInput.isEmpty() || userInput == null) { + if (userInput.isEmpty()) { return true; } // if exception is thrown in there, it will not return true, so isValidDetail will remain false @@ -86,7 +86,7 @@ private boolean checkGithubValidity(String userInput) throws InvalidGithubUserna } private void setParsedGithubUsername(String userInput) { - if (userInput.isEmpty() || userInput == null) { + if (userInput.isEmpty()) { this.personalContact.setGithub(null); } else { this.personalContact.setGithub(userInput); @@ -108,7 +108,7 @@ private void parsePersonalTelegramUsername() { } private boolean checkTelegramValidity(String userInput) throws InvalidTelegramUsernameException { - if (userInput.isEmpty() || userInput == null) { + if (userInput.isEmpty()) { return true; } // if exception is thrown in there, it will not return true, so isValidDetail will remain false @@ -117,7 +117,7 @@ private boolean checkTelegramValidity(String userInput) throws InvalidTelegramUs } private void setParsedTelegramUsername(String userInput) { - if (userInput.isEmpty() || userInput == null) { + if (userInput.isEmpty()) { this.personalContact.setTelegram(null); } else { this.personalContact.setTelegram(userInput); @@ -139,7 +139,7 @@ private void parsePersonalTwitterUsername() { } private boolean checkTwitterValidity(String userInput) throws InvalidTwitterUsernameException { - if (userInput.isEmpty() || userInput == null) { + if (userInput.isEmpty()) { return true; } // if exception is thrown in there, it will not return true, so isValidDetail will remain false @@ -148,7 +148,7 @@ private boolean checkTwitterValidity(String userInput) throws InvalidTwitterUser } private void setParsedTwitterUsername(String userInput) { - if (userInput.isEmpty() || userInput == null) { + if (userInput.isEmpty()) { this.personalContact.setTwitter(null); } else { this.personalContact.setTwitter(userInput); @@ -170,7 +170,7 @@ private void parsePersonalEmailAddress() { } private boolean checkEmailValidity(String userInput) throws InvalidEmailException { - if (userInput.isEmpty() || userInput == null) { + if (userInput.isEmpty()) { return true; } // if exception is thrown in there, it will not return true, so isValidDetail will remain false @@ -179,7 +179,7 @@ private boolean checkEmailValidity(String userInput) throws InvalidEmailExceptio } private void setParsedEmailAddress(String userInput) { - if (userInput.isEmpty() || userInput == null) { + if (userInput.isEmpty()) { this.personalContact.setEmail(null); } else { this.personalContact.setEmail(userInput); @@ -201,7 +201,7 @@ private void parsePersonalLinkedinUsername() { } private boolean checkLinkedinValidity(String userInput) throws InvalidLinkedinUsernameException { - if (userInput.isEmpty() || userInput == null) { + if (userInput.isEmpty()) { return true; } // if exception is thrown in there, it will not return true, so isValidDetail will remain false @@ -210,7 +210,7 @@ private boolean checkLinkedinValidity(String userInput) throws InvalidLinkedinUs } private void setParsedLinkedinUsername(String userInput) { - if (userInput.isEmpty() || userInput == null) { + if (userInput.isEmpty()) { this.personalContact.setLinkedin(null); } else { this.personalContact.setLinkedin(userInput); From a23b641f61a33b15d1dbe18ae4d07815f044234a Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Fri, 22 Oct 2021 15:19:58 +0800 Subject: [PATCH 430/756] Merge branch 'master' into Edit-Duplicate # Conflicts: # src/main/java/seedu/command/EditContactCommand.java --- docs/diagrams/DeleteContactCommand.puml | 6 + .../DeleteContactCommandSequenceDiagram.png | Bin 42335 -> 41809 bytes .../seedu/command/EditContactCommand.java | 78 +++++----- src/main/java/seedu/contact/Contact.java | 40 +++++ src/main/java/seedu/contact/ContactList.java | 59 ++----- src/main/java/seedu/duke/Duke.java | 5 +- .../parser/AddPersonalContactParser.java | 145 ++++++++++++------ src/main/java/seedu/parser/ContactParser.java | 3 +- .../java/seedu/parser/EditContactParser.java | 9 +- src/main/java/seedu/parser/IndexParser.java | 8 +- .../java/seedu/storage/ContactsDecoder.java | 13 +- src/main/java/seedu/storage/Storage.java | 5 +- src/main/java/seedu/ui/ExceptionTextUi.java | 13 +- src/main/java/seedu/ui/TextUi.java | 31 ++-- text-ui-test/ACTUAL.TXT | 25 ++- text-ui-test/EXPECTED-UNIX.TXT | 25 ++- text-ui-test/EXPECTED.TXT | 25 ++- text-ui-test/input.txt | 3 + 18 files changed, 335 insertions(+), 158 deletions(-) diff --git a/docs/diagrams/DeleteContactCommand.puml b/docs/diagrams/DeleteContactCommand.puml index d9637c1118..a2c00a9d1c 100644 --- a/docs/diagrams/DeleteContactCommand.puml +++ b/docs/diagrams/DeleteContactCommand.puml @@ -13,6 +13,7 @@ deactivate ":IndexParser" activate ":DeleteContactCommand" ":DeleteContactCommand" -> ":TextUi":ConfirmDeleteMessage(deletedContact:Contact, contactIndex:int) activate ":TextUi" +":TextUi" --> ":DeleteContactCommand" deactivate ":TextUi" ":DeleteContactCommand" -> ":UserInputTextUi":getUserConfirmation() @@ -23,6 +24,7 @@ deactivate ":UserInputTextUi" alt#gold #lightgreen userConfirmation.equalsIgnoreCase("y") ":DeleteContactCommand" -> ":ContactList": deleteContact(contactIndex:int) activate ":ContactList" + ":ContactList" --> ":DeleteContactCommand" deactivate ":ContactList" ":DeleteContactCommand" -> ":Contact" :getName() activate ":Contact" @@ -36,12 +38,16 @@ alt#gold #lightgreen userConfirmation.equalsIgnoreCase("y") ":DeleteContactCommand" -> ":TextUi":deleteContactMessage(deletedName:String, contactListSize:int) activate ":TextUi" + ":TextUi" --> ":DeleteContactCommand" deactivate ":TextUi" + else #lightblue else ":DeleteContactCommand" -> ":TextUi":cancelDeleteContactMessage() activate ":TextUi" + ":TextUi" --> ":DeleteContactCommand" deactivate ":TextUi" + end deactivate ":DeleteContactCommand" deactivate ":DeleteContactCommand" diff --git a/docs/images/DeleteContactCommandSequenceDiagram.png b/docs/images/DeleteContactCommandSequenceDiagram.png index 981f3510e9a19b9a4d7ad1c39f5df931eb79b5a8..ce6e6dbeb218d95b875b2cb70d635edc7fc3194f 100644 GIT binary patch literal 41809 zcmcG$bzGEd`z<~Q3aFHn(x8Y4f^>({(t>n%cQ;BSh$syrNJ@8?ba!`&bVv?$?g8Cf z-TQsN=lst3@sIOyW}dm9JFaW3b*=01my!@dxsG=o0)e222=hOOK;Ro7kSm%NU~KLie3#vyiHUfMk7F}hnxgF9=lZ*pHKPT^i1noLnrMku*xQK75- z?6XInad$A2kN1j@TRjj$CB{Cqh|c709&dEn6RV^~Q^t|!@u@lZZBZw?g&O<1IP^M2 z^#um%c6g~iM$)l*JC}1)z~eNeKsc{~^ptj{52Go~@`1OWCsEryO)?wG8N63w+M5%k zOfp+J(1%f&j-(>4f86gW!QsB4=z1N|(y*V+MKTewBbJ&8>IOC!fs{4MROE z3L)c}v6|8ONcg<=QB#Z6&pufgdIq)^R}SrzjJtRpyb{?`pk}B-sg1=j&bXJ=mQmeE zHek9=L6QO2<1MGcUxdDIc{4~MUVt8TmilXNU@%sqM|p*(Aq!6Gys)r0U$|DctF8D= z4Y#b;2ZVP0zM77+YVlZS&s^FoN;Gtpo%hzD&klVj2$!mtcZjK5mzp(wZ0)i-ir0-) zH&zDtnR9xN`%Fg003ivsu_OXL~6Pi5uHJ=jE|)ey{|>rEgz=W@oY}W>~-{3uy z;(f04V2dXJ_r2(?r={Ky@iSs-Rn?B@s{IZf$$a^*r(DzZ-`CBDq7_%;MvbS$_EAZT zz+r*?33=VVarp{jTq_2D@p1+|((v;C2<9fl)H7LKPu%VAqT@=&(WwzY9EdVQ0&?>W z3@9`{#l8>r#GEDJd=MQ*soY!^m6D+2dsC1^qOxGz!4fj#nEUkMm$t-&IFBH!=j_)c zyk2d6G>}U%i7Ss@hHwACc2+ZrWZvZ2p?}3q;7Si`?R7)EAzYLo1e5pg`sggk2)qyl z3b=Jw2L{FZbB&C+`5hR7PnkGoMgd0Ppt)>*@w5oI;dNAL=Bo5=EQRt(fHuM!pG z^KCU!FuGo;zGVxHsNNqlHm^C|M|}|jUqFOs!F0O% zbZfT0$@nT{(-XUoF_RV#4|(JPMY8q`KPwVifSzmHkY|)2E1I2vnZw$ha$6uRm!bawuhfpOMDyTCu-pZAhc-CC&Z-GvP)d_u{110D|h02a2@gG1@Y{>Z;s_w8w?b9*ea&IvU|RVZrj_*xRPH# z!-Em5zf^h`P2CynjG_ldKyNw%9(`!wEd)BJY3mUK}0ke%@I=cuzon5w7MtG}2z4|(?{iM&foYau>0 z*zw174~rS(19xwN{NOH&jBlw_`=q15lnN%caSxS> zR(d%$Zd0*j_=0&-zzy+**LCo7T|8~UrkjX-@4{a;M{*?}lTOUuK&kL{ogLW~=V7@w z>KI0fnO-?+L>S^X!PXC^(o=FBYL)c$VVJ-bN*$fWBmTzho{V2Of%>OtFs6c z6k1Ms(x;8M?t|Hrd&BC)T>4!%%hT@!(^TsO&@E*7g!ra5`dhdRhc7a9bPX$a=e*T8 zZ>w9~!PXjib^DjOzUhdkWw|~^-pzGz16sG(;9pa{+o%10-1MV?_4m%ngEczT&FS;0 z&d}*|x3j)vw0N$HxVh!jrAh1VlA{koL3j=`yl_QWt~Cw~Nl7thhs^@|T_@`U>50>4 zcFd}nnG(3@QA*{~y;}VGvK!wVgzcx;wijCM4VQNJBiXF46AnLSwuM)R-)948J{L^?J&)Hil zqL)`q$t3Ho8s{vARWZ{gIFce5ZI^Nd&;PxHkUSk(JM*f_rlKcibAR zbw*_8yOI{*x1XtYc~1uht@!&-o*i{_t~?E<;5tS0`Gl|5HqZDd8dWk7bM`QMT~w_a zQ{9}aM(~TxhSucn_3gp-yNUjqAf6d&Fo^RozmTnLUd=~v!+$Ua4wk$e&UQKJH=Xa2 zC`26lJaHWM8f@!PRmn%9d|F6Q$25_5_o-8vgbDm7dbdNkp$68SgWA$(qx$NT@eO(D z_uB|JTL(2uTjF$dS<7m=2AjqZpK2`-G%|0r@TsM{1W7%5TS>f4 zaEE!Yl!5YyxAJ*}_3VMxr=;AiH`J-h$dh3=Q5N>KCgppFw_cv}vsN1)hssZh1c~3B zHKwREbMii1S;XjV$OUqfHehc#ZDm2hxQX#aYB=uxnFVq8!6ODzUIp=Q2Y?)uH{m6**bW>WLowbl1U zH@#L?&=l0v&Vn^JI44TU;0y>9R7j1pUGI)N@j#WJ2H0eqeJSEtlWB+9w}(~jRZZ4V z4yNOspu5a&B>)z@myDCSBFY12)GU)o__ta#>_3|D1+3Gw9HF<9lLDG(+M!=;~FR zWYM=l(2u*u+`lWxq-veTB2~CNoU_zSd|slEaNG>tlg#IQ_%JkHg5BNbjb@o>EDr9qtoi2}8zw{_TF$n z*GLW)0mjIsAwfGTtrkoR_sgs;vu-?D94#0>66#pw8vr|?@wU;51&vFbdR~`%&*#r$ zPli8CeAtkw-k;C-X6#VsPPXDUjH4c4`*Z*Ml)L=81w5kkh=cUmD9>6cyaUu=C!nXB z#{ICKEbl4B%#bo-L8be7OoKY(7EglKqD@oNRIU3e^o{$%jyO1T4NF{B&E;sVj4Y1= z%5vb2qt|BYN(i{1IPK^AB|P}i+ZOXbH~#jvAdWipV*SHuTn~?y+{>&MyT#pY&5!~E z;oqoMsBLpV)Lo6&s9|eNN<2J_Gw^i$+t$$t9&8m6s|%>t-#EjRKBy=@e4csiw0gvJE5({6D^T9AGR#|u zAG01{4Vh^@b{==i(^T$xVoX1VFhT#5BYnCEtuYK50uR|?gO z6Yie*H$3m(ePlGq9E_Hj-)+s;m)y_QbUoiqZLCI>1_2XGJFUHJ%hs)t{d7xE9&deRiKiyw z99dvLuGszDnT2hcPTOZ|KhbPw${`XKIxl9Cp5$lLq~nrd`tWzEm%X>3G=d*$UghFA zoG5S*()LJMP%MgmE|7MLaji}szPw0^oIc+>5v6gqKF592d49aul<$$ubLi<_4sC$1 zTB(KJ>QL5Lp?@@;Ho@_gcn5=e(QUuY>KI#)yp~h1ut(U0Z86*Ex-4;&`1tzvcJ~vz zm8xwh$SnPG%91~d#=0Tgdm*2B7?p4b?Pns-Z)!ds*f{RBS&m`19SDC!rTFU07oO-d zLryws8r1QUoaAer(M;IG7JpBmlr$q@LOQ>Xx6{#%x6QcO6z3ZLbm_J?F3}5u#HJ#V zBRoEkY;wL+4K33fOrKo~*xe=GN_Ab!p;ED*wABf{ex2UY`IT7;N6t1Kr>X=$;pW&} zyT@&RbcTjck!qwV`k$K^E_04$qu5=}TYqBR{-m2ef;k3a6p2&6FoOCZSR#d!6Yd9D z(BPhib~IK;;qd>>2Y%s9dz8wEdU&%xV)TC_CVvj&|A&jDX6r$DzcMgVd$GLga;wdO zAuFD@ZDV5$-vahl1Bh5oVww<^31xyyDVZqq6}#QYWZ z^QNK1gushidWks;0ldn%&FG4D3K}8%ZXF_Vk4MYQ66Ei1z7G$_%Rz%wqR0u~Q4aK> zxfm;wgcm#@y;+nQ$giXB3rX^k8rQfU@0V0H#}l7;=Pl5EtLz_5HTKB%YHNEozX#`0 zf*guXpC zaJ&@-sE{oZg>=@CFE}CXFGzA;+eO!kAwt%>*devAG?M3duPgJ?$a_}Oj~QNJAcUNi zITZc-wJya1Rs=n~%U8btq9nksP1;A69z?G?7-DxvOMeeYH z^lW6pLpYKC?+5=Mej4Rsz#e=WDKPaA0*4l%a}d6eza{>~ zyATw9@OEV6ZEX>)S`Rqq?5DrK6N1j8JyPv@oU2){@F6txxr&O*`o51)g=E`5Z-P6> zL|0eW$jHdXX1CC=Um~8nGXV3xm*i{^^$2K3=GTmMEj$^>K3A0uJJUo+(Qpta+nl@nML(Acwe1^z!cR zZk6+aTDgtk-pb$&9BPfm)8m7K)#04apFi7gP9dTZ$rg%+{H9ttb4n`?+hl z481`QN%*DK){}e4*uS{AD3dB-I-0M0es+4WKHeN~lH*vp-Gq-xAt76snU*FjE}pFQ z{Q0eO=uA@(ek*&4VgJ{orT8U1r>56;FfcFzR6FB&+?V^3sZ(`kzj#xlu`bn6pMGn6 zxw4bP9sgsKA!aLaH40_ zedzvr#rKC`$FP{)U_6dLw3bk4^GV^mfvHcRQcQ&Q`Qp@g(C$9&R|Xr=IxI`M1h1s5 zHXAX1qDNxs08XNl{HDR2nQiTpu$FcK61sX?D|4juLLGnhs`OU8#{;2 z#zP}5s)>*F%p6&wq}*zZ6xYwuPWC}`M!TOz*3c@oeh|x$EO4TNKp2q}qJNKkF(mBED4n6_ z6pLr`=9^gfY5(bi_@oqZnC!15k`5n?c|aNahhD#aotc@Lm`FCy41pMs6dp^wasDlM zx}wN`5GlbU=Luk*85ZN&AJOjSK3-EcuhN~kb`e?dFdp}x*Fn!ckQgpk%SbaN4(`9a z?m=Cz?w=?6Ep&6hfdKrGaK*b_=C@y8N7ys;iMj?sApL*-)|hK*GuJQY#52n7N(bY` zEv0!!*U7bRs+fP@!xdoRVIn)`QD=|8~ZHx+F?giH%2r|Hzk7(pbaBJS!>JY4J)9)eajG^$H9K zgqKgtSsbxwBgSxBE#||A4{zVrspH_{qTw<6)fD=@im_iWs)}8&yFPSaQbn#00z|zJ z3WFTs?98_!38uoSKDg|S*x5DouEIHm<;2Yjku?xhp5Db}RuZV#+$}}?B}o?#+eobr zh(&~j1>rG0WM;NoYzsRXQczTk0@09=kjr$eus>CDSgp#KUf~rHm(%*d^0$&iwohk4h%;t(PRqa3ya_aWOCysMoj^RW}#tbw)>Kn2Z$~0^(q!!p%J7 zLE-ZjGdVf=lhB(KSD=20Rwh&9(P@4`*k9fJ^5rQWgsSUDo{CsfSat5mHhQpGQ{2U{ zsM?^y9ik~*9kTR%oL9+zOUuoTn~;W+)1@VZbhGM!Xndi>+0>#Y#-Vp}EgTRVT;@#! z!o4qxl)vmXI>mlZ^?}sUh$snBQRO_X#&ns~jp}1FH+3;d$!QRVlSL!sa@49c>aNIP zZ5BOJDx9Hdt6du{Sbm`2{h_n1Et<&~hwAw>oAp;I%lW1t8_}-jyU%^eMY*InG(o&G0KcsGsR-oKw`3q6PTOPkRZ}bIL zoKFrdKj7bb8;DE0yh2wn5#q<%-(z!b8=LM2>p5QO=T)F z6<~nJY4@9SI5D?NscMBCz?VGE`)dGfeB-V%?7v^^zhBR@2u_-q9AlM!Ajj+A;He^G zd4O=M4yM}iJ3eq#yp4;StgtsPi&$O<17kUC8|vVq{Q$&fX=Uss^pyemmq34ie|%<> zQk&&l$JsTEUYhp6HgJ}#A-Ms)Y@({h)ZCxEUii)ExZ|}~}&s$qtADJ7rx3_~C zAIsNmKRZ3%94~o;t=|y|pjI76pQ`(}o&;GDVPS;=J(Qe?@NkJ(RyulmtCPd+_XUZ| z>*^DlYHDiTAGqe{=I9w19O13t)6>%#UneEqI}75<`~BuX&@!u7XU2OpdP9v7JLo(p zkY&o@l}}v&I9=-HHk9q+O9rkTa08d8YMEO+&?iIGq@FHLl*?Gx1ABC6ZcYpO>#LaYw zEiEnCuMRx|0Uo5}c=xliQsmNR5ZD2H)y}-~k-~<~e6l=jQK-aZy2r-A?puB^q63e=vHj(^0LDPT+39CXs5j_r4I+rbJQLr0W%Ng21Zd$Lb#g17lMLA6vY3n&8Qq4G7C+5J-y(}+Q3fG1y*Pj9Ibayc<_bGuEJ+v<14 z0-aYqp4(L}OUc$$`Fw<(u~|Ncgy0rrY<6EOnR3jvDqYj_2PNg#ZTFy^sOCvuw^A*} zn+fXg?`NQ=cc>~YbpTB4Bw4_OFnT^i9vu}KvTos=*Z2E$puna>{~)!mudnx$kdS~t z6#!ck9WUhMQc_X`g@hzynAdlg`!mx<@OGH0@dlu*Qh;+ld-hDBD=j@;Q^e8nXrc98 z`ssg!gT7P$TX4|mm7XxfAP7J3#a-TC*OK5BCRoeS)8${mj|2@Dmn(oh5j3hwRZe>^ zuijATos&~X5knhD6u7Zbi~_=b%vY=ZwNb#H6btn7$ZTU7^ii={%qE1thT%E_?B)ch zF~DNdv}fu5g@uK&v9W-E_c*jvwpH=Jv;af#{l`$mehej@&lgoFm>}T-4C!TCFLmj7 zQ?gmk@x##2k8xmOU_9A}uDT8PB#Ywi??z;ry0~ysJ#U_Ge)An*8I?+hx5I!WJ8Vpp z8JENyd`4*_h5JZoMlBZv`E9rUTpj?B-?n~ADld^7cbA$$Vc6I5otuO2>w!iPGNs)AMq`_%#YYV4V42_N+18Gq$b>rj{9zkA&@a1;U z&ND(VIM_?^x%yWOx<*lI=^hXmc)Z&$NqMwZ&|Mn!iHxC|45wrWYM|lt5ugVD>HYT3 zPH_20y5;Xo=HgP3G594fd){3hj@`h-@v8U$BL9|+)jZcQerwTh-2NK zB5oq1q=a|wvC|R7px8T57T_EFuK)lw?k52F>&}5kkmL%(x)=LY{O5Km9;dvSlZa%k z?SXWel1V#d6_p7e6#UXbDnNMHZH?N)9~~cT)|gLo%gLI@(P;z3>y-$m9*I5^?1toO z0H=+IGH3U|G4jWx0MRp;nCF9)9HVXaT*CLA9jE;@5uw(Ojs=vK7I3cm8~`-~yYub= zJ?AY{AF%XHwkoiRIlKy@X7HwDvH*))ul<&o81>a%>8tK9cA;QQcbL(8P39Hf>vAYsXXONP10&L%J9la%2#zBmFIq%$ zluI_UN~YKywm#NW_-vm%WhCGp zT$)i%WwP2sAdqv7xDO_#AgESgAl&=|O-Yv_%-q;B%+_Zh#KhF5Ruy%0WV`bXs3t&B zeIYAb30=uJn6T~!fcEt|LNE~*9x-tZ@Ha5%cddbnpJY5Yh!^zCJ3`XQVrm7C~6@FKbH?k0~~r982Isw7d!Oj>T)j_FoY1-v>sh2@qBl+zuw~ z`=x(VM)I6NG6zBeV6fkKPqZO(I*w+p!axdH5qIy0zbZGYL~I3gq{W2=z$rbO_`bf_ zAis5wZ>-9hg?kx@%)ECy%rkh!c{^-?SQSjb_O!K`*uA5Zf2k|3H9-1laDj4(S*C$y zM$R>zP=&WLs;Y!{?zCF1xWTlIf_r3SFFT0aQEZm`yt!iT&0`Z2cL$_!(1|zbQK#lf z1FmLf&`}181(j5ECEQ6r6phNMT^24W4Qw2Y#g&n~dBA_OC(WiZm<@bvRtD0UO~;V% z!N5E|HZ61^p4>ubm;{;v{hcEDtVb-EoiQwEN71>tkL3zW2jyP@F>`c_4lUma5P7|_ zk+>zWZ9tw{vfWV_9UY}k<;z`~*v(n~F8m?p{>eLdpICA&32n7}9T89-0w&KzRsXU* z(zjnvmID4-c3+i&xWEn!XMcp&kZ%ZYwY~_VKmJp9)^bz6YIH>_1<+9L(_NWoKyqd< zyPwwbI>N6ptB4!#WGAA=1*}zL8^>nl_ivxxE_|XhZ|J~YHC;%?SVtSj6Y?By_A||&ntShySlo*)&!#em}s^`Dze(^f5_-N@#Cbq!B9qJ#(o`r^NRK2($Z2Cd}fObu(h~t zSAhRPd4F@-9q7-QX;bXlO|Sj@kObi8K$@LCKRd{&IfH`TB=v>+OZ(#@euU9iDn)WnJbE@bxHjN^E#<D=|6U7+At_*a=S6=x=IX(nqa2~Kk(!P0m%R#0F&U) z77oA^Bj1%_v3Ljj?(zD~?rJljl8`#Sy*p{$S9InB>#c!6R<6K+9qM32l-`@f@7hhe z>Zj_}=jk;q6CKCJSU6Gt8StGV;1Wy zqRRwOyU=~FL$;{@?cG8BxMH~oc_NkKv%Q$=VG0M%fB zA93`??!aEJ|NE|nVL-L?-;NT%jvinO8uXNJIS}evAL{bs^uMHKzX$L-pc~TK-23Pcs91=ll2iFJDq5RtbbY0Qx^ecs4mD>LIy2Te$UIV$QYH_kT)uY#j|G0fieg3ybdaBa;>BbR z%1*V8F_3I&5TKn-58beX{thUG}bjA-#&O?~Cr7P79B*`iQXBmp_6| zwPV<9x8V72kY7b*2%ip)u77!X8Bn1UT}#XDk568Ct%s-02aWc`oiLVJ=V|e}vhEFy zWuUlykC{H1MRT7C!={qsgns+v#xaC8USdwnY!aEbVyCGa1L?%aHb-rbr>*gm`;`#0RlbO%(igMp7SRfb}I>Z zMQ2(&M!@Ni3t;{lc`vY`yPwPxuc#dz9Wj30+S(%J^Qk?_Ay~$z+gfxm*l(<%VwSS zfSZT8DuM@48{l)%IGVJd78hy-y2`U>N|g@VQ4IQG71j>qe=1!jrY~4XKAi(YnbgkN z@#ewGpy-;xSfHRNLpdnyb&`>iK9NqUx>UE`nw=a>g1QQoTqdjS3YJI$cgW$LH^&++aW^l0WO&h;TPi=TB>z0D|hcNFmd8q zo34qUBC**8)!u%|519`@?T0l9)K%K!cR|2Fw>X(j_7DS5nx7wGQl;^FDxivMPw++~ z4i6pVlExRnd34MchGAoTW-!1-EA4O#hh(6i4FulWSp>poLD7rJ8GniorRQhIlnL&{ z?kARcpA2*Iw3{WO=)DKPk`QDZKD44yt86*AgNxhDoqW38Oq_u>@WTaU|E*^hfFC(0 z#Y z(6C+|W(2fTlgJJa1wM#l!}b@a@@>$> z!!sHj4~u0|aY zB7u#o{lIZPh$SDb%4MgOVgbFy%?rwsG04^s3qUb{6>I{OeTNF$)j0O9XM6ydr3?g!a+kGMh)A|S9c znhj@9Libj|0jn?_XD(MZ|B27z_rNi`PxW~-&Pt0MH}LA!tDwxbkUH9asWUEo@xF1X zG%^>mOg+A8w8cm8}~Q_ zK7U603+e+egHoXZ29pDnyF7!T%qZ5U z{aU}49gnzyrYsmtaEF*UJ|?E!ebvsTxUG6$=gC<{{ksM!zv#Qd|tnUTfi$nTe~hSs=y=;$V<+fCv09buO4v zNHQ|x7EMNBGt%^}7l&9D9>S~Y0jPp1Ll7?sx*zn-1WtWH4tK_xRlA*I2I*^KmLKY* zkFI>xb^ZBPQ1LA77NW&5F`)Nio9|RLpT=TI&mAT_X)T=g9#a6Z5LW-Y;88EHe@(Jh zzUh9N!m*>|nsJ!jd^0|3zd{OM6avve`AeV#SWsap;GJ1?PqkAmeRr{KI?9Ye&<)F!m&=uU;QBzHC;Nr#5?0>40LoH1ve8h7%3Tmy!5d}biqAdv*)8bKgZ@UY54 z^zzD18`=`h?65IfGQBgEYsd7siE82SW9V@ofxpxdNOVa z`;Zixf_hreI1s3i!N=C3m!~;*0(pW?dVN|jM#X)4L<5GM#eCmggA7mro=A~1~)AKY$N{69;g6ov>T3 zXmL#7ha(!P!MoS7p_d7JFky+Uji0Y)M`4hJF?wo4Z;Y(LpD_Q&=m zhMG<*devMM!AFFApFB#+MgAF10D(bzAEh_r&I`&fK&Hn6n+0L$l6^zOe{4C}JAe8S zVctYuj(-yn{yP=>f5r9wjjR4jIrmIbK()H*dkFeG(?QOV=6 zD3kE;@K95m0G4A*d{cn{Wct_AZ$(u_YV(+UKY zx~Ar4SUm<*m4LVW_3N8w`Ij~9FLt5>mN!!dEaNX(%k6fV=g$q)hRqOR<3NJg?ofRoC($d< z%rqHDlg`V_1NDi8ro8-odSF>(XLka=!c@ul?5Y*YJDHv)bdKcU?id*v|273uf&Hrr z3^m7lt3r-H%G+_$GBWj{Kv@RN4V1;jqv#hwp*vI9Ro!9MdtDu z0IF|L(FI@$h{fwY3GkZ|Ya@Ag0hp$z4_yIlglSD?BCC-U13+EXY8STl2w*&2WBpP@Q}S{zgs2Q88o~> zSpx`@0Rh*aai1M(o8bVQF4h!rD?b51dToJTIcCE?uO**0;L%MLi+U==24MX3im@-) zPWq0(6ABWnqw`w;v2s&u7G42iSW$Y-cqKtRCNEa-DX>hICD1L+H3sfvH%vf7luFE0 z6%|{pp#I5#K2jsr7W^S?`1f`~U{m;u!_N#3Xv#!8Oq!aSnGeR=R'cB>a+%Ea$g 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%0A+B=ItvQ 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%0ALjya zh*Dv|DioyHt@fs2U#cy)jb#O6s`h;1_oe zy8G;JzyEhY1q1zsK>^UhYh~nHsSU55)v(mh_}PEAWivL-J?X+)Ih(a+!@k|erWBxF ze`6wua#cAbp~HZcz*{)BBPLVTFl4A43ayx6*KNefDh6+sFW6aL>w5u!lEWs3`J`ai zH(XDzo#bA5!PpK1zZVyr(z7syjAC)p2_|IvXfg(JlN-P%uhVJ7mHSPhd;Q=$Wbt`< z8;lFfngv_pV5dvSKw%aPHUy&pcl3OQJw>tiG?!iMXR0k*?rLSCSAnmm zW=@p?)gW+%3i;ur^6lmIlU6wF;m%oAyt>@`tIt+3jvzgIn|1k)Q6n8fm z1&Zg5yOqoM>h_v#Hef{;DRh4Yd~BWWIn}!z_b;XX}go^^%8|gR(Ur@wkpns)6^<>-!8`<=kt94i9J|5M=rSL~=7L@bhZnQu` z)Cx>g!FF+A(;EjNU`V{A+pR*IpA8^^m2$BvVuTYx;U;WY9rEWju$+W$91J7i>UOPj zK%IHnlaam)e8%0`Hx>q0dt1?*W~1P9HRTIPqa04CO%YZ?#+My?{<&d&#bOJvg{L9- z=q}jovnx$`3w%|| duplicatedIndex = new ArrayList<>(); @@ -81,6 +104,14 @@ private Contact duplicateContact(Contact contact) { return new Contact(name, github, linkedin, telegram, twitter, email); } + private boolean[] hasEditedFields(String[] contactDetails) { + boolean[] hasEditedField = new boolean[NUMBER_OF_FIELDS]; + for (int i = 0; i < NUMBER_OF_FIELDS; i++) { + hasEditedField[i] = (contactDetails[i] != null); + } + return hasEditedField; + } + private boolean hasDuplicateField(String input, String saved) { return stringCleaner(saved).equals(stringCleaner(input)); } @@ -89,39 +120,6 @@ private String stringCleaner(String input) { return input.replace(" ", "").toLowerCase(); } - - private Contact editTempContact(String[] contactDetails, Contact preEditContact) throws InvalidFlagException { - Contact tempContact = duplicateContact(preEditContact); - for (int i = 0; i < contactDetails.length; i++) { - if (contactDetails[i] != null) { - switch (i) { - case NAME_INDEX: - tempContact.setName(contactDetails[i]); - break; - case GITHUB_INDEX: - tempContact.setGithub(contactDetails[i]); - break; - case LINKEDIN_INDEX: - tempContact.setLinkedin(contactDetails[i]); - break; - case TELEGRAM_INDEX: - tempContact.setTelegram(contactDetails[i]); - break; - case TWITTER_INDEX: - tempContact.setTwitter(contactDetails[i]); - break; - case EMAIL_INDEX: - tempContact.setEmail(contactDetails[i]); - break; - default: - assert false; - throw new InvalidFlagException(); - } - } - } - return tempContact; - } - private String[] extractContactDetails(Contact contact) throws InvalidFlagException { String[] contactDetails = new String[NUMBER_OF_FIELDS]; for (int i = 0; i < NUMBER_OF_FIELDS; i++) { diff --git a/src/main/java/seedu/contact/Contact.java b/src/main/java/seedu/contact/Contact.java index 743a946833..f71bc8bf9f 100644 --- a/src/main/java/seedu/contact/Contact.java +++ b/src/main/java/seedu/contact/Contact.java @@ -1,6 +1,14 @@ package seedu.contact; +import seedu.exception.InvalidFlagException; + public class Contact { + public static final int NAME_INDEX = 0; + public static final int GITHUB_INDEX = 1; + public static final int LINKEDIN_INDEX = 2; + public static final int TELEGRAM_INDEX = 3; + public static final int TWITTER_INDEX = 4; + public static final int EMAIL_INDEX = 5; private String name; private String github; private String linkedin; @@ -17,6 +25,38 @@ public Contact(String name, String github, String linkedin, String telegram, Str this.email = email; } + //@@author ng-andre + public void editContact(String[] contactDetails) { + for (int i = 0; i < contactDetails.length; i++) { + if (contactDetails[i] != null) { + switch (i) { + case NAME_INDEX: + setName(contactDetails[i]); + break; + case GITHUB_INDEX: + setGithub(contactDetails[i]); + break; + case LINKEDIN_INDEX: + setLinkedin(contactDetails[i]); + break; + case TELEGRAM_INDEX: + setTelegram(contactDetails[i]); + break; + case TWITTER_INDEX: + setTwitter(contactDetails[i]); + break; + case EMAIL_INDEX: + setEmail(contactDetails[i]); + break; + default: + //control should never reach here + assert false; + } + } + } + } + + public String getName() { return name; } diff --git a/src/main/java/seedu/contact/ContactList.java b/src/main/java/seedu/contact/ContactList.java index 0df54368c5..99ef408aea 100644 --- a/src/main/java/seedu/contact/ContactList.java +++ b/src/main/java/seedu/contact/ContactList.java @@ -5,16 +5,7 @@ import java.util.ArrayList; -import static seedu.parser.ContactParser.NUMBER_OF_FIELDS; - public class ContactList { - public static final int NAME_INDEX = 0; - public static final int GITHUB_INDEX = 1; - public static final int LINKEDIN_INDEX = 2; - public static final int TELEGRAM_INDEX = 3; - public static final int TWITTER_INDEX = 4; - public static final int EMAIL_INDEX = 5; - private ArrayList contacts; public ContactList() { @@ -23,46 +14,18 @@ public ContactList() { public void addContact(Contact contact) { contacts.add(contact); - contacts.sort(new ContactComparator()); - } - - //@@author ng-andre - public void editContact(String[] contactDetails, int contactIndex) throws InvalidFlagException { - for (int i = 0; i < contactDetails.length; i++) { - if (contactDetails[i] != null) { - switch (i) { - case NAME_INDEX: - contacts.get(contactIndex).setName(contactDetails[i]); - contacts.sort(new ContactComparator()); - break; - case GITHUB_INDEX: - contacts.get(contactIndex).setGithub(contactDetails[i]); - break; - case LINKEDIN_INDEX: - contacts.get(contactIndex).setLinkedin(contactDetails[i]); - break; - case TELEGRAM_INDEX: - contacts.get(contactIndex).setTelegram(contactDetails[i]); - break; - case TWITTER_INDEX: - contacts.get(contactIndex).setTwitter(contactDetails[i]); - break; - case EMAIL_INDEX: - contacts.get(contactIndex).setEmail(contactDetails[i]); - break; - default: - //control should never reach here - assert false; - throw new InvalidFlagException(); - } - } - } + sortContacts(); } public void deleteContact(int deletedIndex) { contacts.remove(deletedIndex); } + public void editContactAtIndex(String[] contactDetails, int editIndex) { + Contact contactToEdit = getContactAtIndex(editIndex); + contactToEdit.editContact(contactDetails); + } + //@@author ng-andre private boolean hasDetailMatches(String query, int detailType, int index, Contact contact) { String[] contactStringArray = contact.getContactStringArray(); @@ -93,10 +56,18 @@ public int getIndexOfContact(Contact contact) { } public Contact getContactAtIndex(int index) { - contacts.sort(new ContactComparator()); + sortContacts(); return contacts.get(index); } + public ArrayList getContactList() { + return contacts; + } + + public void sortContacts() { + contacts.sort(new ContactComparator()); + } + public int getListSize() { return contacts.size(); } diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 5b706f97bc..ad96c926e8 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -52,6 +52,8 @@ private void runCommandProcedure(Command command) { command.setPersonalContact(personalContact); command.execute(); contactsEncoder.saveContacts(contactFilePath, contactList); + contactsEncoder.savePersonalContact(personalContactFilePath, personalContact); + } catch (FileErrorException e) { ExceptionTextUi.fileErrorMessage(contactFilePath); } @@ -61,6 +63,7 @@ private void runCommandProcedure(Command command) { * Main entry-point for the java.duke.Duke application. */ public static void main(String[] args) { - new Duke("data/contacts.txt", "data/me.txt").runConTech(); + new Duke("data/contacts.txt", + "data/me.txt").runConTech(); } } diff --git a/src/main/java/seedu/parser/AddPersonalContactParser.java b/src/main/java/seedu/parser/AddPersonalContactParser.java index 22c45d8354..e92b30747d 100644 --- a/src/main/java/seedu/parser/AddPersonalContactParser.java +++ b/src/main/java/seedu/parser/AddPersonalContactParser.java @@ -1,6 +1,7 @@ package seedu.parser; import seedu.contact.Contact; + import seedu.exception.InvalidGithubUsernameException; import seedu.exception.InvalidNameException; import seedu.exception.InvalidTelegramUsernameException; @@ -12,16 +13,15 @@ import seedu.ui.UserInputTextUi; public class AddPersonalContactParser extends RegexParser { - private Contact personalContact = new Contact(null, null,null,null, - null,null); - private boolean isValidDetail = false; + private Contact personalContact; public AddPersonalContactParser() { - TextUi.welcomeMessage(); + personalContact = new Contact(null, null,null,null, null,null); } - public void startCollectingPersonalDetails() { - parsePersonalName(); + public void collectPersonalDetails() { + TextUi.welcomeMessage(); + parsePersonalName(true); TextUi.greetingMessage(personalContact); String userConfirmation = UserInputTextUi.getUserConfirmation(); if (userConfirmation != null || userConfirmation.isBlank()) { @@ -29,13 +29,26 @@ public void startCollectingPersonalDetails() { parsePersonalTelegramUsername(); parsePersonalTwitterUsername(); parsePersonalEmailAddress(); - parsePersonalLinkedInUsername(); + parsePersonalLinkedinUsername(); TextUi.finishSetUpMessage(); } } - private void parsePersonalName() { - isValidDetail = false; + public void recallPersonalDetails() { + String userConfirmation = UserInputTextUi.getUserConfirmation(); + if (userConfirmation != null || userConfirmation.isBlank()) { + parsePersonalName(false); + parsePersonalGithubUsername(); + parsePersonalTelegramUsername(); + parsePersonalTwitterUsername(); + parsePersonalEmailAddress(); + parsePersonalLinkedinUsername(); + } + } + + private void parsePersonalName(boolean isFirstTime) { + boolean isValidDetail = false; + TextUi.promptPersonalNameMessage(isFirstTime); do { try { String personalName = UserInputTextUi.getUserInput(); @@ -50,116 +63,156 @@ private void parsePersonalName() { } private void parsePersonalGithubUsername() { - isValidDetail = false; - TextUi.promptPersonalGithubUsernameMessage(this.personalContact.getName()); + boolean isValidDetail = false; + TextUi.promptPersonalGithubUsernameMessage(); do { try { String personalGithubUsername = UserInputTextUi.getUserInput(); - setGithubIfValid(personalGithubUsername); + isValidDetail = checkGithubValidity(personalGithubUsername); + setParsedGithubUsername(personalGithubUsername); } catch (InvalidGithubUsernameException e) { ExceptionTextUi.invalidPersonalGithubUsernameErrorMessage(); } } while (!isValidDetail); } - private void setGithubIfValid(String userInput) throws InvalidGithubUsernameException { + private boolean checkGithubValidity(String userInput) throws InvalidGithubUsernameException { + if (userInput.isEmpty() || userInput == null) { + return true; + } + // if exception is thrown in there, it will not return true, so isValidDetail will remain false + checkGithubUsernameRegex(userInput); + return true; + } + + private void setParsedGithubUsername(String userInput) { if (userInput.isEmpty() || userInput == null) { - isValidDetail = true; + this.personalContact.setGithub(null); } else { - checkGithubUsernameRegex(userInput); - isValidDetail = true; this.personalContact.setGithub(userInput); } } private void parsePersonalTelegramUsername() { - isValidDetail = false; + boolean isValidDetail = false; TextUi.promptPersonalTelegramUsernameMessage(); do { try { - String personalTelegram = UserInputTextUi.getUserInput(); - setTelegramIfValid(personalTelegram); + String personalTelegramUsername = UserInputTextUi.getUserInput(); + isValidDetail = checkTelegramValidity(personalTelegramUsername); + setParsedTelegramUsername(personalTelegramUsername); } catch (InvalidTelegramUsernameException e) { ExceptionTextUi.invalidPersonalTelegramUsernameErrorMessage(); } } while (!isValidDetail); } - private void setTelegramIfValid(String userInput) throws InvalidTelegramUsernameException { + private boolean checkTelegramValidity(String userInput) throws InvalidTelegramUsernameException { if (userInput.isEmpty() || userInput == null) { - isValidDetail = true; + return true; + } + // if exception is thrown in there, it will not return true, so isValidDetail will remain false + checkTelegramUsernameRegex(userInput); + return true; + } + + private void setParsedTelegramUsername(String userInput) { + if (userInput.isEmpty() || userInput == null) { + this.personalContact.setTelegram(null); } else { - checkTelegramUsernameRegex(userInput); - isValidDetail = true; this.personalContact.setTelegram(userInput); } } private void parsePersonalTwitterUsername() { - isValidDetail = false; + boolean isValidDetail = false; TextUi.promptPersonalTwitterUsernameMessage(); do { try { - String personalTwitter = UserInputTextUi.getUserInput(); - setTwitterIfValid(personalTwitter); + String personalTwitterUsername = UserInputTextUi.getUserInput(); + isValidDetail = checkTwitterValidity(personalTwitterUsername); + setParsedTwitterUsername(personalTwitterUsername); } catch (InvalidTwitterUsernameException e) { ExceptionTextUi.invalidPersonalTwitterUsernameErrorMessage(); } } while (!isValidDetail); } - private void setTwitterIfValid(String userInput) throws InvalidTwitterUsernameException { + private boolean checkTwitterValidity(String userInput) throws InvalidTwitterUsernameException { + if (userInput.isEmpty() || userInput == null) { + return true; + } + // if exception is thrown in there, it will not return true, so isValidDetail will remain false + checkTwitterUsernameRegex(userInput); + return true; + } + + private void setParsedTwitterUsername(String userInput) { if (userInput.isEmpty() || userInput == null) { - isValidDetail = true; + this.personalContact.setTwitter(null); } else { - checkTwitterUsernameRegex(userInput); - isValidDetail = true; this.personalContact.setTwitter(userInput); } } private void parsePersonalEmailAddress() { - isValidDetail = false; + boolean isValidDetail = false; TextUi.promptPersonalEmailMessage(); do { try { - String personalEmail = UserInputTextUi.getUserInput(); - setEmailIfValid(personalEmail); + String personalEmailAddress = UserInputTextUi.getUserInput(); + isValidDetail = checkEmailValidity(personalEmailAddress); + setParsedEmailAddress(personalEmailAddress); } catch (InvalidEmailException e) { ExceptionTextUi.invalidPersonalEmailErrorMessage(); } } while (!isValidDetail); } - private void setEmailIfValid(String userInput) throws InvalidEmailException { + private boolean checkEmailValidity(String userInput) throws InvalidEmailException { if (userInput.isEmpty() || userInput == null) { - isValidDetail = true; + return true; + } + // if exception is thrown in there, it will not return true, so isValidDetail will remain false + checkEmailRegex(userInput); + return true; + } + + private void setParsedEmailAddress(String userInput) { + if (userInput.isEmpty() || userInput == null) { + this.personalContact.setEmail(null); } else { - checkEmailRegex(userInput); - isValidDetail = true; this.personalContact.setEmail(userInput); } } - private void parsePersonalLinkedInUsername() { - isValidDetail = false; - TextUi.promptPersonalLinkedInUsernameMessage(); + private void parsePersonalLinkedinUsername() { + boolean isValidDetail = false; + TextUi.promptPersonalLinkedinUsernameMessage(); do { try { - String personalLinkedIn = UserInputTextUi.getUserInput(); - setLinkedInIfValid(personalLinkedIn); + String personalLinkedinUsername = UserInputTextUi.getUserInput(); + isValidDetail = checkLinkedinValidity(personalLinkedinUsername); + setParsedLinkedinUsername(personalLinkedinUsername); } catch (InvalidLinkedinUsernameException e) { ExceptionTextUi.invalidPersonalLinkedinUsernameErrorMessage(); } } while (!isValidDetail); } - private void setLinkedInIfValid(String userInput) throws InvalidLinkedinUsernameException { + private boolean checkLinkedinValidity(String userInput) throws InvalidLinkedinUsernameException { + if (userInput.isEmpty() || userInput == null) { + return true; + } + // if exception is thrown in there, it will not return true, so isValidDetail will remain false + checkLinkedinUsernameRegex(userInput); + return true; + } + + private void setParsedLinkedinUsername(String userInput) { if (userInput.isEmpty() || userInput == null) { - isValidDetail = true; + this.personalContact.setLinkedin(null); } else { - checkLinkedinUsernameRegex(userInput); - isValidDetail = true; this.personalContact.setLinkedin(userInput); } } diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index 48ed4c22c4..6530b37d23 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -62,9 +62,8 @@ public void parseDetail(String[] contactDetails, String detail) if (detailToStore.equals("null")) { throw new ForbiddenDetailException(); } - int indexToStore; checkRegex(flag, detailToStore); - indexToStore = getIndexToStore(flag); + int indexToStore = getIndexToStore(flag); contactDetails[indexToStore] = detailToStore; } } diff --git a/src/main/java/seedu/parser/EditContactParser.java b/src/main/java/seedu/parser/EditContactParser.java index 034204dfd7..eab541d548 100644 --- a/src/main/java/seedu/parser/EditContactParser.java +++ b/src/main/java/seedu/parser/EditContactParser.java @@ -18,13 +18,15 @@ public String[] parseContactDetails(String userInput) throws InvalidFlagException, MissingDetailException, MissingArgException, ForbiddenDetailException, InvalidNameException, InvalidGithubUsernameException, InvalidTelegramUsernameException, InvalidLinkedinUsernameException, InvalidTwitterUsernameException, InvalidEmailException { + String[] inputDetails = userInput.split(" ", NUMBER_OF_EDIT_ARGS); if (inputDetails.length < NUMBER_OF_EDIT_ARGS) { //if arguments are missing e.g. edit 2 throw new MissingArgException(); } + assert (inputDetails.length == NUMBER_OF_EDIT_ARGS); - String[] contactDetails = new String[NUMBER_OF_FIELDS]; //initialise null array of strings + //buffer is used to ensure first flag can be read String[] destructuredInputs = (BUFFER + inputDetails[USER_INFO_INDEX]).split(DETAIL_SEPARATOR); //handles illegal input "edit 0 -" and "edit 0 [invalid string]" @@ -32,10 +34,13 @@ public String[] parseContactDetails(String userInput) if (destructuredInputs.length < 2) { throw new MissingArgException(); } + + //initialise null array of strings + String[] contactDetails = new String[NUMBER_OF_FIELDS]; for (int i = CONTACT_PARAMS_START_INDEX; i < destructuredInputs.length; i++) { parseDetail(contactDetails, destructuredInputs[i]); } + return contactDetails; } - } diff --git a/src/main/java/seedu/parser/IndexParser.java b/src/main/java/seedu/parser/IndexParser.java index 660576cab9..bfca60cd65 100644 --- a/src/main/java/seedu/parser/IndexParser.java +++ b/src/main/java/seedu/parser/IndexParser.java @@ -22,8 +22,14 @@ public static int getIndexFromInput(String userInput) assert destructuredInputs.length == 2; // split index string into words String[] indexSplit = destructuredInputs[INDEX_POSITION].trim().split(" "); + // contact index that is important and what we want + // can be "me" or an integer + String significantIndex = indexSplit[SIGNIFICANT_INDEX_POSITION].trim(); + if (significantIndex.equalsIgnoreCase("me")) { + return -1; + } // takes only the first word/ element as given user input, and throws NumberFormatExcept if it is not integer - return Integer.parseInt(indexSplit[SIGNIFICANT_INDEX_POSITION].trim()); + return Integer.parseInt(significantIndex); } public static Contact getContactFromIndex(int index, ContactList contactList) throws IndexOutOfBoundsException { diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index 8eb2a8c8dc..a391aa156e 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -11,6 +11,7 @@ import seedu.exception.InvalidNameException; import seedu.exception.InvalidTelegramUsernameException; import seedu.exception.InvalidTwitterUsernameException; +import seedu.parser.AddPersonalContactParser; import seedu.parser.RegexParser; import seedu.ui.ExceptionTextUi; @@ -38,7 +39,8 @@ public ContactList readContacts(File contactFile, String contactFilePath) throws return updatedContactList; } - public Contact readPersonalContact(File personalContactFile) throws FileErrorException { + public Contact readPersonalContact(File personalContactFile) + throws FileErrorException { Contact personalContact = new Contact(null, null, null, null, null, null); try { Scanner fileScanner = new Scanner(personalContactFile); @@ -67,13 +69,18 @@ private Contact decodePersonalContact(String contactText, Contact contact) { contactTwitter, contactEmail); } catch (IndexOutOfBoundsException e) { ExceptionTextUi.corruptPersonalContactMessage(); + AddPersonalContactParser addPersonalContactParser = new AddPersonalContactParser(); + addPersonalContactParser.recallPersonalDetails(); + return addPersonalContactParser.getPersonalContact(); } catch (InvalidFlagException e) { assert false; // Control should not arrive here since flags are predetermined by FLAG_SEQUENCE ExceptionTextUi.invalidFlagMessage(); } catch (InvalidGithubUsernameException | InvalidNameException | InvalidTelegramUsernameException | InvalidLinkedinUsernameException | InvalidTwitterUsernameException | InvalidEmailException e) { - // For @lezongmun, from @marcusbory - ExceptionTextUi.invalidNameInput(); + ExceptionTextUi.invalidPersonalContactFileMessage(); + AddPersonalContactParser addPersonalContactParser = new AddPersonalContactParser(); + addPersonalContactParser.recallPersonalDetails(); + return addPersonalContactParser.getPersonalContact(); } return personalContact; } diff --git a/src/main/java/seedu/storage/Storage.java b/src/main/java/seedu/storage/Storage.java index 63c6a4cac7..d96bcbe97f 100644 --- a/src/main/java/seedu/storage/Storage.java +++ b/src/main/java/seedu/storage/Storage.java @@ -55,7 +55,6 @@ private boolean hasEmptyExistingPersonalContactFile() { return false; } - private boolean hasExistingContactFile() throws FileErrorException { try { if (!contactFile.exists()) { @@ -83,14 +82,14 @@ public Contact loadExistingPersonalContact() throws FileErrorException { isFirstRun = true; // get new contact's name AddPersonalContactParser addPersonalContactParser = new AddPersonalContactParser(); - addPersonalContactParser.startCollectingPersonalDetails(); + addPersonalContactParser.collectPersonalDetails(); Contact personalContact = addPersonalContactParser.getPersonalContact(); contactsEncoder.savePersonalContact(personalContactFilePath, personalContact); return personalContact; } Contact personalContact = contactsDecoder.readPersonalContact(personalContactFile); + contactsEncoder.savePersonalContact(personalContactFilePath, personalContact); TextUi.welcomeBackMessage(personalContact); return personalContact; } - } diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index 8f42059cb2..cf16b9d1de 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -169,7 +169,18 @@ public static void corruptLineMessage(String line, int lineIndex, String contact } public static void corruptPersonalContactMessage() { - printBottomLineMessage("Your personal contact file at data/me.txt is corrupted and not loaded."); + String message = "Your personal contact file at data/me.txt is corrupted and\n" + + "not loaded. We would need to set up your personal contact\n" + + "again.\n\n" + + "Enter anything to continue..."; + printDoubleLineMessage(message); + } + + public static void invalidPersonalContactFileMessage() { + String message = "It seems that your personal contact at data/me.txt has been" + + "\naltered. We would need to set up your personal contact again.\n\n" + + "Enter anything to continue..."; + printDoubleLineMessage(message); } public static void forbiddenInputCommaMessage(String newUserInput) { diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 7f628c24e0..86c8148af7 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -2,9 +2,7 @@ import seedu.contact.Contact; import seedu.contact.ContactList; - import java.util.ArrayList; -import java.util.Scanner; public abstract class TextUi { private static final String LOGO = " _____ _______ _ \n" @@ -34,11 +32,7 @@ public static void printBottomLine() { } public static void welcomeMessage() { - printDoubleLineMessage(LOGO); - String message = "Welcome to ConTech, your personal contact tracker.\n" - + "Can I get your name?"; - printBottomLineMessage(message); - System.out.print("Name: "); + printTopLineMessage(LOGO); } public static void welcomeBackMessage(Contact personalContact) { @@ -66,7 +60,19 @@ public static void finishSetUpMessage() { printDoubleLineMessage(message); } - public static void promptPersonalGithubUsernameMessage(String personalName) { + public static void promptPersonalNameMessage(boolean isFirstTime) { + String message; + if (isFirstTime) { + message = "Welcome to ConTech, your personal contact tracker.\n" + + "Please provide us with your Name."; + } else { + message = "Please provide us with your Name."; + } + printDoubleLineMessage(message); + System.out.print("Name: "); + } + + public static void promptPersonalGithubUsernameMessage() { String message = "Please provide us with your Github Username\n" + "or press ENTER if you would like to skip."; printDoubleLineMessage(message); @@ -94,7 +100,7 @@ public static void promptPersonalEmailMessage() { System.out.print("Email Address: "); } - public static void promptPersonalLinkedInUsernameMessage() { + public static void promptPersonalLinkedinUsernameMessage() { String message = "Please provide us with your LinkedIn Username\n" + "or press ENTER if you would like to skip."; printDoubleLineMessage(message); @@ -169,6 +175,13 @@ public static void viewPersonalContactMessage(Contact personalContact) { printDoubleLineMessage(message); } + public static void editPersonalContactMessage(Contact personalContact) { + String message = "ConTech has edited your personal contact:\n" + + "Name: " + personalContact.getName() + + formatContactFields(personalContact); + printDoubleLineMessage(message); + } + public static void confirmDeleteMessage(Contact deletedContact, int deletedIndex) { String message = "Delete this contact? (y/n)\n" + deletedIndex + ". " + deletedContact.getName() + formatContactFields(deletedContact); diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index 068c693e2f..2b032e1c42 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -9,6 +9,7 @@ data/me.txt ____________________________________________________________ ____________________________________________________________ + _____ _______ _ / ____| |__ __| | | | | ___ _ __ | | ___ ___| |__ @@ -18,9 +19,8 @@ ____________________________________________________________ ____________________________________________________________ - Welcome to ConTech, your personal contact tracker. -Can I get your name? +Please provide us with your Name. ____________________________________________________________ Name: ____________________________________________________________ @@ -87,6 +87,27 @@ Email: lezongmun@gmail.com Telegram: t.me/lezongg ____________________________________________________________ +____________________________________________________________ +ConTech has edited your personal contact: +Name: Marcus Bory +Github: github.com/lezongmun +Email: lezongmun@gmail.com +Telegram: t.me/lezongg +____________________________________________________________ + +____________________________________________________________ +There seems to be missing parameters in your request. +Please specify your command. +____________________________________________________________ + +____________________________________________________________ +The email id is not correctly formatted, +Rules for email id : + * Lowercase letters only + * Numbers, underscore, hyphen and dot allowed + * @ cannot be at the start or end +____________________________________________________________ + ____________________________________________________________ There are no contacts stored in ConTech. ____________________________________________________________ diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index 068c693e2f..2b032e1c42 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -9,6 +9,7 @@ data/me.txt ____________________________________________________________ ____________________________________________________________ + _____ _______ _ / ____| |__ __| | | | | ___ _ __ | | ___ ___| |__ @@ -18,9 +19,8 @@ ____________________________________________________________ ____________________________________________________________ - Welcome to ConTech, your personal contact tracker. -Can I get your name? +Please provide us with your Name. ____________________________________________________________ Name: ____________________________________________________________ @@ -87,6 +87,27 @@ Email: lezongmun@gmail.com Telegram: t.me/lezongg ____________________________________________________________ +____________________________________________________________ +ConTech has edited your personal contact: +Name: Marcus Bory +Github: github.com/lezongmun +Email: lezongmun@gmail.com +Telegram: t.me/lezongg +____________________________________________________________ + +____________________________________________________________ +There seems to be missing parameters in your request. +Please specify your command. +____________________________________________________________ + +____________________________________________________________ +The email id is not correctly formatted, +Rules for email id : + * Lowercase letters only + * Numbers, underscore, hyphen and dot allowed + * @ cannot be at the start or end +____________________________________________________________ + ____________________________________________________________ There are no contacts stored in ConTech. ____________________________________________________________ diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 068c693e2f..2b032e1c42 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -9,6 +9,7 @@ data/me.txt ____________________________________________________________ ____________________________________________________________ + _____ _______ _ / ____| |__ __| | | | | ___ _ __ | | ___ ___| |__ @@ -18,9 +19,8 @@ ____________________________________________________________ ____________________________________________________________ - Welcome to ConTech, your personal contact tracker. -Can I get your name? +Please provide us with your Name. ____________________________________________________________ Name: ____________________________________________________________ @@ -87,6 +87,27 @@ Email: lezongmun@gmail.com Telegram: t.me/lezongg ____________________________________________________________ +____________________________________________________________ +ConTech has edited your personal contact: +Name: Marcus Bory +Github: github.com/lezongmun +Email: lezongmun@gmail.com +Telegram: t.me/lezongg +____________________________________________________________ + +____________________________________________________________ +There seems to be missing parameters in your request. +Please specify your command. +____________________________________________________________ + +____________________________________________________________ +The email id is not correctly formatted, +Rules for email id : + * Lowercase letters only + * Numbers, underscore, hyphen and dot allowed + * @ cannot be at the start or end +____________________________________________________________ + ____________________________________________________________ There are no contacts stored in ConTech. ____________________________________________________________ diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index 85145b3c96..d3ce1b0bb1 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -7,6 +7,9 @@ lezongg lezongmun@gmail.com me +edit me -n Marcus Bory +edit me +edit me -e lezongmun rm 1 add -n ng andre -g ng-andre rm 2 From 00e34433f79cf7dc2162c3eb04e047696309f4bb Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Fri, 22 Oct 2021 15:22:44 +0800 Subject: [PATCH 431/756] Refactor code due to checkstyle violation --- src/main/java/seedu/command/EditContactCommand.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index 9301522fb7..598a149167 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -81,11 +81,11 @@ private boolean hasDuplicates(Contact postEditContact, ContactList contactList, } if ((postEditContactDetails[j] != null && currentContactDetails[j] != null) && hasDuplicateField(postEditContactDetails[j], currentContactDetails[j])) { - duplicatedIndex.add(i); - break; - } + duplicatedIndex.add(i); + break; } } + } if (!duplicatedIndex.isEmpty()) { TextUi.confirmDuplicateMessage(duplicatedIndex, contactList, EDIT_TYPE); String userEditConfirmation = UserInputTextUi.getUserConfirmation(); From 72f60ae139fcd211e9751f716e7b9ae3d8c72eab Mon Sep 17 00:00:00 2001 From: lezong Date: Mon, 25 Oct 2021 01:28:05 +0800 Subject: [PATCH 432/756] Remove if branch in addPersonalContactParser --- .../parser/AddPersonalContactParser.java | 30 ++++++++----------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/src/main/java/seedu/parser/AddPersonalContactParser.java b/src/main/java/seedu/parser/AddPersonalContactParser.java index 002631d7f7..05d112d760 100644 --- a/src/main/java/seedu/parser/AddPersonalContactParser.java +++ b/src/main/java/seedu/parser/AddPersonalContactParser.java @@ -23,27 +23,23 @@ public void collectPersonalDetails() { TextUi.welcomeMessage(); parsePersonalName(true); TextUi.greetingMessage(personalContact); - String userConfirmation = UserInputTextUi.getUserConfirmation(); - if (userConfirmation.isBlank()) { - parsePersonalGithubUsername(); - parsePersonalTelegramUsername(); - parsePersonalTwitterUsername(); - parsePersonalEmailAddress(); - parsePersonalLinkedinUsername(); - TextUi.finishSetUpMessage(); - } + UserInputTextUi.getUserConfirmation(); + parsePersonalGithubUsername(); + parsePersonalTelegramUsername(); + parsePersonalTwitterUsername(); + parsePersonalEmailAddress(); + parsePersonalLinkedinUsername(); + TextUi.finishSetUpMessage(); } public void recallPersonalDetails() { String userConfirmation = UserInputTextUi.getUserConfirmation(); - if (userConfirmation.isBlank()) { - parsePersonalName(false); - parsePersonalGithubUsername(); - parsePersonalTelegramUsername(); - parsePersonalTwitterUsername(); - parsePersonalEmailAddress(); - parsePersonalLinkedinUsername(); - } + parsePersonalName(false); + parsePersonalGithubUsername(); + parsePersonalTelegramUsername(); + parsePersonalTwitterUsername(); + parsePersonalEmailAddress(); + parsePersonalLinkedinUsername(); } private void parsePersonalName(boolean isFirstTime) { From 2b74a98e62aacc364429d8fb246af6f1c7c93713 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Mon, 25 Oct 2021 11:45:20 +0800 Subject: [PATCH 433/756] Add author tag for Ashraf --- .../java/seedu/command/AddContactCommand.java | 2 ++ .../seedu/command/EditContactCommand.java | 23 ++++++++++--------- src/main/java/seedu/command/HelpCommand.java | 2 ++ .../seedu/command/ViewContactCommand.java | 2 ++ src/main/java/seedu/parser/MainParser.java | 2 +- src/main/java/seedu/ui/TextUi.java | 4 ++++ .../java/seedu/ui/ViewMessageFormatterUi.java | 2 ++ 7 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/main/java/seedu/command/AddContactCommand.java b/src/main/java/seedu/command/AddContactCommand.java index eeb794edb3..81279ae666 100644 --- a/src/main/java/seedu/command/AddContactCommand.java +++ b/src/main/java/seedu/command/AddContactCommand.java @@ -72,6 +72,7 @@ public void execute() { } } + //@@author ashrafjfr private boolean hasDuplicates(Contact addedContact, ContactList contactList) throws InvalidFlagException { ArrayList duplicatedIndex = new ArrayList<>(); String[] addedContactDetails = extractContactDetails(addedContact); @@ -131,4 +132,5 @@ private boolean hasDuplicateField(String input, String saved) { private String stringCleaner(String input) { return input.replace(" ", "").toLowerCase(); } + //@@author } diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index 1e44ee44a6..c86aee2115 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -63,7 +63,7 @@ private void updateContact(Contact postEditContact) throws IndexOutOfBoundsExcep TextUi.editContactMessage(postEditContact); } - + //@@author ashrafjfr private boolean hasDuplicates(Contact postEditContact, ContactList contactList, int contactIndex) throws InvalidFlagException { ArrayList duplicatedIndex = new ArrayList<>(); @@ -93,16 +93,6 @@ && hasDuplicateField(postEditContactDetails[j], currentContactDetails[j])) { return false; } - private Contact duplicateContact(Contact contact) { - String name = contact.getName(); - String github = contact.getGithub(); - String linkedin = contact.getLinkedin(); - String telegram = contact.getTelegram(); - String twitter = contact.getTwitter(); - String email = contact.getEmail(); - return new Contact(name, github, linkedin, telegram, twitter, email); - } - private boolean[] hasEditedFields(String[] contactDetails) { boolean[] hasEditedField = new boolean[NUMBER_OF_FIELDS]; for (int i = 0; i < NUMBER_OF_FIELDS; i++) { @@ -148,4 +138,15 @@ private String[] extractContactDetails(Contact contact) throws InvalidFlagExcept } return contactDetails; } + + //@@author ng-andre + private Contact duplicateContact(Contact contact) { + String name = contact.getName(); + String github = contact.getGithub(); + String linkedin = contact.getLinkedin(); + String telegram = contact.getTelegram(); + String twitter = contact.getTwitter(); + String email = contact.getEmail(); + return new Contact(name, github, linkedin, telegram, twitter, email); + } } diff --git a/src/main/java/seedu/command/HelpCommand.java b/src/main/java/seedu/command/HelpCommand.java index 0d337cd234..d9344cf3a6 100644 --- a/src/main/java/seedu/command/HelpCommand.java +++ b/src/main/java/seedu/command/HelpCommand.java @@ -1,3 +1,5 @@ +//@@author ashrafjfr + package seedu.command; import seedu.ui.TextUi; diff --git a/src/main/java/seedu/command/ViewContactCommand.java b/src/main/java/seedu/command/ViewContactCommand.java index b1717287a2..261875c837 100644 --- a/src/main/java/seedu/command/ViewContactCommand.java +++ b/src/main/java/seedu/command/ViewContactCommand.java @@ -1,3 +1,5 @@ +//@@author ashrafjfr + package seedu.command; import seedu.contact.Contact; diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 0a9630e4ed..e2ac58d6a7 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -170,7 +170,7 @@ private Command parseInvalidDetailCommand(Exception e) { return new FailedCommand(FailedCommandType.GENERAL); } - //@@author + //@@author ashrafjfr private Command parseViewContact(String userInput) { try { int viewedIndex = IndexParser.getIndexFromInput(userInput); diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 86c8148af7..f20229d2e5 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -135,6 +135,7 @@ public static void editContactMessage(Contact editedContact) { printDoubleLineMessage(message); } + //@@author ashrafjfr public static String formatContactFields(Contact addedContact) { String viewGithub = ViewMessageFormatterUi.viewGithubFormatter(addedContact); String viewEmail = ViewMessageFormatterUi.viewEmailFormatter(addedContact); @@ -150,6 +151,7 @@ public static void viewContactMessage(Contact viewingContact, int index) { printDoubleLineMessage(message); } + //@@author public static void printContactWithIndex(int index, String contactName) { System.out.println(index + ". " + contactName); } @@ -204,6 +206,7 @@ public static void exitMessage() { printDoubleLineMessage(message); } + //@@author ashrafjfr public static void helpMessage() { String message = "add: ConTech adds the specified contact with provided parameters.\n" + " Parameters: -n NAME -g GITHUB -e EMAIL -te TELEGRAM -l LINKEDIN -tw TWITTER\n" @@ -281,6 +284,7 @@ public static void ignoreContact(String type) { printDoubleLineMessage(message); } + //@@author public static void successfulImportMessage(int numberOfLines) { String message = "ConTech has successfully imported " + numberOfLines + " lines"; printDoubleLineMessage(message); diff --git a/src/main/java/seedu/ui/ViewMessageFormatterUi.java b/src/main/java/seedu/ui/ViewMessageFormatterUi.java index 0d52294276..d997538fc9 100644 --- a/src/main/java/seedu/ui/ViewMessageFormatterUi.java +++ b/src/main/java/seedu/ui/ViewMessageFormatterUi.java @@ -1,3 +1,5 @@ +//@@author ashrafjfr + package seedu.ui; import seedu.contact.Contact; From 39990af9dfc1e0ea2df4ca671f1ca6048eba3a56 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Mon, 25 Oct 2021 11:46:26 +0800 Subject: [PATCH 434/756] Update User Guide in docs --- docs/UserGuide.md | 152 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 130 insertions(+), 22 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index abd9fbe891..c0077e3e7c 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -2,32 +2,140 @@ ## Introduction -{Give a product intro} - +**ConTech** is a **Command Line Interface (CLI) application for managing computing-related contacts**. +If you are a computing professional that often uses the command line for work, **ConTech** can get your contact +management tasks done faster than any traditional GUI app. + +With our `add`, `edit`, `view`, and many more [features](#features) specifically set for computing-related contacts +such as saving a colleague's GitHub username, **ConTech** aims to improve your efficiency at work by cutting down the +time required to look up for various usernames when working with colleagues. + +* **[Quick Start](#start)** +* **[Features](#features)** + * **[Viewing help : `help`](#help)** + * **[Adding a contact : `add`](#add)** + * **[Listing all contacts : `list`](#list)** + * **[Viewing a contact : `view`](#view)** + * **[Deleting a contact : `rm`](#delete)** + * **[Editing a contact : `edit`](#edit)** + * **[Searching for a contact : `search`](#search)** + * **[Importing a contact : `import`](#import)** + * **[Exiting the program : `exit`](#exit)** + +* **[FAQ](#faq)** +* **[Command Summary](#summary)** + + ## Quick Start -{Give steps to get started quickly} - -1. Ensure that you have Java 11 or above installed. -1. Down the latest version of `Duke` from [here](http://link.to/duke). - +1. Ensure that you have Java `11` or above installed in your Computer. +1. Download the latest version of `contech.jar` from [here](https://github.com/AY2122S1-CS2113T-T09-1/tp/releases). +1. Copy the `contech.jar` file to the folder you want to use as the _home folder_ for **ConTech**. +1. Open your desired _Command Line Interface_ from the folder with `contech.jar` and enter the following code: +`java -jar contech.jar`. +1. Type a command in the command box and press _Enter_ to execute it. e.g., typing `help` and pressing _Enter_ will + display the help message.
+ Some example commands you can try: + * `add -n Alex Lee -g alexlee -e alex.lee@contech.sg -te alexl33`: Adds a contact named `Alex Lee` + to the ConTech Book. + * `list`: Lists all contacts. + * `view 1`: Displays all the details of the contact at index `1`. + * `rm 1`: Deletes the contact at index `1` in the list. + * `exit`: Exits the program. + +1. Refer to the [Features](#features) below for details of each command. + + ## Features -{Give detailed description of each feature} - -### Adding a todo: `todo` -Adds a new item to the list of todo items. - -Format: `todo n/TODO_NAME d/DEADLINE` - -* The `DEADLINE` can be in a natural language format. -* The `TODO_NAME` cannot contain punctuation. - -Example of usage: - -`todo n/Write the rest of the User Guide d/next week` - -`todo n/Refactor the User Guide to remove passive voice d/13/04/2020` + +### Viewing help: `help` +Displays a help message explaining what commands are available and each input format. + +Usage: `help` + +Expected outcome of usage: + +``` +help +____________________________________________________________ +add: ConTech adds the specified contact with provided parameters. + Parameters: -n NAME -g GITHUB -e EMAIL -te TELEGRAM -l LINKEDIN -tw TWITTER + Note: Parameters need not be in order and are optional except for NAME. + Example: add -n John Doe -g johndoecoder -e john@email.com -te johndoe + +list: Displays the name of all saved contacts. + Example: list + +edit: Edit any parameter in an existing contact. + Parameters: INDEX -n NAME -g GITHUB -e EMAIL -te TELEGRAM -l LINKEDIN -tw TWITTER + Note: Parameters need not be in order and are optional except for INDEX. + Example: edit 1 -e john.doe@email.com + +view: Displays all details for index specified contact. + Parameter: INDEX + Note: Index starts from 0. + Example: view 2 + +rm: Deletes the index specified contact. + Parameter: INDEX + Note: Index starts from 0. + Example: rm 0 + +search: Search for a contact containing a specified query. + Note: Flags may be used to specify a detail type to search. + If no flag is specified, contact name is searched by default. + Example: search -g QUERY + +help: Displays application usage instructions. + Example: help + +import: Imports contacts from a CSV Text File. + Note: Please ensure that data is saved in data/import.txt + Example: import +____________________________________________________________ +``` + + +### Adding a contact: `add` + + +### Listing all contacts: `list` + + +### Viewing a contact: `view` +Displays all the details saved to a contact in the ConTech Book. + +Usage: `view INDEX` +* Displays all the details of the contact at the specified `INDEX`. +* The index refers to the index number shown in the displayed contact list. +* The index must be within the range of indexes displayed in the contact list _(zero-based)_. + +Expected outcome of usage: +``` +view 0 +____________________________________________________________ +0. Alex Lee + Github: github.com/alexlee + Email: alex.lee@contech.sg + Telegram: t.me/alexl33 +____________________________________________________________ +``` + + +### Deleting a contact: `rm` + + +### Editing a contact : `edit` + + +### Searching for a contact: `search` + + +### Importing contacts: `import` + + +### Exiting the program: `exit` ## FAQ From f5db22aed785eb685e130fef21721d7f245ed0ce Mon Sep 17 00:00:00 2001 From: lezong Date: Mon, 25 Oct 2021 12:10:05 +0800 Subject: [PATCH 435/756] Add remove all feature --- data/import.txt | 3 +- .../java/seedu/command/AddContactCommand.java | 2 +- .../seedu/command/DeleteContactCommand.java | 39 +++++++++++++++---- .../seedu/command/EditContactCommand.java | 6 +-- src/main/java/seedu/contact/ContactList.java | 4 ++ src/main/java/seedu/parser/IndexParser.java | 17 ++++++-- src/main/java/seedu/ui/TextUi.java | 17 ++++++-- 7 files changed, 68 insertions(+), 20 deletions(-) diff --git a/data/import.txt b/data/import.txt index 45cc5b79ec..3dda6a993b 100644 --- a/data/import.txt +++ b/data/import.txt @@ -2,4 +2,5 @@ ashraf,ashrafjfr,null,null,null,null lezai,lezongmun,null,null,null,null andre,null marcus,null,null,null,null,null -badgithub,@@github,null,null,null,null \ No newline at end of file +badgithub,@@github,null,null,null,null +Le Zong,lezongmun,null,lezongg,null,lezongmun@gmail.com \ No newline at end of file diff --git a/src/main/java/seedu/command/AddContactCommand.java b/src/main/java/seedu/command/AddContactCommand.java index eeb794edb3..acb490e2ca 100644 --- a/src/main/java/seedu/command/AddContactCommand.java +++ b/src/main/java/seedu/command/AddContactCommand.java @@ -89,7 +89,7 @@ private boolean hasDuplicates(Contact addedContact, ContactList contactList) thr if (!duplicatedIndex.isEmpty()) { TextUi.confirmDuplicateMessage(duplicatedIndex, contactList, "add"); String userAddConfirmation = UserInputTextUi.getUserConfirmation(); - return userAddConfirmation.equalsIgnoreCase("n"); + return !userAddConfirmation.equalsIgnoreCase("y"); } return false; } diff --git a/src/main/java/seedu/command/DeleteContactCommand.java b/src/main/java/seedu/command/DeleteContactCommand.java index 6f775173e7..5330a8f6e3 100644 --- a/src/main/java/seedu/command/DeleteContactCommand.java +++ b/src/main/java/seedu/command/DeleteContactCommand.java @@ -1,5 +1,6 @@ package seedu.command; +import org.w3c.dom.Text; import seedu.contact.Contact; import seedu.parser.IndexParser; import seedu.ui.TextUi; @@ -8,6 +9,9 @@ public class DeleteContactCommand extends Command { + private static String ACKNOWLEDGE_DELETE = "y"; + private static int DELETE_ALL_CONTACTS = -2; + private final int contactIndex; public DeleteContactCommand(int contactIndex) { @@ -18,27 +22,46 @@ public int getDeletedIndex() { return contactIndex; } - private void deleteOnConfirmation(Contact deletedContact) { + + private void deleteSelectedContact() throws IndexOutOfBoundsException { + // throws IndexOutOfBoundsException if index is outside of the range + Contact deletedContact = IndexParser.getContactFromIndex(contactIndex, contactList); + // index must be within range since no exceptions thrown + assert contactIndex >= 0 && contactIndex < contactList.getListSize(); // ask for confirmation to delete from user - TextUi.confirmDeleteMessage(deletedContact, contactIndex); + TextUi.confirmDeleteContactMessage(deletedContact, contactIndex); String userConfirmation = UserInputTextUi.getUserConfirmation(); - if (userConfirmation.equalsIgnoreCase("y")) { + if (userConfirmation.equalsIgnoreCase(ACKNOWLEDGE_DELETE)) { this.contactList.deleteContact(contactIndex); String deletedName = deletedContact.getName(); int contactListSize = contactList.getListSize(); TextUi.deleteContactMessage(deletedName, contactListSize); } else { - assert !userConfirmation.equalsIgnoreCase("y"); + assert !userConfirmation.equalsIgnoreCase(ACKNOWLEDGE_DELETE); + TextUi.cancelDeleteContactMessage(); + } + } + + private void deleteAllContacts() { + TextUi.confirmDeleteAllMessage(); + String userConfirmation = UserInputTextUi.getUserConfirmation(); + if (userConfirmation.equalsIgnoreCase(ACKNOWLEDGE_DELETE)) { + int contactListSize = contactList.getListSize(); + this.contactList.deleteAllContacts(); + TextUi.deleteAllContactsMessage(contactListSize); + } else { + assert !userConfirmation.equalsIgnoreCase(ACKNOWLEDGE_DELETE); TextUi.cancelDeleteContactMessage(); } } public void execute() { try { - // throws IndexOutOfBoundsException if index is outside of the range - Contact deletedContact = IndexParser.getContactFromIndex(contactIndex, contactList); - assert contactIndex >= 0 && contactIndex < contactList.getListSize(); - deleteOnConfirmation(deletedContact); + if (contactIndex == DELETE_ALL_CONTACTS) { + deleteAllContacts(); + } else { + deleteSelectedContact(); + } } catch (IndexOutOfBoundsException e) { ExceptionTextUi.numOutOfRangeMessage(contactList.getListSize()); } diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index 1e44ee44a6..73c470958a 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -88,7 +88,7 @@ && hasDuplicateField(postEditContactDetails[j], currentContactDetails[j])) { if (!duplicatedIndex.isEmpty()) { TextUi.confirmDuplicateMessage(duplicatedIndex, contactList, EDIT_TYPE); String userEditConfirmation = UserInputTextUi.getUserConfirmation(); - return userEditConfirmation.equalsIgnoreCase("n"); + return !userEditConfirmation.equalsIgnoreCase("y"); } return false; } @@ -112,10 +112,10 @@ private boolean[] hasEditedFields(String[] contactDetails) { } private boolean hasDuplicateField(String input, String saved) { - return stringCleaner(saved).equals(stringCleaner(input)); + return cleanString(saved).equals(cleanString(input)); } - private String stringCleaner(String input) { + private String cleanString(String input) { return input.replace(" ", "").toLowerCase(); } diff --git a/src/main/java/seedu/contact/ContactList.java b/src/main/java/seedu/contact/ContactList.java index 99ef408aea..cf286933aa 100644 --- a/src/main/java/seedu/contact/ContactList.java +++ b/src/main/java/seedu/contact/ContactList.java @@ -21,6 +21,10 @@ public void deleteContact(int deletedIndex) { contacts.remove(deletedIndex); } + public void deleteAllContacts() { + contacts.clear(); + } + public void editContactAtIndex(String[] contactDetails, int editIndex) { Contact contactToEdit = getContactAtIndex(editIndex); contactToEdit.editContact(contactDetails); diff --git a/src/main/java/seedu/parser/IndexParser.java b/src/main/java/seedu/parser/IndexParser.java index bfca60cd65..f438c6100d 100644 --- a/src/main/java/seedu/parser/IndexParser.java +++ b/src/main/java/seedu/parser/IndexParser.java @@ -10,6 +10,10 @@ public class IndexParser { private static final int INDEX_POSITION = 1; private static final int SIGNIFICANT_INDEX_POSITION = 0; private static final int COMD_INDEX_LENGTH = 2; + private static final String PERSONAL_CONTACT_INDEX = "me"; + private static final int PERSONAL_CONTACT_ID = -1; + private static final String REMOVE_ALL_INDEX = "-rf"; + private static final int REMOVE_ALL_ID = -2; public static int getIndexFromInput(String userInput) @@ -22,12 +26,17 @@ public static int getIndexFromInput(String userInput) assert destructuredInputs.length == 2; // split index string into words String[] indexSplit = destructuredInputs[INDEX_POSITION].trim().split(" "); - // contact index that is important and what we want - // can be "me" or an integer + // Since inputs like "rm 1 2 3" are allowed + // 1 is the significant index that is important and chosen as the index for command + // index can be "me" or "-rf" or an integer String significantIndex = indexSplit[SIGNIFICANT_INDEX_POSITION].trim(); - if (significantIndex.equalsIgnoreCase("me")) { - return -1; + if (significantIndex.equalsIgnoreCase(PERSONAL_CONTACT_INDEX)) { + return PERSONAL_CONTACT_ID; } + if (significantIndex.equalsIgnoreCase(REMOVE_ALL_INDEX)) { + return REMOVE_ALL_ID; + } + // takes only the first word/ element as given user input, and throws NumberFormatExcept if it is not integer return Integer.parseInt(significantIndex); } diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 86c8148af7..a05f2bcaed 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -5,10 +5,10 @@ import java.util.ArrayList; public abstract class TextUi { - private static final String LOGO = " _____ _______ _ \n" + private static final String LOGO = "\n _____ _______ _ \n" + " / ____| |__ __| | | \n" + " | | ___ _ __ | | ___ ___| |__ \n" + " | | / _ \\| '_ \\| |/ _ \\/ __| '_ \\ \n" + " | |___| (_) | | | | | __/ (__| | | |\n" - + " \\_____\\___/|_| |_|_|\\___|\\___|_| |_|\n" + " \n"; + + " \\_____\\___/|_| |_|_|\\___|\\___|_| |_|\n" + " "; private static final String LINE = "____________________________________________________________\n"; @@ -182,18 +182,29 @@ public static void editPersonalContactMessage(Contact personalContact) { printDoubleLineMessage(message); } - public static void confirmDeleteMessage(Contact deletedContact, int deletedIndex) { + public static void confirmDeleteContactMessage(Contact deletedContact, int deletedIndex) { String message = "Delete this contact? (y/n)\n" + deletedIndex + ". " + deletedContact.getName() + formatContactFields(deletedContact); printDoubleLineMessage(message); } + public static void confirmDeleteAllMessage() { + String message = "Delete all of your contacts? (y/n)"; + printDoubleLineMessage(message); + } + public static void deleteContactMessage(String contactName, int listSize) { String message = "ConTech has removed the specified contact: " + contactName + "\n" + "You now have " + listSize + " contact(s)."; printDoubleLineMessage(message); } + public static void deleteAllContactsMessage(int listSize) { + String message = "ConTech has removed all " + listSize + + " of your contact(s)."; + printDoubleLineMessage(message); + } + public static void cancelDeleteContactMessage() { String message = "Delete has been cancelled."; printDoubleLineMessage(message); From f179ea4416b633abd70b6362735498da81aa02b4 Mon Sep 17 00:00:00 2001 From: lezong Date: Mon, 25 Oct 2021 12:28:54 +0800 Subject: [PATCH 436/756] Minor changes and add author --- src/main/java/seedu/command/DeleteContactCommand.java | 2 ++ src/main/java/seedu/command/EditContactCommand.java | 3 +-- src/main/java/seedu/parser/AddPersonalContactParser.java | 3 ++- src/main/java/seedu/parser/IndexParser.java | 2 ++ 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/command/DeleteContactCommand.java b/src/main/java/seedu/command/DeleteContactCommand.java index 6f775173e7..5516339bdf 100644 --- a/src/main/java/seedu/command/DeleteContactCommand.java +++ b/src/main/java/seedu/command/DeleteContactCommand.java @@ -1,3 +1,5 @@ +//@@author lezongmun + package seedu.command; import seedu.contact.Contact; diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index 1e44ee44a6..7db7a481ea 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -7,9 +7,8 @@ import seedu.ui.ExceptionTextUi; import seedu.ui.UserInputTextUi; -import java.lang.reflect.Array; import java.util.ArrayList; -import java.util.Arrays; + public class EditContactCommand extends Command { public static final int PERSONAL_CONTACT_INDEX = -1; diff --git a/src/main/java/seedu/parser/AddPersonalContactParser.java b/src/main/java/seedu/parser/AddPersonalContactParser.java index 05d112d760..6a17f9b147 100644 --- a/src/main/java/seedu/parser/AddPersonalContactParser.java +++ b/src/main/java/seedu/parser/AddPersonalContactParser.java @@ -1,7 +1,8 @@ +//@@author lezongmun + package seedu.parser; import seedu.contact.Contact; - import seedu.exception.InvalidGithubUsernameException; import seedu.exception.InvalidNameException; import seedu.exception.InvalidTelegramUsernameException; diff --git a/src/main/java/seedu/parser/IndexParser.java b/src/main/java/seedu/parser/IndexParser.java index bfca60cd65..8ed3505b4f 100644 --- a/src/main/java/seedu/parser/IndexParser.java +++ b/src/main/java/seedu/parser/IndexParser.java @@ -1,3 +1,5 @@ +//@@author lezongmun + package seedu.parser; import seedu.contact.Contact; From bf093b2f25ff79c4403fc70535149c9c1e0b4bb9 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Mon, 25 Oct 2021 16:01:30 +0800 Subject: [PATCH 437/756] Update style.puml with colours --- docs/diagrams/style.puml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/diagrams/style.puml b/docs/diagrams/style.puml index aeb3c2f71f..eb8dcc8e99 100644 --- a/docs/diagrams/style.puml +++ b/docs/diagrams/style.puml @@ -3,4 +3,8 @@ skinparam Shadowing false hide footbox hide members -hide circle \ No newline at end of file +hide circle + +!define ALT_HEADER_COLOR #gold +!define ALT_BODY_COLOUR #lightgreen +!define ELSE_BODY_COLOUR #lightblue From 22558738188f2ee35b1e1346ff98eed8dbd371ee Mon Sep 17 00:00:00 2001 From: lezong Date: Mon, 25 Oct 2021 16:25:25 +0800 Subject: [PATCH 438/756] Refactor parseCommand in MainParser --- text-ui-test/ACTUAL.TXT | 39 +++++++++++++++------------------- text-ui-test/EXPECTED-UNIX.TXT | 39 +++++++++++++++------------------- text-ui-test/EXPECTED.TXT | 39 +++++++++++++++------------------- 3 files changed, 51 insertions(+), 66 deletions(-) diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index 2b032e1c42..30b55242ca 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -10,6 +10,7 @@ ____________________________________________________________ ____________________________________________________________ + _____ _______ _ / ____| |__ __| | | | | ___ _ __ | | ___ ___| |__ @@ -17,7 +18,6 @@ ____________________________________________________________ | |___| (_) | | | | | __/ (__| | | | \_____\___/|_| |_|_|\___|\___|_| |_| - ____________________________________________________________ Welcome to ConTech, your personal contact tracker. Please provide us with your Name. @@ -517,11 +517,7 @@ Do you still want to add the contact? (y/n) ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: -Name: asjoda sadfsd -Twitter: twitter.com/123_adad - -You now have 9 contact(s). +Contact was not added. ____________________________________________________________ ____________________________________________________________ @@ -557,7 +553,7 @@ ConTech has added the specified contact: Name: lezongggg Telegram: t.me/testTelegram -You now have 10 contact(s). +You now have 9 contact(s). ____________________________________________________________ ____________________________________________________________ @@ -580,12 +576,12 @@ No search results found. ____________________________________________________________ ____________________________________________________________ -2. bory +1. bory Github: github.com/marcus ____________________________________________________________ ____________________________________________________________ -6. lezongmun +5. lezongmun Github: github.com/lezong ____________________________________________________________ @@ -601,20 +597,19 @@ Please try again with a valid flag. ____________________________________________________________ ____________________________________________________________ -ConTech has 10 contacts stored. +ConTech has 9 contacts stored. Here's the list : ____________________________________________________________ 0. asjoda sadfsd -1. asjoda sadfsd -2. bory -3. dev -4. lezong mun -5. lezongggg -6. lezongmun -7. mayank -8. ng andre -9. yusdhsdsd +1. bory +2. dev +3. lezong mun +4. lezongggg +5. lezongmun +6. mayank +7. ng andre +8. yusdhsdsd ____________________________________________________________ @@ -623,7 +618,7 @@ ConTech has added the specified contact: Name: ashraf Github: github.com/ashrafjfr -You now have 11 contact(s). +You now have 10 contact(s). ____________________________________________________________ ____________________________________________________________ @@ -641,7 +636,7 @@ ConTech has added the specified contact: Name: ashraf Telegram: t.me/ashrafjfr -You now have 12 contact(s). +You now have 11 contact(s). ____________________________________________________________ ____________________________________________________________ @@ -693,7 +688,7 @@ ConTech has successfully imported 3 lines ____________________________________________________________ ____________________________________________________________ -7. lezai +6. lezai Github: github.com/lezongmun ____________________________________________________________ diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index 2b032e1c42..30b55242ca 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -10,6 +10,7 @@ ____________________________________________________________ ____________________________________________________________ + _____ _______ _ / ____| |__ __| | | | | ___ _ __ | | ___ ___| |__ @@ -17,7 +18,6 @@ ____________________________________________________________ | |___| (_) | | | | | __/ (__| | | | \_____\___/|_| |_|_|\___|\___|_| |_| - ____________________________________________________________ Welcome to ConTech, your personal contact tracker. Please provide us with your Name. @@ -517,11 +517,7 @@ Do you still want to add the contact? (y/n) ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: -Name: asjoda sadfsd -Twitter: twitter.com/123_adad - -You now have 9 contact(s). +Contact was not added. ____________________________________________________________ ____________________________________________________________ @@ -557,7 +553,7 @@ ConTech has added the specified contact: Name: lezongggg Telegram: t.me/testTelegram -You now have 10 contact(s). +You now have 9 contact(s). ____________________________________________________________ ____________________________________________________________ @@ -580,12 +576,12 @@ No search results found. ____________________________________________________________ ____________________________________________________________ -2. bory +1. bory Github: github.com/marcus ____________________________________________________________ ____________________________________________________________ -6. lezongmun +5. lezongmun Github: github.com/lezong ____________________________________________________________ @@ -601,20 +597,19 @@ Please try again with a valid flag. ____________________________________________________________ ____________________________________________________________ -ConTech has 10 contacts stored. +ConTech has 9 contacts stored. Here's the list : ____________________________________________________________ 0. asjoda sadfsd -1. asjoda sadfsd -2. bory -3. dev -4. lezong mun -5. lezongggg -6. lezongmun -7. mayank -8. ng andre -9. yusdhsdsd +1. bory +2. dev +3. lezong mun +4. lezongggg +5. lezongmun +6. mayank +7. ng andre +8. yusdhsdsd ____________________________________________________________ @@ -623,7 +618,7 @@ ConTech has added the specified contact: Name: ashraf Github: github.com/ashrafjfr -You now have 11 contact(s). +You now have 10 contact(s). ____________________________________________________________ ____________________________________________________________ @@ -641,7 +636,7 @@ ConTech has added the specified contact: Name: ashraf Telegram: t.me/ashrafjfr -You now have 12 contact(s). +You now have 11 contact(s). ____________________________________________________________ ____________________________________________________________ @@ -693,7 +688,7 @@ ConTech has successfully imported 3 lines ____________________________________________________________ ____________________________________________________________ -7. lezai +6. lezai Github: github.com/lezongmun ____________________________________________________________ diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 2b032e1c42..30b55242ca 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -10,6 +10,7 @@ ____________________________________________________________ ____________________________________________________________ + _____ _______ _ / ____| |__ __| | | | | ___ _ __ | | ___ ___| |__ @@ -17,7 +18,6 @@ ____________________________________________________________ | |___| (_) | | | | | __/ (__| | | | \_____\___/|_| |_|_|\___|\___|_| |_| - ____________________________________________________________ Welcome to ConTech, your personal contact tracker. Please provide us with your Name. @@ -517,11 +517,7 @@ Do you still want to add the contact? (y/n) ____________________________________________________________ ____________________________________________________________ -ConTech has added the specified contact: -Name: asjoda sadfsd -Twitter: twitter.com/123_adad - -You now have 9 contact(s). +Contact was not added. ____________________________________________________________ ____________________________________________________________ @@ -557,7 +553,7 @@ ConTech has added the specified contact: Name: lezongggg Telegram: t.me/testTelegram -You now have 10 contact(s). +You now have 9 contact(s). ____________________________________________________________ ____________________________________________________________ @@ -580,12 +576,12 @@ No search results found. ____________________________________________________________ ____________________________________________________________ -2. bory +1. bory Github: github.com/marcus ____________________________________________________________ ____________________________________________________________ -6. lezongmun +5. lezongmun Github: github.com/lezong ____________________________________________________________ @@ -601,20 +597,19 @@ Please try again with a valid flag. ____________________________________________________________ ____________________________________________________________ -ConTech has 10 contacts stored. +ConTech has 9 contacts stored. Here's the list : ____________________________________________________________ 0. asjoda sadfsd -1. asjoda sadfsd -2. bory -3. dev -4. lezong mun -5. lezongggg -6. lezongmun -7. mayank -8. ng andre -9. yusdhsdsd +1. bory +2. dev +3. lezong mun +4. lezongggg +5. lezongmun +6. mayank +7. ng andre +8. yusdhsdsd ____________________________________________________________ @@ -623,7 +618,7 @@ ConTech has added the specified contact: Name: ashraf Github: github.com/ashrafjfr -You now have 11 contact(s). +You now have 10 contact(s). ____________________________________________________________ ____________________________________________________________ @@ -641,7 +636,7 @@ ConTech has added the specified contact: Name: ashraf Telegram: t.me/ashrafjfr -You now have 12 contact(s). +You now have 11 contact(s). ____________________________________________________________ ____________________________________________________________ @@ -693,7 +688,7 @@ ConTech has successfully imported 3 lines ____________________________________________________________ ____________________________________________________________ -7. lezai +6. lezai Github: github.com/lezongmun ____________________________________________________________ From b98b85457213ceca36bf572294f60d289d3e680d Mon Sep 17 00:00:00 2001 From: lezong Date: Mon, 25 Oct 2021 16:26:41 +0800 Subject: [PATCH 439/756] Refactor parseCommand in MainParser --- .../seedu/command/DeleteContactCommand.java | 3 +- .../seedu/command/EditContactCommand.java | 4 + src/main/java/seedu/parser/CommandType.java | 6 ++ src/main/java/seedu/parser/MainParser.java | 89 ++++++++++++++++--- .../java/seedu/storage/ContactsDecoder.java | 4 +- .../java/seedu/storage/ContactsEncoder.java | 2 + src/main/java/seedu/storage/Storage.java | 10 +-- .../java/seedu/parser/MainParserTest.java | 23 +++-- 8 files changed, 112 insertions(+), 29 deletions(-) create mode 100644 src/main/java/seedu/parser/CommandType.java diff --git a/src/main/java/seedu/command/DeleteContactCommand.java b/src/main/java/seedu/command/DeleteContactCommand.java index f521743c8d..33d7d46a80 100644 --- a/src/main/java/seedu/command/DeleteContactCommand.java +++ b/src/main/java/seedu/command/DeleteContactCommand.java @@ -2,7 +2,6 @@ package seedu.command; -import org.w3c.dom.Text; import seedu.contact.Contact; import seedu.parser.IndexParser; import seedu.ui.TextUi; @@ -20,7 +19,7 @@ public DeleteContactCommand(int contactIndex) { this.contactIndex = contactIndex; } - public int getDeletedIndex() { + public int getContactIndex() { return contactIndex; } diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index 880c88122b..d917da1db3 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -138,6 +138,10 @@ private String[] extractContactDetails(Contact contact) throws InvalidFlagExcept return contactDetails; } + public int getContactIndex() { + return this.contactIndex; + } + //@@author ng-andre private Contact duplicateContact(Contact contact) { String name = contact.getName(); diff --git a/src/main/java/seedu/parser/CommandType.java b/src/main/java/seedu/parser/CommandType.java new file mode 100644 index 0000000000..b6f8d64abd --- /dev/null +++ b/src/main/java/seedu/parser/CommandType.java @@ -0,0 +1,6 @@ +package seedu.parser; + + +public enum CommandType { + MANIPULATION, QUERY, CONTROL, FAILED +} diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index e2ac58d6a7..fd9b4c4c76 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -50,9 +50,59 @@ public class MainParser { private final SearchContactParser searchContactParser = new SearchContactParser(); public Command parseCommand(String userInput) { - String commandType = getCommandWord(userInput); + CommandType commandType = getCommandType(userInput); + String commandWord = getCommandWord(userInput); Command command; switch (commandType) { + case MANIPULATION: + command = parseManipulationCommand(commandWord, userInput); + break; + case QUERY: + command = parseQueryCommand(commandWord, userInput); + break; + case CONTROL: + command = parseControlCommand(commandWord); + break; + default: + command = new FailedCommand(FailedCommandType.GENERAL); + } + return command; + } + + public String getCommandWord(String userInput) { + String[] destructuredInputs = userInput.split(" ", ISOLATE_COMD_WORD); + return destructuredInputs[COMD_WORD_INDEX]; + } + + public CommandType getCommandType(String userInput) { + String commandWord = getCommandWord(userInput); + CommandType commandType; + switch (commandWord) { + case ADD_CONTACT_COMD: + case EDIT_CONTACT_COMD: + case DELETE_CONTACT_COMD: + case IMPORT_COMD: + commandType = CommandType.MANIPULATION; + break; + case VIEW_CONTACT_COMD: + case SEARCH_COMD: + case LIST_COMD: + case HELP_COMD: + case PERSONAL_CONTACT_COMD: + commandType = CommandType.QUERY; + break; + case EXIT_COMD: + commandType = CommandType.CONTROL; + break; + default: + commandType = CommandType.FAILED; + } + return commandType; + } + + private Command parseManipulationCommand(String commandWord, String userInput) { + Command command; + switch (commandWord) { case ADD_CONTACT_COMD: command = parseAddContact(userInput); break; @@ -62,12 +112,35 @@ public Command parseCommand(String userInput) { case DELETE_CONTACT_COMD: command = parseDeleteContact(userInput); break; - case VIEW_CONTACT_COMD: - command = parseViewContact(userInput); + case IMPORT_COMD: + command = new ImportContactCommand(); break; + default: + assert false; + command = new FailedCommand(FailedCommandType.GENERAL); + } + return command; + } + + private Command parseControlCommand(String commandWord) { + Command command; + switch (commandWord) { case EXIT_COMD: command = new ExitCommand(); break; + default: + assert false; + command = new FailedCommand(FailedCommandType.GENERAL); + } + return command; + } + + private Command parseQueryCommand(String commandWord, String userInput) { + Command command; + switch (commandWord) { + case VIEW_CONTACT_COMD: + command = parseViewContact(userInput); + break; case LIST_COMD: command = new ListContactsCommand(); break; @@ -77,24 +150,16 @@ public Command parseCommand(String userInput) { case SEARCH_COMD: command = parseSearchCommand(userInput); break; - case IMPORT_COMD: - command = new ImportContactCommand(); - break; case PERSONAL_CONTACT_COMD: command = parsePersonalContact(); break; default: + assert false; command = new FailedCommand(FailedCommandType.GENERAL); } return command; } - - public String getCommandWord(String userInput) { - String[] destructuredInputs = userInput.split(" ", ISOLATE_COMD_WORD); - return destructuredInputs[COMD_WORD_INDEX]; - } - private Command parseAddContact(String userInput) { contactParser = addContactParser; try { diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index a391aa156e..276891dbb6 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -39,6 +39,7 @@ public ContactList readContacts(File contactFile, String contactFilePath) throws return updatedContactList; } + //@@author lezongmun public Contact readPersonalContact(File personalContactFile) throws FileErrorException { Contact personalContact = new Contact(null, null, null, null, null, null); @@ -54,7 +55,7 @@ public Contact readPersonalContact(File personalContactFile) return personalContact; } - + //@author lezongmun private Contact decodePersonalContact(String contactText, Contact contact) { Contact personalContact = contact; try { @@ -85,6 +86,7 @@ private Contact decodePersonalContact(String contactText, Contact contact) { return personalContact; } + //@@author private void decodeContact(ContactList contactList, String contactText, int lineIndex, String contactFilePath) { // Add the decoded details into the contact list try { diff --git a/src/main/java/seedu/storage/ContactsEncoder.java b/src/main/java/seedu/storage/ContactsEncoder.java index 90e9ce7b39..4834e45ab8 100644 --- a/src/main/java/seedu/storage/ContactsEncoder.java +++ b/src/main/java/seedu/storage/ContactsEncoder.java @@ -10,6 +10,7 @@ import static seedu.storage.Storage.SEPARATOR; public class ContactsEncoder { + //@@author lezongmun public void savePersonalContact(String contactFilePath, Contact personalContact) throws FileErrorException { try { FileWriter fileWriter = new FileWriter(contactFilePath); @@ -21,6 +22,7 @@ public void savePersonalContact(String contactFilePath, Contact personalContact) } } + //@@author public void saveContacts(String contactFilePath, ContactList contactList) throws FileErrorException { try { FileWriter fileWriter = new FileWriter(contactFilePath); diff --git a/src/main/java/seedu/storage/Storage.java b/src/main/java/seedu/storage/Storage.java index a41b9029b5..2fa65b360e 100644 --- a/src/main/java/seedu/storage/Storage.java +++ b/src/main/java/seedu/storage/Storage.java @@ -17,7 +17,6 @@ public class Storage { private final ContactsDecoder contactsDecoder; private final ContactsEncoder contactsEncoder; public static final String SEPARATOR = ","; - private static boolean isFirstRun = false; public Storage(String contactFilePath, String personalContactFilePath, ContactsDecoder contactsDecoder, ContactsEncoder contactsEncoder) { @@ -29,10 +28,7 @@ public Storage(String contactFilePath, String personalContactFilePath, ContactsD this.contactsEncoder = contactsEncoder; } - public static boolean getIsFirstRun() { - return isFirstRun; - } - + //@@author lezongmun private boolean hasExistingPersonalContactFile() throws FileErrorException { try { if (!personalContactFile.exists()) { @@ -48,10 +44,12 @@ private boolean hasExistingPersonalContactFile() throws FileErrorException { return true; } + //@@author lezongmun private boolean hasEmptyExistingPersonalContactFile() { return personalContactFile.exists() && personalContactFile.length() == 0; } + //@@author private boolean hasExistingContactFile() throws FileErrorException { try { if (!contactFile.exists()) { @@ -74,9 +72,9 @@ public ContactList loadExistingContacts() throws FileErrorException { return contactsDecoder.readContacts(contactFile, contactFilePath); } + //@@author lezongmun public Contact loadExistingPersonalContact() throws FileErrorException { if (!hasExistingPersonalContactFile() || hasEmptyExistingPersonalContactFile()) { - isFirstRun = true; // get new contact's name AddPersonalContactParser addPersonalContactParser = new AddPersonalContactParser(); addPersonalContactParser.collectPersonalDetails(); diff --git a/src/test/java/seedu/parser/MainParserTest.java b/src/test/java/seedu/parser/MainParserTest.java index 1076070b6d..29e2d85ca1 100644 --- a/src/test/java/seedu/parser/MainParserTest.java +++ b/src/test/java/seedu/parser/MainParserTest.java @@ -6,6 +6,7 @@ import seedu.command.AddContactCommand; import seedu.command.Command; import seedu.command.DeleteContactCommand; +import seedu.command.EditContactCommand; import seedu.command.FailedCommand; import seedu.command.InvalidDetailCommand; import seedu.command.ViewContactCommand; @@ -44,21 +45,29 @@ private T getParsedCommand(String userInput, Class comman return (T) result; } - @Test public void parseDeleteCommand_validIndex_expectDeleteContactIndexMatch() { testIndex = 1; testUserInput = "rm " + testIndex; final DeleteContactCommand testResultCommand = getParsedCommand(testUserInput, DeleteContactCommand.class); - assertEquals(testIndex, testResultCommand.getDeletedIndex()); + assertEquals(testIndex, testResultCommand.getContactIndex()); + } + + @Test + public void parseDeleteCommand_validDeleteAllIndex_expectDeleteAddIdMatch() { + String testIndex = "-rf"; + int testId = -2; + testUserInput = "rm " + testIndex; + final DeleteContactCommand testResultCommand = getParsedCommand(testUserInput, DeleteContactCommand.class); + assertEquals(testId, testResultCommand.getContactIndex()); } @Test public void parseDeleteCommand_multipleIndexes_expectDeleteContactIndexMatch() { - int testIndex = 1; + testIndex = 1; testUserInput = String.format("rm %d %d", testIndex, 2); final DeleteContactCommand testResultCommand = getParsedCommand(testUserInput, DeleteContactCommand.class); - assertEquals(testIndex, testResultCommand.getDeletedIndex()); + assertEquals(testIndex, testResultCommand.getContactIndex()); } @Test @@ -66,7 +75,7 @@ public void parseDeleteCommand_validIndexWithSpaces_expectDeleteContactIndexMatc testIndex = 1; testUserInput = "rm " + testIndex; final DeleteContactCommand testResultCommand = getParsedCommand(testUserInput, DeleteContactCommand.class); - assertEquals(testIndex, testResultCommand.getDeletedIndex()); + assertEquals(testIndex, testResultCommand.getContactIndex()); } @Test @@ -85,7 +94,6 @@ public void parseDeleteCommand_invalidNumber_expectFailedCommandType() { assertEquals(expectedFailedCommandType, actualFailedCommand.getType()); } - @Test public void parseDeleteCommand_outOfRangeIndex_expectException() { ContactList contactList = new ContactList(); @@ -98,12 +106,11 @@ public void parseDeleteCommand_outOfRangeIndex_expectException() { // trying to delete the contact with index 3 when there is only 1 contact (with index 0) in the contact list DeleteContactCommand deleteContactCommand = getParsedCommand(testUserInput, DeleteContactCommand.class); deleteContactCommand.setContactList(contactList); - int deletedIndex = deleteContactCommand.getDeletedIndex(); + int deletedIndex = deleteContactCommand.getContactIndex(); assertThrows(IndexOutOfBoundsException.class, () -> contactList.deleteContact(deletedIndex)); } - @Test public void parseAddCommand_validInputsWithIrregularSpaces_expectAddContactCommand() { testUserInput = " add -n andre -g ng-andre -l linkedin -tw twit -te teles123 -e andre@twix.com"; From 8c6c117e236fae9699d5e21528f0e8f93bcf204d Mon Sep 17 00:00:00 2001 From: lezong Date: Mon, 25 Oct 2021 16:30:02 +0800 Subject: [PATCH 440/756] Update test in text-ui-test for deleting all contacts --- text-ui-test/ACTUAL.TXT | 64 ++++++++++++++++++++++++++++++++++ text-ui-test/EXPECTED-UNIX.TXT | 64 ++++++++++++++++++++++++++++++++++ text-ui-test/EXPECTED.TXT | 64 ++++++++++++++++++++++++++++++++++ text-ui-test/input.txt | 7 ++++ 4 files changed, 199 insertions(+) diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index 30b55242ca..ddc13873e5 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -696,6 +696,70 @@ ____________________________________________________________ No search results found. ____________________________________________________________ +____________________________________________________________ +ConTech has 14 contacts stored. +Here's the list : +____________________________________________________________ + +0. ashraf +1. ashraf +2. ashraf +3. asjoda sadfsd +4. bory +5. dev +6. lezai +7. lezong mun +8. lezongggg +9. lezongmun +10. marcus +11. mayank +12. ng andre +13. yusdhsdsd + +____________________________________________________________ + +____________________________________________________________ +Delete all of your contacts? (y/n) +____________________________________________________________ + +____________________________________________________________ +Delete has been cancelled. +____________________________________________________________ + +____________________________________________________________ +ConTech has 14 contacts stored. +Here's the list : +____________________________________________________________ + +0. ashraf +1. ashraf +2. ashraf +3. asjoda sadfsd +4. bory +5. dev +6. lezai +7. lezong mun +8. lezongggg +9. lezongmun +10. marcus +11. mayank +12. ng andre +13. yusdhsdsd + +____________________________________________________________ + +____________________________________________________________ +Delete all of your contacts? (y/n) +____________________________________________________________ + +____________________________________________________________ +ConTech has removed all 14 of your contact(s). +____________________________________________________________ + +____________________________________________________________ +You have not stored any contacts in ConTech +____________________________________________________________ + ____________________________________________________________ ConTech will now shutdown. We hope you have enjoyed using it. diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index 30b55242ca..ddc13873e5 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -696,6 +696,70 @@ ____________________________________________________________ No search results found. ____________________________________________________________ +____________________________________________________________ +ConTech has 14 contacts stored. +Here's the list : +____________________________________________________________ + +0. ashraf +1. ashraf +2. ashraf +3. asjoda sadfsd +4. bory +5. dev +6. lezai +7. lezong mun +8. lezongggg +9. lezongmun +10. marcus +11. mayank +12. ng andre +13. yusdhsdsd + +____________________________________________________________ + +____________________________________________________________ +Delete all of your contacts? (y/n) +____________________________________________________________ + +____________________________________________________________ +Delete has been cancelled. +____________________________________________________________ + +____________________________________________________________ +ConTech has 14 contacts stored. +Here's the list : +____________________________________________________________ + +0. ashraf +1. ashraf +2. ashraf +3. asjoda sadfsd +4. bory +5. dev +6. lezai +7. lezong mun +8. lezongggg +9. lezongmun +10. marcus +11. mayank +12. ng andre +13. yusdhsdsd + +____________________________________________________________ + +____________________________________________________________ +Delete all of your contacts? (y/n) +____________________________________________________________ + +____________________________________________________________ +ConTech has removed all 14 of your contact(s). +____________________________________________________________ + +____________________________________________________________ +You have not stored any contacts in ConTech +____________________________________________________________ + ____________________________________________________________ ConTech will now shutdown. We hope you have enjoyed using it. diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 30b55242ca..ddc13873e5 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -696,6 +696,70 @@ ____________________________________________________________ No search results found. ____________________________________________________________ +____________________________________________________________ +ConTech has 14 contacts stored. +Here's the list : +____________________________________________________________ + +0. ashraf +1. ashraf +2. ashraf +3. asjoda sadfsd +4. bory +5. dev +6. lezai +7. lezong mun +8. lezongggg +9. lezongmun +10. marcus +11. mayank +12. ng andre +13. yusdhsdsd + +____________________________________________________________ + +____________________________________________________________ +Delete all of your contacts? (y/n) +____________________________________________________________ + +____________________________________________________________ +Delete has been cancelled. +____________________________________________________________ + +____________________________________________________________ +ConTech has 14 contacts stored. +Here's the list : +____________________________________________________________ + +0. ashraf +1. ashraf +2. ashraf +3. asjoda sadfsd +4. bory +5. dev +6. lezai +7. lezong mun +8. lezongggg +9. lezongmun +10. marcus +11. mayank +12. ng andre +13. yusdhsdsd + +____________________________________________________________ + +____________________________________________________________ +Delete all of your contacts? (y/n) +____________________________________________________________ + +____________________________________________________________ +ConTech has removed all 14 of your contact(s). +____________________________________________________________ + +____________________________________________________________ +You have not stored any contacts in ConTech +____________________________________________________________ + ____________________________________________________________ ConTech will now shutdown. We hope you have enjoyed using it. diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index d3ce1b0bb1..208550231c 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -89,4 +89,11 @@ view 0 import search -n lezai search -n badgithub +list +rm -rf +asdsad +list +rm -rf +y +list exit \ No newline at end of file From a37341a549d4c90983f3d8c85e8e62f70ea57d39 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Mon, 25 Oct 2021 16:34:27 +0800 Subject: [PATCH 441/756] Improve format list command --- src/main/java/seedu/ui/TextUi.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index f20229d2e5..3ba627108b 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -28,7 +28,7 @@ private static void printTopLineMessage(String message) { // Used to print a line after displayed data public static void printBottomLine() { - System.out.println("\n" + LINE); + System.out.println(LINE); } public static void welcomeMessage() { @@ -162,7 +162,7 @@ public static void contactsListMessage(int listSize) { } public static void contactsEmptyListMessage() { - String message = "You have not stored any contacts in ConTech"; + String message = "You do not have any stored contacts"; printDoubleLineMessage(message); } From ae9306cb8af4c83ef091d4079a32cf44e942c747 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Mon, 25 Oct 2021 19:35:07 +0800 Subject: [PATCH 442/756] Update edit sequence diagram --- docs/diagrams/EditContactCommand.puml | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/docs/diagrams/EditContactCommand.puml b/docs/diagrams/EditContactCommand.puml index 3fe47523b2..8d83db2392 100644 --- a/docs/diagrams/EditContactCommand.puml +++ b/docs/diagrams/EditContactCommand.puml @@ -5,18 +5,29 @@ hide footbox -> ":MainParser": execute() activate ":MainParser" -":MainParser" -> ":MainParser" :getCommandWord(userInput:String) + +":MainParser" -> ":MainParser":getCommandWord(userInput:String) +activate ":MainParser" ":MainParser" -> ":EditContactParser" :EditContactParser(userInput:String) activate ":EditContactParser" + ":EditContactParser" -> ":EditContactParser" :parseContactDetails(userInput:String) +activate ":EditContactParser" +":EditContactParser" --> ":EditContactParser" :details:String[] +deactivate ":EditContactParser" + ":EditContactParser" -> ":IndexParser" :getIndexFromInput(userInput:String) activate ":IndexParser" ":IndexParser" --> ":EditContactParser" :userIndex:int deactivate ":IndexParser" -":EditContactParser" -> ":EditContactCommand" : execute(contactDetails:String[], contactIndex:int) +":EditContactParser" --> ":MainParser" : EditContactCommand(details, userIndex):Command +deactivate ":EditContactParser" + +":MainParser" -> ":EditContactCommand" : EditContactCommand:Command + activate ":EditContactCommand" ":EditContactCommand" -> ":ContactList" : editContact(contactDetails:String[], contactIndex:int) @@ -37,4 +48,12 @@ alt#gold #lightgreen NAME_INDEX ":ContactList" -> ":ContactList" : setEmail(contactDetails(i)) end end + +":ContactList"-->":EditContactCommand" +deactivate ":ContactList" + +":EditContactCommand"-->":MainParser" +deactivate ":EditContactCommand" +deactivate ":MainParser" + @enduml \ No newline at end of file From 0e6e6f791bda02af2148767bda4db104dfbedc09 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Mon, 25 Oct 2021 19:35:17 +0800 Subject: [PATCH 443/756] Update search sequence diagram --- docs/diagrams/SearchContactCommand.puml | 33 ++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/docs/diagrams/SearchContactCommand.puml b/docs/diagrams/SearchContactCommand.puml index ae8bb160ca..6074dd6e48 100644 --- a/docs/diagrams/SearchContactCommand.puml +++ b/docs/diagrams/SearchContactCommand.puml @@ -6,22 +6,38 @@ hide footbox activate ":MainParser" ":MainParser" -> ":MainParser" :getCommandWord(userInput:String) +activate ":MainParser" ":MainParser" -> ":SearchContactParser" :parseSearchQuery(userInput:String) activate ":SearchContactParser" ":SearchContactParser" -> ":SearchContactParser" :parseSearchQuery(userInput:String) -":SearchContactParser" -> ":SearchContactParser" :getDetailFlag(userInput:String) +activate ":SearchContactParser" +":SearchContactParser" --> ":SearchContactParser" :searchInput:String +deactivate ":SearchContactParser" + +":SearchContactParser" -> ":SearchContactParser" :getDetailFlag(searchInput:String)) +activate ":SearchContactParser" +":SearchContactParser" --> ":SearchContactParser" :detailFlag:int +deactivate ":SearchContactParser" + +":SearchContactParser" -> ":SearchContactParser" :parseSearchQuery(searchInput:String) +activate ":SearchContactParser" +":SearchContactParser" --> ":SearchContactParser" :query:String +deactivate ":SearchContactParser" -":SearchContactParser" -> ":SearchContactCommand" : execute(query:String, detailIndex:int) +":SearchContactParser" --> ":MainParser" : SearchContactCommand(query:String, detailFlag:int) +deactivate ":SearchContactParser" + +":MainParser" -> ":SearchContactCommand" : SearchContactCommand:Command activate ":SearchContactCommand" -":SearchContactCommand" -> ":ContactList" : searchContact(query:String, detailIndex:int) +":SearchContactCommand" -> ":ContactList" : searchContact(query:String, detailFlag:int) activate ":ContactList" loop for all contacts ":ContactList" -> ":ContactList" :getDetailFlag(userInput:String) -alt#gold #lightgreen NAME_INDEX +loop#gold #lightgreen for all contacts alt contact.getName().contains(query) ":ContactList" -> ":TextUI" : viewContactMessage(contact, i) activate ":TextUI" @@ -61,4 +77,13 @@ alt#gold #lightgreen NAME_INDEX deactivate ":TextUI" end end end + +":ContactList"-->":SearchContactCommand" +deactivate ":ContactList" + +":SearchContactCommand"-->":MainParser" +deactivate ":SearchContactCommand" +deactivate ":MainParser" + + @enduml \ No newline at end of file From 9c823a43ef8c95eee16c182c8c8e7990a1168350 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Mon, 25 Oct 2021 19:35:33 +0800 Subject: [PATCH 444/756] Export new sequence diagrams --- .../EditContactCommandSequenceDiagram.png | Bin 51768 -> 56988 bytes .../SearchContactCommandSequenceDiagram.png | Bin 72334 -> 85938 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/images/EditContactCommandSequenceDiagram.png b/docs/images/EditContactCommandSequenceDiagram.png index 68b7f356d78084e67515128b592f21358a10302c..e57c400d84dee026e1701385318705f30da208a5 100644 GIT binary patch literal 56988 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 z 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
+:information_source: You are advised to go through the following two sections. Before moving on to the features of **ConTech**, we have prepared some documentation regarding some common notations that will be used throughout this guide. From 7d1ea3d016f0588e51325f87ee17e6bcd1dd9594 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Fri, 29 Oct 2021 01:52:44 +0800 Subject: [PATCH 567/756] Update command formats based on common notations --- docs/UserGuide.md | 58 +++++++++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index c99b6ec2a6..0b9f5e5bc1 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -120,11 +120,11 @@ Do familiarise yourself with these notations to better utilise the user guide. Adds a specified contact to the ConTech Book. -Usage: `add -n NAME -g GITHUB -l LINKEDIN -te TELEGRAM -tw TWITTER -e EMAIL` +Command format: `add <-n> {-g } {-l } {-te } {-tw } {-e }` - ConTech is robust and allows you to specify your fields in any order. - The `-n` name field is the only compulsory field required to add a contact. The rest are optional. -- Up to five other `FLAGS` and `DETAILS` can be specified +- Up to five other `flags` and `details` can be specified. - ConTech also has built-in duplicate checkers, in case you accidentally add the same contact twice. Expected outcome of usage: @@ -145,11 +145,10 @@ ____________________________________________________________ ### Listing all contacts: `ls` -Lists all the saved contacts with the index and contact name. +Lists all the contacts in the ConTech Book with their indexes and names. -Usage: `ls` -* The indexes start from 0, this is done as computing professionals - are more familiar with index start from 0. +Command format: `ls` +* Do note that the indexes start from 0, similar to array indexes, which you may be familiar with. Expected outcome of usage: @@ -174,11 +173,19 @@ ____________________________________________________________ ### Viewing a contact: `view` Displays all the details saved to a contact in the ConTech Book. -Usage: `view INDEX` +Command format: `view ` * Displays all the details of the contact at the specified `INDEX`. * The index refers to the index number shown in the displayed contact list. * The index must be within the range of indexes displayed in the contact list _(zero-based)_. +
+ +:information_source: You can easily run the [`ls`](#list) command to view your contact indexes before running any +command +requiring indexes. + +
+ Expected outcome of usage: ``` view 0 @@ -189,11 +196,14 @@ ____________________________________________________________ Telegram: t.me/alexl33 ____________________________________________________________ ``` + ### Viewing personal contact: `me` -Displays all the details saved to the personal contact in the ConTech Book. +Displays all your details saved to the personal contact in the ConTech Book. -Usage: `me` +This refers to the details which you filled in while setting up **ConTech**. + +Command format: `me` * Displays all the details of the personal contact. Expected outcome of usage: @@ -214,11 +224,14 @@ display the details of the specified contact to be deleted, and prompt user to c Usages: -`rm INDEX` +Command formats: + +`rm ` * Deletes the contact with the specified `INDEX`. * The index refers to the index number shown in the displayed contact list. * The index must be within the range of indexes displayed in the contact list _(zero-based)_. +`rm {-g} {-l} {-te} {-tw} {-e}` `rm all` * Deletes all contacts in the ConTech Book @@ -262,12 +275,13 @@ ____________________________________________________________ Edits the details of a specified contact in the ConTech Book. -Usage: `edit INDEX -FLAG DETAIL` +Command format: `edit {-n } {-g } {-l } {-te } {-tw } {-e }` -- Up to six `FLAGS` and `DETAILS` can be specified in any order +- Up to six `flags` and `details` can be specified, in any order. - The index refers to the index number shown in the displayed contact list. - The index must be within the range of indexes displayed in the contact list (zero-based). - ConTech also has built-in duplicate checkers and will alert you if there is already a contact with the same details when editing. +- While all six `details` are optional, minimally **one** must be specified for any effect to take place. Expected outcome of usage: @@ -286,12 +300,12 @@ ____________________________________________________________ Search the ConTech Book for a contact whose details contain the specified query. -Usage: `search [-FLAG] QUERY` +Command format: `search {-n | -g | -l | -te | -tw | -e} ` -- Only one flag can be specified. -- If no flag is specified, the default search field is contact name. -- The search query is not case-sensitive. -- All contacts with the specified field containing the search query will be displayed in view format. +- Up to one `flag` can be specified for queries relating to that `flag`. +- If no flag is specified, the default search detail is contact name. +- The search query is **not** case-sensitive. +- All contacts with the specified field containing the search query will be displayed in [`view`](#view) format. Expected outcome of usage: ``` @@ -378,7 +392,7 @@ ____________________________________________________________ ### Exiting the program: `exit` Exits the application. -Usage: `exit` +Command format: `exit` Excepted outcome of usage: `exit` @@ -407,12 +421,12 @@ a quick view when using the application. Action | Command Format | Example --- | --- | --- | List all valid commands and usage | `help` | `help` -Add a new contact| `add -n -g -e -te -l -tw ` | `add -n Marcus`
`add -n John Doe -g johndoecoder -e john@email.com -te johndoe`
+Add a new contact| `add -n {-g } {-e } {-te } {-l } {-tw }` | `add -n Marcus`
`add -n John Doe -g johndoecoder -e john@email.com -te johndoe`
List all contacts | `ls` | `ls` View a contact| `view ` | `view 2` -Edit a contact| `edit -n -g -e -te -l -tw ` | `edit 1 -e john.doe@email.com`
`edit 0 -n Tan -g tanned -te tantan`
-Delete contact fields| `` | `` +Edit a contact| `edit {-n } {-g } {-e } {-te } {-l } {-tw }` | `edit 1 -e john.doe@email.com`
`edit 0 -n Tan -g tanned -te tantan`
+Delete contact fields| ` {-g} {-l} {-te} {-tw} {-e}>` | `` Delete a contact | `rm ` | `rm 1` -Search for a contact| `search ` | `search Ashraf`
`search -g revflash`
+Search for a contact| search {-n | -g | -l | -te | -tw | -e} \ | `search Ashraf`
`search -g revflash`
Import contacts from .txt file|`import` | `import` Exit ConTech | `exit` | `exit` From 405919d325a8a8fefecb6377e4f4db60d05984ad Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Fri, 29 Oct 2021 01:53:16 +0800 Subject: [PATCH 568/756] Update `delete` command description --- docs/UserGuide.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 0b9f5e5bc1..e7dc32d813 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -219,10 +219,11 @@ ____________________________________________________________ ### Deleting a contact: `rm` -Removes the contact with a specified index from the ConTech Book. Before any deletion, ConTech Book will -display the details of the specified contact to be deleted, and prompt user to confirm deletion. +Removes the contact with a specified index from the ConTech Book. The `rm` command can also be used to delete +**all** your contacts at one go, or to remove specific fields for each of your contacts. -Usages: +To improve user experience, before any deletion, ConTech Book will display the details of the contact you specified to +be deleted, and prompt you to confirm deletion. Command formats: From f3358ca2ae13c5e206ff69c38d360fc42ecc2c62 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Fri, 29 Oct 2021 01:53:45 +0800 Subject: [PATCH 569/756] Add delete contact detail to UG --- docs/UserGuide.md | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index e7dc32d813..66ed41c7f5 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -233,8 +233,15 @@ Command formats: * The index must be within the range of indexes displayed in the contact list _(zero-based)_. `rm {-g} {-l} {-te} {-tw} {-e}` +* Deletes a specific detail belong to the contact at index `INDEX` according to the flag specified. +* The index refers to the index number shown in the displayed contact list. +* The index must be within the range of indexes displayed in the contact list _(zero-based)_. +* While all fields are optional, minimally **one** must be specified for any effect to take place. +* The `NAME` (denoted by `-n`) *cannot* be deleted. To delete entire contacts, please use `rm `. +* If the specified detail is already empty, no deletion will take place for that detail. + `rm all` -* Deletes all contacts in the ConTech Book +* Deletes all contacts in the ConTech Book. Expected outcome of usages: * Remove selected contact: @@ -247,8 +254,7 @@ Github: github.com/alexlee Email: alex.lee@contech.sg Telegram: t.me/alex133 ____________________________________________________________ -``` -``` + y ____________________________________________________________ ConTech has removed the specified contact: Alex Lee @@ -256,6 +262,23 @@ You now have 2 contact(s). ____________________________________________________________ ``` +* Remove specific details of a contact: +``` +rm 3 -g -te -l -e +____________________________________________________________ +Delete the following fields for Le Zong? (y/n) + +Github: github.com/lezongmun +Telegram: t.me/lezongg +Email: lezongmun@gmail.com +____________________________________________________________ + +y +____________________________________________________________ +The specified fields for Le Zong have been deleted. +____________________________________________________________ +``` + * Remove all contacts: ``` @@ -263,8 +286,7 @@ rm all ____________________________________________________________ Delete all of your contacts? (y/n) ____________________________________________________________ -``` -``` + y ____________________________________________________________ ConTech has removed all 2 of your contact(s). From 111cdabc139cb012a898823fd9d8f50b9b6e19a8 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Fri, 29 Oct 2021 01:54:07 +0800 Subject: [PATCH 570/756] Update `import` command --- docs/UserGuide.md | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 66ed41c7f5..d9d56d6dd0 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -350,17 +350,42 @@ ____________________________________________________________ ### Importing contacts: `import` -Import contacts from a CSV text file into your contact list. +Import contacts from a comma-separated value (CSV) text file into your contact list. -Usage: `import` +Command format: `import` - Data to be imported should be stored in the file `data/import.txt`. -- Invalid or corrupt data will not be imported into the contact list and will be discarded. -- Duplicate contacts will trigger a confirmation message, allowing the user to choose if the duplicate contact should be added. +- Data to be imported should adhere to the following format: + - CSV for **six** fields in the order of `NAME,GITHUB,LINKEDIN,TELEGRAM,TWITTER,EMAIL` + - For values that are empty, a `null` has to be specified. +``` +Le Zong,lezongmun,null,lezongg,null,lezongmun@gmail.com +marcus,null,null,null,null,null +``` +- Invalid or corrupt data will not be imported into the contact list and will be discarded. Their line number in the + `import.txt` will be specified for convenience in identifying problems. +- However, there is a limitation that duplicates will not be checked for when performing contact imports. Do import + with caution. Expected outcome of usage: +``` +import +data/import.txt:3 - "andre,null" is corrupted and not loaded. +data/import.txt:5 - There is an invalid field. +____________________________________________________________ +The github username is not correctly formatted, +Rules for Github username : +* Only contain alphanumeric characters or hyphens +* Only lowercase allowed +* Maximum 39 characters allowed +* Cannot have multiple consecutive hyphens +* Cannot begin or end with a hyphen +____________________________________________________________ -{to be added} +____________________________________________________________ +ConTech has successfully imported 4 lines +____________________________________________________________ +``` ### Viewing help: `help` From f6f5b9edf9e9dce0a1f4d4b48e9bcc032305abea Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Fri, 29 Oct 2021 01:54:19 +0800 Subject: [PATCH 571/756] Add note for `help` command at the end --- docs/UserGuide.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index d9d56d6dd0..5b1bcdec73 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -391,7 +391,14 @@ ____________________________________________________________ ### Viewing help: `help` Displays a help message explaining what commands are available and each input format. -Usage: `help` +
+ +:information_source: After learning of all the crucial features and commands of **ConTech**, you are ready to begin +using the app. A condensed version of this user guide can be accessed by typing `help`. + +
+ +Command format: `help` Expected outcome of usage: From 56f11c0b7f4ffc535d16d9a4f83e0c745a8ddab8 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Fri, 29 Oct 2021 10:35:56 +0800 Subject: [PATCH 572/756] Fix syntax + edit personal fields --- docs/UserGuide.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 5b1bcdec73..a581fe2cf1 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -110,7 +110,7 @@ Throughout the user guide, you will find the following notations: - e.g. For `{-n | -g | -l | -te | -tw | -e}`, only **up to** one `flag` is allowed, but there are **six** choices. Do familiarise yourself with these notations to better utilise the user guide. -
+
## Features @@ -302,6 +302,7 @@ Command format: `edit {-n } {-g } {-l } {-te -n {-g } {-e } {-te } {-l } {-tw }` | `add -n Marcus`
`add -n John Doe -g johndoecoder -e john@email.com -te johndoe`
+Add a new contact| `add -n {-g } {-e } {-te } {-l } {-tw }` | `add -n Marcus`
`add -n John Doe -g johndoecoder -e john@email.com -te johndoe`
List all contacts | `ls` | `ls` View a contact| `view ` | `view 2` -Edit a contact| `edit {-n } {-g } {-e } {-te } {-l } {-tw }` | `edit 1 -e john.doe@email.com`
`edit 0 -n Tan -g tanned -te tantan`
+Edit a contact| `edit {-n } {-g } {-e } {-te } {-l } {-tw }` | `edit 1 -e john.doe@email.com`
`edit 0 -n Tan -g tanned -te tantan`
Delete contact fields| ` {-g} {-l} {-te} {-tw} {-e}>` | `` Delete a contact | `rm ` | `rm 1` -Search for a contact| search {-n | -g | -l | -te | -tw | -e} \ | `search Ashraf`
`search -g revflash`
+Search for a contact| search {-n | -g | -l | -te | -tw | -e} \ | `search Ashraf`
`search -g revflash`
Import contacts from .txt file|`import` | `import` Exit ConTech | `exit` | `exit` From a98fae856aa8280c8fe70a29097948167a3fe45d Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Fri, 29 Oct 2021 11:43:40 +0800 Subject: [PATCH 573/756] Fix formatting issue --- docs/UserGuide.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index a581fe2cf1..4fa614389c 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -245,6 +245,7 @@ Command formats: Expected outcome of usages: * Remove selected contact: + ``` rm 0 ____________________________________________________________ @@ -263,6 +264,7 @@ ____________________________________________________________ ``` * Remove specific details of a contact: + ``` rm 3 -g -te -l -e ____________________________________________________________ From e8aa334cb32297d0f768b1854b9bf5eb93a37b96 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Fri, 29 Oct 2021 11:45:21 +0800 Subject: [PATCH 574/756] Fix issue --- docs/UserGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 4fa614389c..3e7f3a54e8 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -485,6 +485,6 @@ View a contact| `view ` | `view 2` Edit a contact| `edit {-n } {-g } {-e } {-te } {-l } {-tw }` | `edit 1 -e john.doe@email.com`
`edit 0 -n Tan -g tanned -te tantan`
Delete contact fields| ` {-g} {-l} {-te} {-tw} {-e}>` | `` Delete a contact | `rm ` | `rm 1` -Search for a contact| search {-n | -g | -l | -te | -tw | -e} \ | `search Ashraf`
`search -g revflash`
+Search for a contact| search {-n | -g | -l | -te | -tw | -e} | `search Ashraf`
`search -g revflash`
Import contacts from .txt file|`import` | `import` Exit ConTech | `exit` | `exit` From 0f28962429ab068598c0c444effd3727ae3f0069 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Fri, 29 Oct 2021 11:52:47 +0800 Subject: [PATCH 575/756] Fix issue using escape sequence --- docs/UserGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 3e7f3a54e8..41d1a1ba57 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -485,6 +485,6 @@ View a contact| `view ` | `view 2` Edit a contact| `edit {-n } {-g } {-e } {-te } {-l } {-tw }` | `edit 1 -e john.doe@email.com`
`edit 0 -n Tan -g tanned -te tantan`
Delete contact fields| ` {-g} {-l} {-te} {-tw} {-e}>` | `` Delete a contact | `rm ` | `rm 1` -Search for a contact| search {-n | -g | -l | -te | -tw | -e} | `search Ashraf`
`search -g revflash`
+Search for a contact| search {-n | -g | -l | -te | -tw | -e} <QUERY> | `search Ashraf`
`search -g revflash`
Import contacts from .txt file|`import` | `import` Exit ConTech | `exit` | `exit` From 56652e606188806d64750b36e5590db663a07dab Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Fri, 29 Oct 2021 12:00:10 +0800 Subject: [PATCH 576/756] Add author tags --- src/main/java/seedu/command/EditContactCommand.java | 1 + src/main/java/seedu/command/SearchContactCommand.java | 1 + src/main/java/seedu/parser/EditContactParser.java | 1 + src/main/java/seedu/parser/IndexParser.java | 1 + src/main/java/seedu/parser/SearchContactParser.java | 1 + 5 files changed, 5 insertions(+) diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index 9547e59e19..1fa0ab0924 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -86,6 +86,7 @@ && hasDuplicateField(postEditContactDetails[j], currentContactDetails[j])) { return false; } + //@@author ng-andre private boolean[] hasEditedFields(String[] contactDetails) { boolean[] hasEditedField = new boolean[NUMBER_OF_FIELDS]; for (int i = 0; i < NUMBER_OF_FIELDS; i++) { diff --git a/src/main/java/seedu/command/SearchContactCommand.java b/src/main/java/seedu/command/SearchContactCommand.java index de0d2e197c..e636c6055f 100644 --- a/src/main/java/seedu/command/SearchContactCommand.java +++ b/src/main/java/seedu/command/SearchContactCommand.java @@ -3,6 +3,7 @@ import seedu.exception.InvalidFlagException; import seedu.ui.ExceptionTextUi; +//@@author ng-andre public class SearchContactCommand extends Command { String query; int detailIndex; diff --git a/src/main/java/seedu/parser/EditContactParser.java b/src/main/java/seedu/parser/EditContactParser.java index be0ec9dc57..10948c8c20 100644 --- a/src/main/java/seedu/parser/EditContactParser.java +++ b/src/main/java/seedu/parser/EditContactParser.java @@ -12,6 +12,7 @@ import seedu.exception.MissingArgEditException; import seedu.exception.MissingDetailException; +//@@author ng-andre public class EditContactParser extends ContactParser { public static final String BUFFER = " "; diff --git a/src/main/java/seedu/parser/IndexParser.java b/src/main/java/seedu/parser/IndexParser.java index 8587ebfeeb..b1e293d42c 100644 --- a/src/main/java/seedu/parser/IndexParser.java +++ b/src/main/java/seedu/parser/IndexParser.java @@ -15,6 +15,7 @@ public class IndexParser { private static final int REMOVE_ALL_ID = -2; private static final String numbers = "[0-9]+"; + //@@author ng-andre public static int getIndexFromInput(String userInput) throws NumberFormatException, MissingIndexException { //split user input into 2 strings: command word string and index string diff --git a/src/main/java/seedu/parser/SearchContactParser.java b/src/main/java/seedu/parser/SearchContactParser.java index 3a291e92d0..db557a8c2a 100644 --- a/src/main/java/seedu/parser/SearchContactParser.java +++ b/src/main/java/seedu/parser/SearchContactParser.java @@ -7,6 +7,7 @@ import static seedu.parser.ContactParser.FLAG_INDEX_IN_DETAILS; import static seedu.parser.ContactParser.NUMBER_OF_DETAILS; +//@@author ng-andre public class SearchContactParser implements ContactDetails { //return only search query as a String public String parseSearchQuery(String searchInput) throws MissingArgSearchException { From 17a07c28b3c1510e45086dd40efe9c20544b8da9 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Fri, 29 Oct 2021 12:01:20 +0800 Subject: [PATCH 577/756] Remove unused imports and constants --- src/main/java/seedu/command/DeleteContactCommand.java | 1 - src/main/java/seedu/command/ViewContactCommand.java | 1 - src/main/java/seedu/ui/ViewMessageFormatterUi.java | 1 - 3 files changed, 3 deletions(-) diff --git a/src/main/java/seedu/command/DeleteContactCommand.java b/src/main/java/seedu/command/DeleteContactCommand.java index 1de396b486..e35ed04651 100644 --- a/src/main/java/seedu/command/DeleteContactCommand.java +++ b/src/main/java/seedu/command/DeleteContactCommand.java @@ -3,7 +3,6 @@ package seedu.command; import seedu.contact.Contact; -import seedu.parser.IndexParser; import seedu.ui.TextUi; import seedu.ui.ExceptionTextUi; import seedu.ui.UserInputTextUi; diff --git a/src/main/java/seedu/command/ViewContactCommand.java b/src/main/java/seedu/command/ViewContactCommand.java index 4322e91b5d..b2858cee1e 100644 --- a/src/main/java/seedu/command/ViewContactCommand.java +++ b/src/main/java/seedu/command/ViewContactCommand.java @@ -3,7 +3,6 @@ package seedu.command; import seedu.contact.Contact; -import seedu.parser.IndexParser; import seedu.ui.TextUi; import seedu.ui.ExceptionTextUi; diff --git a/src/main/java/seedu/ui/ViewMessageFormatterUi.java b/src/main/java/seedu/ui/ViewMessageFormatterUi.java index 8bc68a1e60..fe90c1a067 100644 --- a/src/main/java/seedu/ui/ViewMessageFormatterUi.java +++ b/src/main/java/seedu/ui/ViewMessageFormatterUi.java @@ -11,7 +11,6 @@ public class ViewMessageFormatterUi { public static final int TELEGRAM_INDEX = 3; public static final int TWITTER_INDEX = 4; public static final int EMAIL_INDEX = 5; - public static final int NUMBER_OF_FIELDS = 6; public static String viewNameFormatter(Contact contact) { if (contact.getName() == null) { From 2289404a5e20f10e89ceb01e968cd9fbef846254 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Fri, 29 Oct 2021 12:03:27 +0800 Subject: [PATCH 578/756] Project level code reformat --- .../java/seedu/command/AddContactCommand.java | 19 +++++++++--------- .../seedu/command/DeleteContactCommand.java | 2 +- .../seedu/command/EditContactCommand.java | 4 ++-- .../seedu/command/ViewContactCommand.java | 2 +- src/main/java/seedu/contact/Contact.java | 10 +++++----- src/main/java/seedu/duke/Duke.java | 20 +++++++++---------- .../InvalidDeleteDetailException.java | 2 +- .../parser/AddPersonalContactParser.java | 6 +++--- .../seedu/parser/DeleteContactParser.java | 2 +- src/main/java/seedu/parser/MainParser.java | 4 +--- src/main/java/seedu/parser/RegexParser.java | 3 ++- .../java/seedu/storage/ContactsDecoder.java | 6 +++--- src/main/java/seedu/storage/Storage.java | 4 ++-- src/main/java/seedu/ui/TextUi.java | 6 +++--- 14 files changed, 45 insertions(+), 45 deletions(-) diff --git a/src/main/java/seedu/command/AddContactCommand.java b/src/main/java/seedu/command/AddContactCommand.java index caddda004c..4da543714f 100644 --- a/src/main/java/seedu/command/AddContactCommand.java +++ b/src/main/java/seedu/command/AddContactCommand.java @@ -11,6 +11,7 @@ import seedu.ui.UserInputTextUi; import java.util.ArrayList; + import static seedu.parser.ContactParser.NUMBER_OF_FIELDS; public class AddContactCommand extends Command { @@ -21,6 +22,15 @@ public class AddContactCommand extends Command { private final String twitter; private final String email; + public AddContactCommand(String[] details) { + this.name = details[DetailType.NAME.getIndex()]; + this.github = details[DetailType.GITHUB.getIndex()]; + this.linkedin = details[DetailType.LINKEDIN.getIndex()]; + this.telegram = details[DetailType.TELEGRAM.getIndex()]; + this.twitter = details[DetailType.TWITTER.getIndex()]; + this.email = details[DetailType.EMAIL.getIndex()]; + } + public String getLinkedin() { return linkedin; } @@ -45,15 +55,6 @@ public String getGithub() { return github; } - public AddContactCommand(String[] details) { - this.name = details[DetailType.NAME.getIndex()]; - this.github = details[DetailType.GITHUB.getIndex()]; - this.linkedin = details[DetailType.LINKEDIN.getIndex()]; - this.telegram = details[DetailType.TELEGRAM.getIndex()]; - this.twitter = details[DetailType.TWITTER.getIndex()]; - this.email = details[DetailType.EMAIL.getIndex()]; - } - public void execute() { try { Contact addedContact = new Contact(name, github, linkedin, telegram, twitter, email); diff --git a/src/main/java/seedu/command/DeleteContactCommand.java b/src/main/java/seedu/command/DeleteContactCommand.java index e35ed04651..41ce06bc99 100644 --- a/src/main/java/seedu/command/DeleteContactCommand.java +++ b/src/main/java/seedu/command/DeleteContactCommand.java @@ -3,8 +3,8 @@ package seedu.command; import seedu.contact.Contact; -import seedu.ui.TextUi; import seedu.ui.ExceptionTextUi; +import seedu.ui.TextUi; import seedu.ui.UserInputTextUi; diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index 1fa0ab0924..37cb254eb1 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -3,8 +3,8 @@ import seedu.contact.Contact; import seedu.contact.ContactList; import seedu.exception.InvalidFlagException; -import seedu.ui.TextUi; import seedu.ui.ExceptionTextUi; +import seedu.ui.TextUi; import seedu.ui.UserInputTextUi; import java.util.ArrayList; @@ -51,7 +51,7 @@ private void handleDuplicates(Contact postEditContact) throws IndexOutOfBoundsEx } private void updateContact(Contact postEditContact) throws IndexOutOfBoundsException { - contactList.editContactAtIndex(contactDetails,contactIndex); + contactList.editContactAtIndex(contactDetails, contactIndex); //sort the contact list based on name after a contact has been edited contactList.sortContacts(); TextUi.editContactMessage(postEditContact); diff --git a/src/main/java/seedu/command/ViewContactCommand.java b/src/main/java/seedu/command/ViewContactCommand.java index b2858cee1e..9504607fff 100644 --- a/src/main/java/seedu/command/ViewContactCommand.java +++ b/src/main/java/seedu/command/ViewContactCommand.java @@ -3,8 +3,8 @@ package seedu.command; import seedu.contact.Contact; -import seedu.ui.TextUi; import seedu.ui.ExceptionTextUi; +import seedu.ui.TextUi; public class ViewContactCommand extends Command { private final int contactIndex; diff --git a/src/main/java/seedu/contact/Contact.java b/src/main/java/seedu/contact/Contact.java index ae38672026..37401a717e 100644 --- a/src/main/java/seedu/contact/Contact.java +++ b/src/main/java/seedu/contact/Contact.java @@ -73,14 +73,14 @@ public String getName() { return name; } - public String getGithub() { - return github; - } - public void setName(String name) { this.name = name; } + public String getGithub() { + return github; + } + public void setGithub(String github) { this.github = github; } @@ -120,6 +120,6 @@ public void setTelegram(String telegram) { //@@author ng-andre public String[] getContactStringArray() { - return new String[]{ name, github, linkedin, telegram, twitter, email }; + return new String[]{name, github, linkedin, telegram, twitter, email}; } } diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 3f4cf840d2..4515653cd5 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -14,14 +14,14 @@ import seedu.ui.UserInputTextUi; public class Duke { + private final ContactsDecoder contactsDecoder; + private final ContactsEncoder contactsEncoder; private String contactFilePath; private Storage storage; private MainParser parser; private ContactList contactList; private String personalContactFilePath; private Contact personalContact; - private final ContactsDecoder contactsDecoder; - private final ContactsEncoder contactsEncoder; public Duke(String contactFilePath, String personalContactFilePath) { this.contactFilePath = contactFilePath; @@ -39,6 +39,14 @@ public Duke(String contactFilePath, String personalContactFilePath) { } } + /** + * Main entry-point for the java.duke.Duke application. + */ + public static void main(String[] args) { + new Duke("data/contacts.txt", + "data/me.txt").runConTech(); + } + private void runConTech() { Command command; do { @@ -60,12 +68,4 @@ private void runCommandProcedure(Command command) { ExceptionTextUi.fileErrorMessage(contactFilePath); } } - - /** - * Main entry-point for the java.duke.Duke application. - */ - public static void main(String[] args) { - new Duke("data/contacts.txt", - "data/me.txt").runConTech(); - } } diff --git a/src/main/java/seedu/exception/InvalidDeleteDetailException.java b/src/main/java/seedu/exception/InvalidDeleteDetailException.java index 8238232681..b9293a0ffb 100644 --- a/src/main/java/seedu/exception/InvalidDeleteDetailException.java +++ b/src/main/java/seedu/exception/InvalidDeleteDetailException.java @@ -1,4 +1,4 @@ package seedu.exception; -public class InvalidDeleteDetailException extends Exception{ +public class InvalidDeleteDetailException extends Exception { } diff --git a/src/main/java/seedu/parser/AddPersonalContactParser.java b/src/main/java/seedu/parser/AddPersonalContactParser.java index 6a17f9b147..10a0f42762 100644 --- a/src/main/java/seedu/parser/AddPersonalContactParser.java +++ b/src/main/java/seedu/parser/AddPersonalContactParser.java @@ -3,12 +3,12 @@ package seedu.parser; import seedu.contact.Contact; +import seedu.exception.InvalidEmailException; import seedu.exception.InvalidGithubUsernameException; +import seedu.exception.InvalidLinkedinUsernameException; import seedu.exception.InvalidNameException; import seedu.exception.InvalidTelegramUsernameException; import seedu.exception.InvalidTwitterUsernameException; -import seedu.exception.InvalidLinkedinUsernameException; -import seedu.exception.InvalidEmailException; import seedu.ui.ExceptionTextUi; import seedu.ui.TextUi; import seedu.ui.UserInputTextUi; @@ -17,7 +17,7 @@ public class AddPersonalContactParser extends RegexParser { private Contact personalContact; public AddPersonalContactParser() { - personalContact = new Contact(null, null,null,null, null,null); + personalContact = new Contact(null, null, null, null, null, null); } public void collectPersonalDetails() { diff --git a/src/main/java/seedu/parser/DeleteContactParser.java b/src/main/java/seedu/parser/DeleteContactParser.java index bf348d372e..aeebacd16e 100644 --- a/src/main/java/seedu/parser/DeleteContactParser.java +++ b/src/main/java/seedu/parser/DeleteContactParser.java @@ -8,9 +8,9 @@ //@@author ng-andre public class DeleteContactParser implements ContactDetails { - private static final int DELETE_CONTACT_INDEX = 6; public static final int NUMBER_OF_DELETE_ARGS = 3; public static final String BUFFER = " "; + private static final int DELETE_CONTACT_INDEX = 6; boolean[] hasDeletedDetail(String userInput) throws InvalidFlagException, InvalidDeleteDetailException { boolean[] hasDeletedDetail = new boolean[7]; //all false by default diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index f73e215ab6..ba05858e1d 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -32,6 +32,7 @@ import static seedu.parser.ContactParser.NUMBER_OF_FIELDS; public class MainParser { + public static final int NAME_INDEX = 0; private static final String ADD_CONTACT_COMD = "add"; private static final String EDIT_CONTACT_COMD = "edit"; private static final String DELETE_CONTACT_COMD = "rm"; @@ -42,11 +43,8 @@ public class MainParser { private static final String SEARCH_COMD = "search"; private static final String IMPORT_COMD = "import"; private static final String PERSONAL_CONTACT_COMD = "me"; - private static final int COMD_WORD_INDEX = 0; private static final int ISOLATE_COMD_WORD = 2; - public static final int NAME_INDEX = 0; - private final AddContactParser addContactParser = new AddContactParser(); private final EditContactParser editContactParser = new EditContactParser(); private final SearchContactParser searchContactParser = new SearchContactParser(); diff --git a/src/main/java/seedu/parser/RegexParser.java b/src/main/java/seedu/parser/RegexParser.java index 9ac3bed423..0ee21564a2 100644 --- a/src/main/java/seedu/parser/RegexParser.java +++ b/src/main/java/seedu/parser/RegexParser.java @@ -9,6 +9,7 @@ import seedu.exception.InvalidNameException; import seedu.exception.InvalidTelegramUsernameException; import seedu.exception.InvalidTwitterUsernameException; + import java.util.logging.Level; import java.util.logging.Logger; @@ -21,7 +22,7 @@ public abstract class RegexParser { public static final String EMAIL_FLAG = "e"; protected static final String[] FLAG_SEQUENCE = {NAME_FLAG, GITHUB_FLAG, LINKEDIN_FLAG, - TELEGRAM_FLAG, TWITTER_FLAG, EMAIL_FLAG}; + TELEGRAM_FLAG, TWITTER_FLAG, EMAIL_FLAG}; private static final Logger LOGGER = Logger.getLogger(RegexParser.class.getName()); public void checkRegex(String flag, String detailToParse) diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index 434d5d6705..b1b5f7cd14 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -17,13 +17,13 @@ import seedu.parser.RegexParser; import seedu.ui.ExceptionTextUi; -import static seedu.storage.Storage.SEPARATOR; -import static seedu.parser.ContactParser.NUMBER_OF_FIELDS; - import java.io.File; import java.io.FileNotFoundException; import java.util.Scanner; +import static seedu.parser.ContactParser.NUMBER_OF_FIELDS; +import static seedu.storage.Storage.SEPARATOR; + public class ContactsDecoder extends RegexParser { public ContactList readContacts(File contactFile, String contactFilePath) throws FileErrorException { ContactList updatedContactList = new ContactList(); diff --git a/src/main/java/seedu/storage/Storage.java b/src/main/java/seedu/storage/Storage.java index c4893d9170..c0b75a3380 100644 --- a/src/main/java/seedu/storage/Storage.java +++ b/src/main/java/seedu/storage/Storage.java @@ -12,13 +12,13 @@ import java.io.IOException; public class Storage { + public static final String SEPARATOR = ","; private final String contactFilePath; private final File contactFile; private final String personalContactFilePath; private final File personalContactFile; private final ContactsDecoder contactsDecoder; private final ContactsEncoder contactsEncoder; - public static final String SEPARATOR = ","; public Storage(String contactFilePath, String personalContactFilePath, ContactsDecoder contactsDecoder, ContactsEncoder contactsEncoder) { @@ -27,7 +27,7 @@ public Storage(String contactFilePath, String personalContactFilePath, ContactsD this.personalContactFilePath = personalContactFilePath; this.personalContactFile = new File(personalContactFilePath); this.contactsDecoder = contactsDecoder; - this.contactsEncoder = contactsEncoder; + this.contactsEncoder = contactsEncoder; } //@@author lezongmun diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 94c9b9206f..34f519e5d0 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -2,17 +2,17 @@ import seedu.contact.Contact; import seedu.contact.ContactList; + import java.util.ArrayList; public abstract class TextUi { + public static final int GITHUB_INDEX = 1; + public static final int EMAIL_INDEX = 5; private static final String LOGO = "\n _____ _______ _ \n" + " / ____| |__ __| | | \n" + " | | ___ _ __ | | ___ ___| |__ \n" + " | | / _ \\| '_ \\| |/ _ \\/ __| '_ \\ \n" + " | |___| (_) | | | | | __/ (__| | | |\n" + " \\_____\\___/|_| |_|_|\\___|\\___|_| |_|\n" + " "; - private static final String LINE = "____________________________________________________________\n"; - public static final int GITHUB_INDEX = 1; - public static final int EMAIL_INDEX = 5; // Used for print messages after user inputs private static void printDoubleLineMessage(String message) { From d7240b066733841116423b24d72eaf7b9490ea57 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Fri, 29 Oct 2021 12:07:59 +0800 Subject: [PATCH 579/756] Fix checkstyle and some spelling errors in comments --- src/main/java/seedu/parser/RegexParser.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/parser/RegexParser.java b/src/main/java/seedu/parser/RegexParser.java index 0ee21564a2..6c3c24aa9d 100644 --- a/src/main/java/seedu/parser/RegexParser.java +++ b/src/main/java/seedu/parser/RegexParser.java @@ -22,7 +22,7 @@ public abstract class RegexParser { public static final String EMAIL_FLAG = "e"; protected static final String[] FLAG_SEQUENCE = {NAME_FLAG, GITHUB_FLAG, LINKEDIN_FLAG, - TELEGRAM_FLAG, TWITTER_FLAG, EMAIL_FLAG}; + TELEGRAM_FLAG, TWITTER_FLAG, EMAIL_FLAG}; private static final Logger LOGGER = Logger.getLogger(RegexParser.class.getName()); public void checkRegex(String flag, String detailToParse) @@ -83,7 +83,7 @@ protected void checkTwitterUsernameRegex(String detailToParse) throws InvalidTwi } protected void checkTelegramUsernameRegex(String detailToParse) throws InvalidTelegramUsernameException { - //allows uppercase, lowercase, numbers and underscore. Length must be atleast 5 characters + //allows uppercase, lowercase, numbers and underscore. Length must be at least 5 characters String telegramRegex = "^[a-zA-Z0-9_]{5,}$"; if (!detailToParse.matches(telegramRegex)) { LOGGER.log(Level.FINE, "Regex check for Telegram username failed"); @@ -92,9 +92,9 @@ protected void checkTelegramUsernameRegex(String detailToParse) throws InvalidTe } protected void checkGithubUsernameRegex(String detailToParse) throws InvalidGithubUsernameException { - //Github username may only contain alphanumeric characters or hyphens. - //Github username cannot have multiple consecutive hyphens. - //Github username cannot begin or end with a hyphen. + //GitHub username may only contain alphanumeric characters or hyphens. + //GitHub username cannot have multiple consecutive hyphens. + //GitHub username cannot begin or end with a hyphen. //Maximum is 39 characters. String githubUsernameRegex = "^[a-z\\d](?:[a-z\\d]|-(?=[a-z\\d])){0,39}$"; if (!detailToParse.matches(githubUsernameRegex)) { From f07e452fe6dcd121eb1e29da1176ac31cb5805d6 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Sun, 31 Oct 2021 13:24:30 +0800 Subject: [PATCH 580/756] Fix broken link for the list --- docs/UserGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 41d1a1ba57..1ce14a8e5a 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -142,7 +142,7 @@ You now have 1 contact(s). ____________________________________________________________ ``` - + ### Listing all contacts: `ls` Lists all the contacts in the ConTech Book with their indexes and names. From d46681734ef4049dd0827af944d9243c80b4e2ef Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Sun, 31 Oct 2021 13:52:42 +0800 Subject: [PATCH 581/756] Fix typo for add and delete contact in command summary --- docs/UserGuide.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 1ce14a8e5a..d820204bf7 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -479,11 +479,11 @@ a quick view when using the application. Action | Command Format | Example --- | --- | --- | List all valid commands and usage | `help` | `help` -Add a new contact| `add -n {-g } {-e } {-te } {-l } {-tw }` | `add -n Marcus`
`add -n John Doe -g johndoecoder -e john@email.com -te johndoe`
+Add a new contact| `add -n {-g } {-e } {-te } {-l } {-tw }` | `add -n Marcus`
`add -n John Doe -g johndoecoder -e john@email.com -te johndoe`
List all contacts | `ls` | `ls` View a contact| `view ` | `view 2` Edit a contact| `edit {-n } {-g } {-e } {-te } {-l } {-tw }` | `edit 1 -e john.doe@email.com`
`edit 0 -n Tan -g tanned -te tantan`
-Delete contact fields| ` {-g} {-l} {-te} {-tw} {-e}>` | `` +Delete contact fields| `rm {-g} {-l} {-te} {-tw} {-e}` | `rm 3 -g -te -l -e` Delete a contact | `rm ` | `rm 1` Search for a contact| search {-n | -g | -l | -te | -tw | -e} <QUERY> | `search Ashraf`
`search -g revflash`
Import contacts from .txt file|`import` | `import` From ef6fb132d67b7934a47fed62c5c196ad0acbde4a Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Sun, 31 Oct 2021 14:02:33 +0800 Subject: [PATCH 582/756] Update FAQ --- docs/UserGuide.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index d820204bf7..965632abba 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -466,8 +466,16 @@ ____________________________________________________________ **Q**: How do I transfer my data to another computer? -**A**: +**A**: Transfer the files inside `data/` to a new directory `data/` in the same location as the jar file on the target +computer. The files are `data/contacts.txt` and `data/me.txt`. +**Q**: Can I edit the files in `data/` manually? + +**A**: Yes, ConTech supports manual editing of `contacts.txt` and `me.txt` in the `data/` directory, although this is +not recommended. When doing so, remember to follow the correct syntax for contact details. Any incomplete/incorrect/ +corrupt data will be discarded by ConTech upon launch. Users are recommended to use the `add` and `edit` commands in the +app instead of manually editing the save data files. For adding a large number of contacts at once, the `import` function +can be used. ## Command Summary From 094dfca636006bd92969d06e0251fb573dd77e32 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Sun, 31 Oct 2021 14:17:36 +0800 Subject: [PATCH 583/756] Add hyperlink to notations in quick start --- docs/UserGuide.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 965632abba..24b4846dc2 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -72,8 +72,8 @@ If you have reached this step without any issues, congratulations! You have succ
:information_source: You are advised to go through the following two sections. -Before moving on to the features of **ConTech**, we have prepared some documentation regarding some common notations -that will be used throughout this guide. +Before moving on to the features of **ConTech**, we have prepared some documentation regarding some common +[notations](#notations) that will be used throughout this guide. However, if you would like to, you can refer to the [Features](#features) below for details of each feature and its respective command. From 58eb2f93435ffab03f4e88808ac4d42c581c2772 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Sun, 31 Oct 2021 14:20:33 +0800 Subject: [PATCH 584/756] Update hyperlinks and quick start --- docs/UserGuide.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 24b4846dc2..6e3bc1e38d 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -52,7 +52,7 @@ when learning how to use **ConTech**. This section aims to get you started with using **ConTech**. 1. Ensure that you have Java `11` or above installed in your Computer. -2. Download the latest version of `contech.jar` from [here](https://github.com/AY2122S1-CS2113T-T09-1/tp/releases). +2. Download the latest version of `contech.jar` from **[here](https://github.com/AY2122S1-CS2113T-T09-1/tp/releases)**. 3. Copy the `contech.jar` file to the folder you want to use as the _home folder_ for **ConTech**. 4. Open your desired _Command Line Interface_ from the folder with `contech.jar` and enter the following code: `java -jar contech.jar`. @@ -73,9 +73,10 @@ If you have reached this step without any issues, congratulations! You have succ :information_source: You are advised to go through the following two sections. Before moving on to the features of **ConTech**, we have prepared some documentation regarding some common -[notations](#notations) that will be used throughout this guide. +**[notations](#notations)** that will be used throughout this guide. You are strongly recommended to familiarise yourself +with the notations used. -However, if you would like to, you can refer to the [Features](#features) below for details of each feature and +You may also refer to the **[features](#features)** below for details of each feature and its respective command.
From 01445d5b9116a6bbc0a7d22eb4e2e15114ac9d82 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Sun, 31 Oct 2021 14:30:02 +0800 Subject: [PATCH 585/756] Update to specify extra inputs are ignored --- docs/UserGuide.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 6e3bc1e38d..d492ab626e 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -127,6 +127,7 @@ Command format: `add <-n> {-g } {-l } {-te } - The `-n` name field is the only compulsory field required to add a contact. The rest are optional. - Up to five other `flags` and `details` can be specified. - ConTech also has built-in duplicate checkers, in case you accidentally add the same contact twice. +- Additional input between the `add` command and the first detail flag will be treated as erroneous input and discarded. Expected outcome of usage: @@ -149,7 +150,8 @@ ____________________________________________________________ Lists all the contacts in the ConTech Book with their indexes and names. Command format: `ls` -* Do note that the indexes start from 0, similar to array indexes, which you may be familiar with. +- Do note that the indexes start from 0, similar to array indexes, which you may be familiar with. +- Additional input after the `ls` command will be treated as erroneous input and discarded. Expected outcome of usage: @@ -178,6 +180,8 @@ Command format: `view ` * Displays all the details of the contact at the specified `INDEX`. * The index refers to the index number shown in the displayed contact list. * The index must be within the range of indexes displayed in the contact list _(zero-based)_. +* Additional input after the `` in the command will be treated as erroneous input and discarded. +
@@ -206,6 +210,8 @@ This refers to the details which you filled in while setting up **ConTech**. Command format: `me` * Displays all the details of the personal contact. +* Additional input after the `me` command will be treated as erroneous input and discarded. + Expected outcome of usage: ``` @@ -224,7 +230,8 @@ Removes the contact with a specified index from the ConTech Book. The `rm` comma **all** your contacts at one go, or to remove specific fields for each of your contacts. To improve user experience, before any deletion, ConTech Book will display the details of the contact you specified to -be deleted, and prompt you to confirm deletion. +be deleted, and prompt you to confirm deletion. Any additional input not specified in the required command format will +be treated as erroneous input and discarded. Command formats: @@ -309,7 +316,7 @@ Command format: `edit {-n } {-g } {-l } {-te Date: Sun, 31 Oct 2021 14:30:15 +0800 Subject: [PATCH 586/756] Update search flag phrasing --- docs/UserGuide.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index d492ab626e..660907753c 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -334,9 +334,9 @@ ____________________________________________________________ Search the ConTech Book for a contact whose details contain the specified query. -Command format: `search {-n | -g | -l | -te | -tw | -e} ` +Command format: `search {-n | -g | -l | -te | -tw | -e} ` -- Up to one `flag` can be specified for queries relating to that `flag`. +- Up to one `flag` can be specified for queries relating to that search detail. - If no flag is specified, the default search detail is contact name. - The search query is **not** case-sensitive. - All contacts with the specified field containing the search query will be displayed in [`view`](#view) format. From e17380643d028bffa5dea218f52c30d6cec4c4f5 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Sun, 31 Oct 2021 14:51:53 +0800 Subject: [PATCH 587/756] Update email regex --- src/main/java/seedu/command/ViewContactCommand.java | 2 +- src/main/java/seedu/parser/RegexParser.java | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/command/ViewContactCommand.java b/src/main/java/seedu/command/ViewContactCommand.java index 261875c837..fa56343910 100644 --- a/src/main/java/seedu/command/ViewContactCommand.java +++ b/src/main/java/seedu/command/ViewContactCommand.java @@ -21,7 +21,7 @@ public int getIndex() { public void execute() { try { Contact viewingContact = IndexParser.getContactFromIndex(contactIndex, contactList); - assert contactIndex >= 0 && contactIndex < contactList.getListSize(); + assert contactIndex >= -1 && contactIndex < contactList.getListSize(); TextUi.viewContactMessage(viewingContact, contactIndex); } catch (IndexOutOfBoundsException e) { ExceptionTextUi.numOutOfRangeMessage(contactList.getListSize()); diff --git a/src/main/java/seedu/parser/RegexParser.java b/src/main/java/seedu/parser/RegexParser.java index d4ecf8d1c4..9a869b0deb 100644 --- a/src/main/java/seedu/parser/RegexParser.java +++ b/src/main/java/seedu/parser/RegexParser.java @@ -56,9 +56,12 @@ public void checkRegex(String flag, String detailToParse) protected void checkEmailRegex(String detailToParse) throws InvalidEmailException { //allow lowercase email ids - String emailRegex = "^([\\w-\\.]+){1,64}@([\\w&&[^_]]+){2,255}.[a-z]{2,}$"; + String emailRegex1 = "^([\\w-\\.]+){1,64}@([\\w&&[^_]]+){2,255}.[a-z]{2,}$"; + String emailRegex = "^(([^<>()\\[\\]\\\\.,;:\\s@\"]+(\\.[^<>()\\[\\]\\\\.,;:\\s@\"]+)*)|" + + "(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|" + + "(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$"; if (!detailToParse.matches(emailRegex)) { - //LOGGER.log(Level.INFO, "Regex check for Email id failed"); + LOGGER.log(Level.INFO, "Regex check for Email id failed"); throw new InvalidEmailException(); } } From 9115d984de3c973fe901890b8e4630d1f1ca610c Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Sun, 31 Oct 2021 15:07:37 +0800 Subject: [PATCH 588/756] Update github regex to include uppercase --- src/main/java/seedu/parser/RegexParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/RegexParser.java b/src/main/java/seedu/parser/RegexParser.java index e51aca81b7..3cfffdb321 100644 --- a/src/main/java/seedu/parser/RegexParser.java +++ b/src/main/java/seedu/parser/RegexParser.java @@ -99,7 +99,7 @@ protected void checkGithubUsernameRegex(String detailToParse) throws InvalidGith //GitHub username cannot have multiple consecutive hyphens. //GitHub username cannot begin or end with a hyphen. //Maximum is 39 characters. - String githubUsernameRegex = "^[a-z\\d](?:[a-z\\d]|-(?=[a-z\\d])){0,39}$"; + String githubUsernameRegex = "^[a-zA-Z\\d](?:[a-zA-Z\\d]|-(?=[a-zA-Z\\d])){0,39}$"; if (!detailToParse.matches(githubUsernameRegex)) { LOGGER.log(Level.FINE, "Regex check for Github username failed"); throw new InvalidGithubUsernameException(); From f83b9ef7d1a935cf50812e333d8bec237422048f Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Sun, 31 Oct 2021 15:17:33 +0800 Subject: [PATCH 589/756] Fix inconsistent index error messages --- src/main/java/seedu/parser/IndexParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/IndexParser.java b/src/main/java/seedu/parser/IndexParser.java index b1e293d42c..9c8589e856 100644 --- a/src/main/java/seedu/parser/IndexParser.java +++ b/src/main/java/seedu/parser/IndexParser.java @@ -13,7 +13,7 @@ public class IndexParser { private static final int PERSONAL_CONTACT_ID = -1; private static final String REMOVE_ALL_INDEX = "all"; private static final int REMOVE_ALL_ID = -2; - private static final String numbers = "[0-9]+"; + private static final String numbers = "^-?\\d+$"; //@@author ng-andre public static int getIndexFromInput(String userInput) From dba382d668a9499cab7154c6860c744c705a14b4 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Sun, 31 Oct 2021 15:34:58 +0800 Subject: [PATCH 590/756] Update linkedin error message --- src/main/java/seedu/ui/ExceptionTextUi.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index baf489d18e..fcab737b86 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -89,6 +89,7 @@ public static void invalidPersonalLinkedinUsernameErrorMessage() { + "Rules for Linkedin username :\n" + " * Lowercase letters only\n" + " * Numbers, underscore and hyphen allowed\n" + + " * Other special characters and spaces not allowed\n" + " * Length between 3 to 100 characters\n\n" + "Please enter your linkedin username again\n" + "or press ENTER to skip."; From 0ba3982f3c1b3cdd01388446c04cd0e7f2cd12c5 Mon Sep 17 00:00:00 2001 From: ng-andre Date: Sun, 31 Oct 2021 16:29:50 +0800 Subject: [PATCH 591/756] Add me as valid index for view --- src/main/java/seedu/command/ViewContactCommand.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/command/ViewContactCommand.java b/src/main/java/seedu/command/ViewContactCommand.java index 9504607fff..eb2ae53557 100644 --- a/src/main/java/seedu/command/ViewContactCommand.java +++ b/src/main/java/seedu/command/ViewContactCommand.java @@ -8,6 +8,7 @@ public class ViewContactCommand extends Command { private final int contactIndex; + private static final int PERSONAL_CONTACT_ID = -1; public ViewContactCommand(int contactIndex) { this.contactIndex = contactIndex; @@ -19,9 +20,13 @@ public int getIndex() { public void execute() { try { - Contact viewingContact = contactList.getContactAtIndex(contactIndex); - assert contactIndex >= 0 && contactIndex < contactList.getListSize(); - TextUi.viewContactMessage(viewingContact, contactIndex); + if (contactIndex == PERSONAL_CONTACT_ID) { + TextUi.viewPersonalContactMessage(this.personalContact); + } else { + Contact viewingContact = contactList.getContactAtIndex(contactIndex); + assert contactIndex >= 0 && contactIndex < contactList.getListSize(); + TextUi.viewContactMessage(viewingContact, contactIndex); + } } catch (IndexOutOfBoundsException e) { ExceptionTextUi.numOutOfRangeMessage(contactList.getListSize()); } From f1b0c072f7f53c26b1e8d64c83a86ff06b3df4d7 Mon Sep 17 00:00:00 2001 From: ng-andre Date: Sun, 31 Oct 2021 16:30:11 +0800 Subject: [PATCH 592/756] Update getIndex order for consistency --- src/main/java/seedu/parser/MainParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index ba05858e1d..c71e8c81c2 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -248,8 +248,8 @@ private Command parseViewContact(String userInput) { //@@author lezongmun private Command parseDeleteContact(String userInput) { try { - int deletedIndex = IndexParser.getIndexFromInput(userInput); boolean[] hasDeletedDetail = deleteContactParser.hasDeletedDetail(userInput); + int deletedIndex = IndexParser.getIndexFromInput(userInput); return new DeleteContactCommand(deletedIndex, hasDeletedDetail); } catch (NumberFormatException | IndexOutOfBoundsException e) { return new FailedCommand(FailedCommandType.NUM_OUT_OF_BOUND); From b3a7a358d27a6cf5e8f46ec3522209f25aa0f3ea Mon Sep 17 00:00:00 2001 From: lezong Date: Mon, 1 Nov 2021 20:57:24 +0800 Subject: [PATCH 593/756] Minor edits --- .../seedu/command/AddContactCommand.class | Bin 0 -> 4052 bytes src/main/java/seedu/command/Command.class | Bin 0 -> 629 bytes .../seedu/command/DeleteContactCommand.class | Bin 0 -> 3189 bytes .../seedu/command/EditContactCommand.class | Bin 0 -> 4605 bytes src/main/java/seedu/command/ExitCommand.class | Bin 0 -> 316 bytes .../java/seedu/command/FailedCommand$1.class | Bin 0 -> 1383 bytes .../java/seedu/command/FailedCommand.class | Bin 0 -> 1946 bytes src/main/java/seedu/command/HelpCommand.class | Bin 0 -> 316 bytes .../seedu/command/ImportContactCommand.class | Bin 0 -> 1778 bytes .../command/InvalidDetailCommand$1.class | Bin 0 -> 1021 bytes .../seedu/command/InvalidDetailCommand.class | Bin 0 -> 1178 bytes .../seedu/command/ListContactsCommand.class | Bin 0 -> 1008 bytes .../command/PersonalContactCommand.class | Bin 0 -> 440 bytes .../seedu/command/SearchContactCommand.class | Bin 0 -> 701 bytes .../seedu/command/ViewContactCommand.class | Bin 0 -> 1199 bytes src/main/java/seedu/contact/Contact.class | Bin 0 -> 2292 bytes .../seedu/contact/ContactComparator.class | Bin 0 -> 691 bytes src/main/java/seedu/contact/ContactList.class | Bin 0 -> 2358 bytes src/main/java/seedu/contact/DetailType.class | Bin 0 -> 1234 bytes src/main/java/seedu/duke/Duke.class | Bin 1234 -> 2404 bytes .../seedu/exception/FileErrorException.class | Bin 0 -> 229 bytes .../exception/ForbiddenDetailException.class | Bin 0 -> 241 bytes .../InvalidDeleteDetailException.class | Bin 0 -> 249 bytes .../exception/InvalidEmailException.class | Bin 0 -> 235 bytes .../exception/InvalidFlagException.class | Bin 0 -> 233 bytes .../InvalidGithubUsernameException.class | Bin 0 -> 253 bytes .../InvalidLinkedinUsernameException.class | Bin 0 -> 257 bytes .../exception/InvalidNameException.class | Bin 0 -> 233 bytes .../InvalidTelegramUsernameException.class | Bin 0 -> 257 bytes .../InvalidTwitterUsernameException.class | Bin 0 -> 255 bytes .../exception/MissingArgAddException.class | Bin 0 -> 237 bytes .../exception/MissingArgEditException.class | Bin 0 -> 239 bytes .../exception/MissingArgSearchException.class | Bin 0 -> 243 bytes .../exception/MissingDetailException.class | Bin 0 -> 237 bytes .../exception/MissingIndexException.class | Bin 0 -> 235 bytes .../java/seedu/parser/AddContactParser.class | Bin 0 -> 1113 bytes .../parser/AddPersonalContactParser.class | Bin 0 -> 4706 bytes src/main/java/seedu/parser/CommandType.class | Bin 0 -> 973 bytes .../java/seedu/parser/ContactDetails.class | Bin 0 -> 1249 bytes .../java/seedu/parser/ContactParser.class | Bin 0 -> 2382 bytes .../seedu/parser/DeleteContactParser.class | Bin 0 -> 1836 bytes .../java/seedu/parser/EditContactParser.class | Bin 0 -> 1979 bytes .../java/seedu/parser/FailedCommandType.class | Bin 0 -> 2072 bytes src/main/java/seedu/parser/IndexParser.class | Bin 0 -> 1856 bytes src/main/java/seedu/parser/IndexParser.java | 2 +- src/main/java/seedu/parser/MainParser$1.class | Bin 0 -> 713 bytes src/main/java/seedu/parser/MainParser.class | Bin 0 -> 8142 bytes src/main/java/seedu/parser/RegexParser.class | Bin 0 -> 3437 bytes .../seedu/parser/SearchContactParser.class | Bin 0 -> 1546 bytes .../java/seedu/storage/ContactsDecoder.class | Bin 0 -> 4452 bytes .../java/seedu/storage/ContactsEncoder.class | Bin 0 -> 1937 bytes src/main/java/seedu/storage/Storage.class | Bin 0 -> 2577 bytes src/main/java/seedu/ui/ExceptionTextUi.class | Bin 0 -> 11439 bytes src/main/java/seedu/ui/TextUi.class | Bin 0 -> 12383 bytes src/main/java/seedu/ui/TextUi.java | 2 +- src/main/java/seedu/ui/UserInputTextUi.class | Bin 0 -> 993 bytes .../seedu/ui/ViewMessageFormatterUi.class | Bin 0 -> 2473 bytes 57 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 src/main/java/seedu/command/AddContactCommand.class create mode 100644 src/main/java/seedu/command/Command.class create mode 100644 src/main/java/seedu/command/DeleteContactCommand.class create mode 100644 src/main/java/seedu/command/EditContactCommand.class create mode 100644 src/main/java/seedu/command/ExitCommand.class create mode 100644 src/main/java/seedu/command/FailedCommand$1.class create mode 100644 src/main/java/seedu/command/FailedCommand.class create mode 100644 src/main/java/seedu/command/HelpCommand.class create mode 100644 src/main/java/seedu/command/ImportContactCommand.class create mode 100644 src/main/java/seedu/command/InvalidDetailCommand$1.class create mode 100644 src/main/java/seedu/command/InvalidDetailCommand.class create mode 100644 src/main/java/seedu/command/ListContactsCommand.class create mode 100644 src/main/java/seedu/command/PersonalContactCommand.class create mode 100644 src/main/java/seedu/command/SearchContactCommand.class create mode 100644 src/main/java/seedu/command/ViewContactCommand.class create mode 100644 src/main/java/seedu/contact/Contact.class create mode 100644 src/main/java/seedu/contact/ContactComparator.class create mode 100644 src/main/java/seedu/contact/ContactList.class create mode 100644 src/main/java/seedu/contact/DetailType.class create mode 100644 src/main/java/seedu/exception/FileErrorException.class create mode 100644 src/main/java/seedu/exception/ForbiddenDetailException.class create mode 100644 src/main/java/seedu/exception/InvalidDeleteDetailException.class create mode 100644 src/main/java/seedu/exception/InvalidEmailException.class create mode 100644 src/main/java/seedu/exception/InvalidFlagException.class create mode 100644 src/main/java/seedu/exception/InvalidGithubUsernameException.class create mode 100644 src/main/java/seedu/exception/InvalidLinkedinUsernameException.class create mode 100644 src/main/java/seedu/exception/InvalidNameException.class create mode 100644 src/main/java/seedu/exception/InvalidTelegramUsernameException.class create mode 100644 src/main/java/seedu/exception/InvalidTwitterUsernameException.class create mode 100644 src/main/java/seedu/exception/MissingArgAddException.class create mode 100644 src/main/java/seedu/exception/MissingArgEditException.class create mode 100644 src/main/java/seedu/exception/MissingArgSearchException.class create mode 100644 src/main/java/seedu/exception/MissingDetailException.class create mode 100644 src/main/java/seedu/exception/MissingIndexException.class create mode 100644 src/main/java/seedu/parser/AddContactParser.class create mode 100644 src/main/java/seedu/parser/AddPersonalContactParser.class create mode 100644 src/main/java/seedu/parser/CommandType.class create mode 100644 src/main/java/seedu/parser/ContactDetails.class create mode 100644 src/main/java/seedu/parser/ContactParser.class create mode 100644 src/main/java/seedu/parser/DeleteContactParser.class create mode 100644 src/main/java/seedu/parser/EditContactParser.class create mode 100644 src/main/java/seedu/parser/FailedCommandType.class create mode 100644 src/main/java/seedu/parser/IndexParser.class create mode 100644 src/main/java/seedu/parser/MainParser$1.class create mode 100644 src/main/java/seedu/parser/MainParser.class create mode 100644 src/main/java/seedu/parser/RegexParser.class create mode 100644 src/main/java/seedu/parser/SearchContactParser.class create mode 100644 src/main/java/seedu/storage/ContactsDecoder.class create mode 100644 src/main/java/seedu/storage/ContactsEncoder.class create mode 100644 src/main/java/seedu/storage/Storage.class create mode 100644 src/main/java/seedu/ui/ExceptionTextUi.class create mode 100644 src/main/java/seedu/ui/TextUi.class create mode 100644 src/main/java/seedu/ui/UserInputTextUi.class create mode 100644 src/main/java/seedu/ui/ViewMessageFormatterUi.class diff --git a/src/main/java/seedu/command/AddContactCommand.class b/src/main/java/seedu/command/AddContactCommand.class new file mode 100644 index 0000000000000000000000000000000000000000..ec2989565fe8e6b96126a1aba134ee8ce34b62c7 GIT binary patch literal 4052 zcmb_f`Fj)B6+L4uBgkK+?woWqkMo|54wReZ{er}2!6PkYf0OMIV|$DdJgUIw4_;yHXyo_$`# z7i88Kz4#Ko?7>&OSc|W!xFCC76!A3?Ul;KW5#JQ?EeYb=D!$`IKsIPC>~cvaf7gTW zdGNfb-xo3M#Sid96_*t_Q~HFVz!yHQpVR|MJ(UQIS{XBy*rvdpFs);`BMLl8Gc|6+ z%@kG3NE(TZKA}LhPMMZvWE8lJ3EfO8XpHO|-WA+CHZnLi7z&05MinR_1@-;uRMyf{ z)_y&iGaSr-TY)#yHyj)bMFxToi3JL@p-^=9zFo66MZuzQD6%Iw5Q@xNYiNxI!@;4w zeZ#X>2e*kH2t}jZzPzYYL0xdTFBG0NxfCp3rDwB7#xfbzfSJ{gB#k%&Jw)e(VTH>_ zy`!VE8Y<5IbexDa(9wwGCXN`Hs4P*K9WA5d}F59^b~-RqC(*@4_-(v0brkyWszu%J2qFBT2~Db}T&VLQ5wTQ=heKvOj6)DJi%$Rc2OAmS=m6wQD2m9ZlylF=Nn_ zT($JY zFNt_r#4C7#xK%}8mdIG4X@&cil1qC4X+Gz)QYQv8nRG^jiQ^jng15NG3I)*cSNu)G-w{>u4-NmsI~Bkdj!;Y= zk6yLzT1y8mG(n+!qf?Wt0jDsKg7$e0G3!DKl*SFE;>Kya?Z{>B0!i^niJ7RD=!jif zCuatt?DKslTg^Y5(taByg>VHi9%u}z7oo)d4?Hjnw>XnWV3pLwxze59+D`E>1F)o zW+)wGv03O8JALKlnz&&xw7ybi+dD#?)lp&vG|d)kC}kN5p&ykkm@`I>3SD#R0uN4` z1KY@v;|7^mm`pXZ!HG$0%C0Alm&DSkqh@BJOx@*3gGJ!yHuL|Y?}|W*@9?=0?c-Z7 zl$y+0Wrzrd7zv2PpbO=*sf`mkJ(&#^>Ojvj33Etc&K8$o8wT$ z_=yExsRh|yp#Cg>UtTB9rImR(~0C<#nn0AwUbUH_$sch`K~>5;%lIat9!oddO97(hl{Rf z;UNCNaMyLHUESB<$)k3|D@264x1hU4uPf+^=vqOq5xu^kJ49bp(4AMyNZt((^U<<2(uUzd<0{~aGs~Xgfnsj4F{PNNsL>P!>fjugO~F<8pB=P z)SB|}T|k|0@eJ;mMvGXw^Jp$UYMH^3X{g~Dv|Z)$U`5@}5A_;5#cNPY%Y9hEF#N2= zURL6E*5MF#(`%5`HG~Lj?h$%5!uc+GRW#g!ZC}!xz*{|L^Juw*(Jp_pE01MjcRMzz&1$3j5;nIvo7D|(ptH?w-&c0o278pp z@(XC}X?D$EMII{;Or!Rks!adq&2uiw%RPDAeG$uh{BrbrX0U3jtIg$GoyVGsP@U6o zI<7dbFs8y;cku+wFr$p{ugeIQ;sO3Gc@XQ_5q<22y)2x=Jj)nu2A_|!>M|^+DOw+6 zrJU!JN4Uajc;1IkMZ1ca@*bARt@qz>-Gb{~tWdFbr*eyKab8XWE>QDZs0dRn3(d(V z=NsLxVePPE$1=g-?6S+W>Ad9U;0@XC$&Dmi&_`8 z&3-qvZfZS#m71U0J$?_h9%^mZu zb??C=Fm>13zj~Ee%>jrXfW^{ZLx3C%VNn;0W`h*bhCDtfS*#?bvkaG?ZN)jOiruSq z`+9vF^VpQf=K1~pB=bIAZm?d?lwXtYt~~B7Rm)3QCp}w0qQHLj_6c05(RK<)Chf-) F{{@0Lv)=#! literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/command/Command.class b/src/main/java/seedu/command/Command.class new file mode 100644 index 0000000000000000000000000000000000000000..208c2cc5481211b30b3424a0091a8774e15fa84d GIT binary patch literal 629 zcmZ`$!A`9Ogti3(+XduN=h86IG_hl%B~bJNKXScjpu$L?IS8d3 z#ZC%3{jAv&DBa6h82Iiag#~KM`NTDjm9L@`fm~<*MnLZeBS{Ve<;(MUI+U|(cQ_$r zEtJu(DFW@za!(G}W2*`&E*FC|{!t|gQ_iIqM>Ne);ptq_k5Z~z0qZJ=XP!J$oW$-2 z)2Zu^4#)0;YoiF;hKUs$1y}<0@5Lk>hh0*>K=p6$2QRaeGjaVp=VCaPUZn5R_6>Rx z4LW<%O=o*L^PsnYO?8#NT679VyDtz=bfHC2H4>0(31zBG-6J!Nd)|VL n={hRQ__;-XiTGt*V1raVbraQ8mqmJq{+KkgNKD!yOhfGpP4Isb literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/command/DeleteContactCommand.class b/src/main/java/seedu/command/DeleteContactCommand.class new file mode 100644 index 0000000000000000000000000000000000000000..5a1d0d5c749dcb104c9e50c60b4f9ad4d1b9d3b1 GIT binary patch literal 3189 zcma)8YjYFl6@FHdy=J`z*%)JE$c2j|+klcnOj;mCNU~9pWr76+lf+%5wONo>&h9F4 zl3tQFO`EjoHEjw>+obJ`zw`@j<7m=p`n|uRKZJokXIEOuQ=6$ZKD+1gp8GlP{`>wH zUjjIRKWi96VHs09&{ zMa8QM22$zsg}E#FY-T3An91g|#Vm>Wo5m|fvSQfF$$8JQ?B$aR`qDMq^$gp)Y*gx| zf}Mf%Vk)0sOwSdHsdRB(fs%_pc<|u90(~Y|Ja_5rVy=+MJ|AU@6b0M!xx)EuCRb=v zBcv8-cIIMgwoQ%FT=7b-Sj=8*6JrW`v$LsOzD??)ol?#AjFOkL%jT+r_zlC&m=)7A z%Nf%%tcrrjwFP>6&~RPT@hk?Bv0USN#VpfXa=K4hw&gv`mqhN`!uVwcv2?A>0C(gq z+bq`xrnrB@G7SN_Gvr;CinyY51?$L{$Q>9ANWo^DzcS`28CEkq$aW^%j zYt^b@myb#%b(}(4XOm9qcm`k9@jBj6@hu(S#&>jl4JTE6SI3)3DHv{7KGjNC)^Tc% zinnxp58qeuwvHd*9R>Sc(=6AMrNB^fGwaOoYdU_2AL)1(@9Fq4-qG>>nRw` zw=`}zDNK&gaKKzK9JXT8_w$1P&i-t-*0fWrHoN)hMD8I9$2aHE(8!iv&|z8% zrKJPOx|J-NtKKDxAuymN%c*Xt=d9_v#xmtc6I&R~Nvk&lq_#_pFlVpSy_Q-DP>9T> zXg8$u6$~cEH`_IF^X0lxadXRd%`wx4OT)Vo|0_7o@$C!7BrH)Z;d`ReT*0XF;NS*< zFp!~5^!X?ElnlFMRyGfR_lD$fUPFDuftijG4p~D1s~n8-jA@&W;nf@kM-tZ-wn*ou zX;CdVTV3(EJ-AsI`*yn)xY=3~BOBcFsi7BpA7YH9+vb|yjOE>^U*96vlSZ{M9k@PUV+Gkdmbqm5k@j&7@q2JL#)AMK00 zo6Jz%j`m!pD_rynm~+>1%yPKIxP-mBi^q8lj`23qum?{d0R`j4BIqMNfyod*j1e5^ zz>gA7cHmDEf2srj3h`qd_;KP-ci>YPko`+r1G0jF_^>Qq;wo*P!fC>1i5;Uaa$D}0 z_#Dc_=x2yb9R3W^yCf<2I^h6fgu{d**hZ(fW0agTNHrDg<5QtT*Tmlu`Ac}L+b2Fk z?cAA!V(UMAcJcX^i1I(yKv({+=)Qx;gz^#kTa0z6pQ864=(+kiw*6~T$PH)>^v)h0 z=v&A3+c+fWg}#m*lk12V1n04-*pXe-+rNf=zUIN!flylm0}@@tk8X;E01o;^O0qmB zSe}zCOopkO!(kLzloxRnB^F}|Px1nLiucwr@_~MI-NO?qvg$odshA#$V20!vBR@d( zyl40(alcPYa-3>lCu7J@He(oR`g}Tg4(@GWSLk<3Xmh_O*igU})t+EMpFx}@mI6OY z?+>uNV=VA#8b8CI_^Kg#4`YFo5xKzv*OZy2YhOw##f|^7BovKKHZZh~-M67OFnqU3 z8R;z21tG?c-A2!(vW`81b+xcj!Ma=6UcuBBwokC07WN1YJsRfa;q_d=5Ti}Ao*7mw z%N)!w1LxSS-(b||F^fDd6E32FGA^Ks=ip!-Z?MvDlJhRE@KfO`KIF&p$9RFa_DlGJ z(*K0v=W#cBn>FvhhyBcFAOE^pd4&dA^?sX4jnIwb3?mZ1{|U5-bv(9)VF@cPF$>}G zHK=^-U*l&g8PdEB9K1_Sz#+Dx^pFhT7{?AU371&rWscwtZk3yqu_;wy!&cdlwPu;S z;_>KN6$j+I|9t4tabGK2c0gapp*v7xYlubvhVJ$x1OqF1<18bhpOLZ76NzBoa%Py2arykH8;=R|xG*O~>eE6#BXduvc+!hjWaQgtg*+wXX)iv9&&!8rggh&v&v|hY z&%5!07k<1bQm15e+Krdo_<{_-DCA2jzAToV5%LuwFAMpqkgo~(x>)xO6_Z}95WN~Q zD!wUSzU9R$__m6(3TA8xZXFqp^o95I4@aVX{n0(4$UyKO1xiRkeSa#MvGk<1T~A~U z$2I;b@J9NEf_W(iqX-4srciYAwvFXEMZvUiC~|jjAQUOj)^Ii&3;WtRfiIx}fn>lMuGsIpP0bGrg(e=2S$Xb780Ba$5-HPTVpK!Iu;GGbYaBS(h_ z){oG#14H_R{awX(6trX~;<{yQG18e-Qco}mVmu=sJQOn~YDxG^a=&UA8hT`Xbf$$WYhEUL1u^TvgYt8vIm zGm?cEl+X~knd_ZZvP(b5jN%prq%f1Lmd1E77o{LCyXnr=qe`s0*ToVAba_Wo*>ubp zGzB*^CA5W&`%~lN%>Gh=x`wUTp;STc-QQWg2$LigP%x;Z?k*A&HcR z*Kt9^$8fKL`Q-|-{Tt3&!+STTvdMU+1V9A~@@kACB)db&gL=Y@4<_`nl9+}Z##LO@ zFoo}HcmtPIT-NX=?$xjdpJ167^h(29xT4|XGW!FJX!xPn_am`ox@}9=G85f>>9l@W zV5cDtL&JU?(6AR{Dt@ftC-|v`xABgKpW$5%@8Rbvexc!)c%Kz}Si`UIYYqEgYWNM_ z;nZ9O?1#U_?=<{gWE#sp=V7Jc4|re0ABFr$$e)G$MaW-;Y{5qrw3b)(6a4zqxU7>*m4H2?TH}*8Q^$Qp#fbR;LED-)Ics*8{D`s$x0(Eu z%#Pd0+R9dK2ug>HOhzB$DktsWRt*y$Zh$jyYF$G~QE~q^vG+qQw4|Zl980FsM#-I) zYAu8&G*>uX3X_&erHheZldF^|DQGGqBb2m^F@um$Ssz(rcrOoK3G@vT46;Ly^N6|5 zn&Hv?M$GD!wx^nz;P`}f*giVQ&t$&$n(6UU8!xF37W}!saC)nU&qhRrIfY|WQc%v{ zHlBo`GCTeI^z;a2jAYE{t+4vK`Km_LS*dX9ep+nnS80DlALsTSjy9RrzU*ib zzR3g3JG~JwM~#Frme$94{0eu!X<3p?H<{o#ZxaeqmF5*ZsW9ySJY!cz89V(6UQ&pt zxREi_M!eL9c&o6o8QjJz;O)F6Y4G6=^zgFQORfg%$bY1QUr+wd3Vs9mz6yRL`Th!i zfPAomA0)r2g5OL&RKedx{%(Xz`kQG5k1SHisRcB)N=qeIPnoS4A&rt-Nn7QX*WkYh z#ou)SHU8Nb;5g4I1=~oQ=^)TXItw1m#x%6^%XaK2Z14=1*HEI@|2iBsXW;ecP&wyr%b%yN6P|j5o~QsA8v=i+KQ(79HeSgz41RP_%)=DKwUyoMy*B z^e>~s%dwjaoODp^;E`R}D$F@?b&g-0DLB`33U$rRQv2kkn31-gTCsapkIS(}ZBYZv$;;T+qPCxb zYZ5#CffnYE|Fe4Bjy0YZPowK)^!sXCJS$I&zzUzM#k1mV_R1ac0%b^XM35E~>a2MeaX6X&_YlL*z2Kxa5{XRnd2$67#(`3}N^xvrc0JZ?l_3+Gj+v`D#zCNYx#F=0`YpCqsMmgg5x(-uC1`xFx?+d&CQ2S8f{qY94-qLx*#eF+8ILfI$1zS6P2h2UIf2Kx{z)5AATsN&3VLEn zm&g9ASBaAfa41M{alY$H3zb0EN^O5Q`cE^8{KZfZjkEc=DY}Y2b`6mPA|y+CBsNQX zBre@O5|d>;>Lsk+8Cc?T`f7bHpL!8%%2}ENm3ur#gHEywJkOT&0{g{_?B}Q0T2E8M pM5&{%vP~oAn^~S~i*@)KmX|wQ9wzlRE^ASvZ4h_vqlOx!{|D4wLC^pI literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/command/ExitCommand.class b/src/main/java/seedu/command/ExitCommand.class new file mode 100644 index 0000000000000000000000000000000000000000..2cc00988e604cedfa5f04ad93f13a4e6ecc35aaf GIT binary patch literal 316 zcmY*UyH3ME5S+CgA2@~t5CsJibU=YinusQX3TO!Q7kh;cVOxrQ$iGDeqTmDgD8!f` z9#_oH&Cbqh-#=d80GwbeL4-8H8rBU)24g`yag}RN1>wQrtst7#g$hO&uF@-C&UG=f z^9L$MJI#GdmR#3nkXQ6Cfb`plhQD1_VI3SjL!L+kE5yD{k+}L} Y-TUeS(F=lKXTm@*D&!o`Bo8qB1V$D+^8f$< literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/command/FailedCommand$1.class b/src/main/java/seedu/command/FailedCommand$1.class new file mode 100644 index 0000000000000000000000000000000000000000..4258b9bc5f84e77c8cede298e8b93fb1efe17da4 GIT binary patch literal 1383 zcma)**>2N76o&t4L!G2<2`y#s0u9izH0*0xOzfnF#6fimNL&Qhv1q`xD?0&khXfCR z1P_1&61QwZ2oOSoE3S~>0gw={fjB26xIqXZMgKqFnKQ>TXEGmuym|}ZAPPxr#HIxL zF`A%JnsKv)Eeu;(##qK#wy|ty*}<}tWr8KcvWsOm%N~}!681?rATXXbuh;7KT+v!c zhmKQiq!+9pbb@rws<}=z>(9?yUbTEc<5-$HvbI#Ik;sCYKj# zo?|rTXPuyI&AJrnG3%Cnl?wmjr0F*T+sRQ~fxfo-6IZNj7S+%^+x5emce&`)=lrUK zgY-ee3F}jSSeI}}#$g6gd6zSWZ#L|?T+MN-S`hewj1!!8 zl0{)T#gb)FSu~a$OP*zlMQ1t9at4zEgUz;N?8Q!G+V-8^EgR1g?ioLy{td-=t-cU`mG2A3Wk8^2iiclJ>MDX$sYv{Dcl`Hy5jsMb8o zZC)nbuB;p9l!C5Sas?$%SJ*<`P_+vJ-7Pj|iUPeY%9W;zN}0}1;Yw+yTq)%$r%E%1 zDlqV8sG_MlrT$*4Y6Y#V39KmUrl}kGiZY!yed;tFeq4Fp4eYTd@cG$q&$@QOPx&g-KqCBKLJctHLTkMWHBIo{zt`3HQ$XYw!jif`l{SV!&cYBsqK>uEfN4d*4ADgH$a hj{UD7h7DA&1A`bMk71Z}q!}5eGXY8ZYCkzr@t=`SEGYm0 literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/command/FailedCommand.class b/src/main/java/seedu/command/FailedCommand.class new file mode 100644 index 0000000000000000000000000000000000000000..4d899f637e4724056d06f1d23fca85b46d47ad67 GIT binary patch literal 1946 zcmah~ZBr9h6n-`kLN+V!2v)I*(L$&M6v4`iVjwjIf)c;96bCOLkI<1*G&)z+6_c`~RyZQ5<-~RxxfG>57Vk(Led>q9& zT-Py;q>dTP>eSs3xGAr50=ER_1r{XYwvJD5M_v~NmIRgsRs`+}+!I(8xG#{3U@e06 z2+|sijBTrGs$@Ejax`?h-yJCpmo^=x3bo{sS#?x3nKrGGDx@mqvS}A~>9MGxYss=L zcSXaMiT62A?lWLW znVf6pzu7X6f^;L6{mLv^g+21l*he*Yz3D$vwj9T@i|<>Aj^ zhJk%NHtvfftBtIN#_=zR`yErf3*$w+7A9FxIYbt1dpPVKSck z)^hV-@d)E}*Lb7p@ixy!he8J#4Hp{;|7$eZqDr-3*=DKUA_j~$0%}%r{W!0VT&rU5 zs$+N0BI%%80oyI*IA&3r5a`n-v)ED&2Fi?GP{%E8f1u@1wRA(x@Jh98vTs4wSiWL& zTHH;`ae17eR^bKG!_9dc>PXP6J0)a^$S<$#uxCmA7l|_Ti3c7gcMs&WVi7 z=V+UCy1wsu<~ww%Uo8|`n>1&d?m1;v*~Mn9&44xK^76LS z13{jwSw5vY7%1O7SX}0(Wt1N$4I!CzuEJc8;Ue)vz9py+@u??%gO-^36`|L4?@PoU zbP%KHgieex;xfjAxG_F8TEmH75c-J=erEu7^LPL%dJWIsF6Q zpHf8MLs_S6{EzI=_Kx@ndl*QZpvyyykBEoP*Fry3=W>mtfdO9HA>=U3TRO(8d6D<= zDokGQ0w$n%09WZ1Mfh(#40m-&FmHZ9{jY$!{T6kzz6sFH=OiUbxkXu|tWvU+10UTU z=6ysx%=pkfBz(j?#CZnB3C{TF@i5YQ>Gh!d=xZ+_jecgjjydkIz)$`i+`uw!;vRQP zVIFDRMuz_zo7{OHOFYsQ`53MjbGE&h74$MH!!kBl!Y1iw zNqw8NACdA7>F#n4_V56Y>G6ctXS5tp`<&Vrbq+eZXQYTQYv^GAq>@SY5FAq8c6`8< KUSDz1*ZnWZq^f}c literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/command/HelpCommand.class b/src/main/java/seedu/command/HelpCommand.class new file mode 100644 index 0000000000000000000000000000000000000000..b6e80b4a5b93a5015145d1264d048995892551a5 GIT binary patch literal 316 zcmY+9u};H45JYEf#|IaKLm~uvc9*3_Dr_ia#fi}#tD46qIn*u*(O!V?^rrXZ=J6|uObLLQkxh8 b5O%j{|2qYOH+a9KmVpq;hZb6k_R#(UBs)9C literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/command/ImportContactCommand.class b/src/main/java/seedu/command/ImportContactCommand.class new file mode 100644 index 0000000000000000000000000000000000000000..f783b2de428d0044db95e34fffb03e94a02b367e GIT binary patch literal 1778 zcmaJ>ZBrXn6n<`!X2WJ_LJ$ZEAhxyAv?dhLs!%Kjs?kuZp(yye>|Ss+Z?n5`GJbUY z6Y|k7eDONL%YR~4u8pa?nOJt%WrZ?|RW`E31(6{8-oP;0G@ZAc$y(gzI?%B@C2Z<<9e zUc-yHN;FN~)k}WmMYro}cpkF?nx{`tJ-go5@B%JrxQ-hdUdB}oMP8;cqu>J#AEKsU zOTzm+bvsQ+P^r*ZQ1&P3@^@Emj=mbYuLpn0+)Oz z*)?RFZ@{}04`3sFrQuU1`59(3e2yC)!-cIl5 z{@pHo)03gU*M%WgU42ej|2s$Neahm= z-cOYbCeE*VgsKjDZOyGTP1zO5Q6=Z2^33UG$d5h$!;h6n4O*yNr%@CbH>G3Q((HE> zO_kems84hBfdYMJBHW+!6yc`!cIsguo#n2ia~y)FfYz7jv`P_z_FUlvqL7IkBU(5^ zY^U%T(Gy%aM*JaJ1?FhYkS_tzIs*P~O=6TR*ZNr7bYiU8LJ!K1$kLXe{}5rRJtR+| z9U*>-VMdI2h&f^dj6=Z$lE@-Om{Z6T^Jx^wLe)$~$d?9?keTl+?VKY)pz$6q{!Gt4 zJFW|4kMN|@Gkbr}2(+&}Lh2A>LChhNXGrgyVC2^`WN06)7Ou06{?Q(uJBE6MWR*{+ z7=K7uS4qh>7^J#oB|Vf2h-i0M(|L-C;O0NWh?Cj? literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/command/InvalidDetailCommand$1.class b/src/main/java/seedu/command/InvalidDetailCommand$1.class new file mode 100644 index 0000000000000000000000000000000000000000..71567a2ac6682a3041fad77c86dd76340fd7a6e2 GIT binary patch literal 1021 zcmah{T~8B16g^W)x2+4Tic(M!p&<2xiV8evOiFhP8`{OR3q0_E+uaFWTy~q?EyiEu zvzi!V3_rkM<1aAYX=%zs1Igr^Id|^dd*|Ny^Y7O=fDLS9F@t*<$he=O-2)+KB|H>j zPQW7p^8ywG5*lu5nJ|03Vflnji3|Syh3pq zrgi_!@?1ydF(tZ4vvOjcSrkh1Z7+yi|G38ER^Uh|P+o&a@pcf!5}wF-if1y$F(KnQ zR%8_Mf?-D7E_#-KTr`44$8J?z?m1c*2BC~q;r3F%D*>+stO;1h3PbPdMZ5Rf;;`EC zs|>R4`#darRuu7wK^Y|6ZJuyDW|;5x@XA08vpuI?ql-ftoubxsM23as!eRAl?>C|> zW4~0@)gz-+(-`Kizaa&oAk!qJfy|Ih4`i04a>@IK z&^`CBkdVP7rZ9>e7O+J8n7+>%@j6OSi8Z`OgV@9e*u)Onh=>!oO=YLL#ZOWUU=ia7 l5}nkBfFW#MKoWPzIf1*B7Nl~7(_KrBk^@-^DHB6U{|Efu<>&wa literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/command/InvalidDetailCommand.class b/src/main/java/seedu/command/InvalidDetailCommand.class new file mode 100644 index 0000000000000000000000000000000000000000..56ac2f56b98d4cad33a040760feb507aa5b29fa1 GIT binary patch literal 1178 zcmah}ZBNrs6n^d)l$8PlVK5jkj)B_{CJLgW1~Y*yVVJmKOi0vjy+UQ{mcAhVq9%S4 z<4fZQzw3`Op4(Oph|=Ud_w>Bqb58sH$Cs}FRt9^tu;s@?Q>g%WJqUo7eyj- ze$4BRP39e05x2KutM$XO+783Xm6l`H`6d<2kSrNTYD3o^a+_`t*1z~lJyIEZcDQAi zxv0caFo>jrI0h6fq9Ea#f+bv+a6`ee(5wi!DPUE=EdjR$+(D8G51LgE`cpVBDZ}t- zqp%o;%xU>~&Y2~KT&D6`x9bOV)4(GW%qH{KY#1VYC5FlWPmns$8-6FrVKi`X z^uoq*owsehWmNgGy{j|C^`MVCYLl0YwqrAlg`zFpK5%Ngv?azLWhzuwd4unpYV#jz z+J!?-HJniogx(uX8d{ic{8vP3g3Zk{9*LJNv!-hrH-br*xn-&QoW2HyJ`jLfB8E#` z2l0crL^womd6Gxyl=Gj#^79`NIq|KB3H!(v=s}cX#3%|w0wbZ{1f7huo%s)ly!-9a zT7RWcVOrv)=YBld4A_P-+zDo24ER?EhLeR!$!_R9vv3|4OcYEkD#TX&z}F8HB8A1L3emMz%~ME~{lMGkG`GB+O?Rt7jp^-r z)s7~YtZ29TYTexqEvbgz)~k)iS}UMIw+T`x3D#KM)1h+1Z89=Lefg#P+I1RkPM|TC3S~gW8e=*%(90MiCcHT(WT)OC}r}S45dc#>Q14 zlbEt`4cBel5W`K}GO=vqHts0Qw>_`cajFAQ=a@vS@u*K&fI^}=XitI^a^<00zh@_` zSB&gu=D$Yba46zd@!zsp4!y)_5Bxj6v+3>XCq9P|W@|rcZtFMVzwWi$Zk-_$L(>s$ zW}CAdj_sMRUzCEHx2rH&DE&KeSx%}S@UW$It0~J?IC-$HRUL+BWn;&7!#4Lvbz}xS z6#@+wo-Q1-Z_M*1lRRD^3SJ3Pq$eoN@>P6CieI2Ukzq}wvA)tI9p86dhrth+E`Em5 zMPw!S9`PQcdl)U|x)_mYqaQtq5%O`2LVkq=F_M@f&IGk4j9(a6QM&Sgm_Vv{jtDkQK@P?8R8>3}6$T_iqIKHPJb(lm7jX8r=-X5C)^ literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/command/PersonalContactCommand.class b/src/main/java/seedu/command/PersonalContactCommand.class new file mode 100644 index 0000000000000000000000000000000000000000..1ebd30a174c24c7d51786b5059de5eb1019ce12c GIT binary patch literal 440 zcmZ{g%TB^j5QhILlmoSjH^g9En6LmAcIiUnrim*wCL;SoJ2A)5*7SnBmWheRg%99E z83#cPMmKXi-~2OY-riqc0UTl1fsNG~%2;zy$GXCX!X}||Vq%k@5=x!!kWluMkO}p^ ziTR?4Mw|}xXe<@QQx1w;BIhb8(tyv*th{&0X_mx#>?d)qgWOM|NXOyft)6HX6(|>5 z*j8w`*g=!f&X~i(3+9;jcQ>K2j4f1Uue;@Ogl7K>{haSD_Ba-H{!kciz|;KN5Ly$% z_rFG-bC&5F`AMtuk5YGt138;5X9O(B$)LnmCEFKI;_coO=s^NPO>AXe6zhDWZOLY6 Xwf6|?8KocE5m5-IM3S%~u?6=77BOW9 literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/command/SearchContactCommand.class b/src/main/java/seedu/command/SearchContactCommand.class new file mode 100644 index 0000000000000000000000000000000000000000..5419bcdfb6b945a66462b827e4a26904b666162a GIT binary patch literal 701 zcmZ`$%Wl&^6g^`nF>xG16OuNxQ2GEuknn;93lN)#N|9U^B(R^_qcGI5iyu|^BG#2C zAQpT8AB8wWQXT>p_t^K|bI;s4^Yz>3F9055;G&N8Ixbjf)q!t2VEKqx_6J0zJ=neiJ7~g#< zP#L9>5@-cFQP0Zxk;C}zb`3l)|H|LlPwHYbG)j}PU^s_#zHG7Hs#Hst<9$t-*| zN)wWbQ97T?B)V@_^l%v+4=x%WJTyJ*V$Z?8hg)a~?B_~FrLPvDIw^FT_~YbM#yUEP znQ@t#jCCED5X;+o%v-VuOOl=O#OCbXEdWj+;Z)hwo8gSPc6Es_)U1ik>by({%0~}b-9n@?Nb(vb|eFtD$oD%>5 literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/command/ViewContactCommand.class b/src/main/java/seedu/command/ViewContactCommand.class new file mode 100644 index 0000000000000000000000000000000000000000..878ade66bdabb49a13b04830f52e0c62cc33e839 GIT binary patch literal 1199 zcmaJ>OH&g;5dJ0)29_m201X5%2x=0P^#Mi!5r|NgsvwpiRdQRhBej}rsC{6{p8_XO zT)f}|D6P`FzsXX2Hk%-&cu3FAeBEDv)7_KrKRK3a;Y@$Akh6H#u%GsHLjq>Ls^e8KTC(3Jg7Cy5k7jHLI5M$aM6r zvM>nQWN4W+Ez_N2h@=ad4O;S5Lojp}O-nrXDqF%{m);Dm+oHi3PG^Xdi<&5TEaDrPXtFna3ZS7Ft2S6?hv zJK_$9;9Rz=m7udz>B4^qGyldYQUAFrNHArR zde+Q0at!L8o~f;in)}RTi0_`ZZbdkbzD;h)^f|fwkqYibB+c44*m^Cm;`in$byGC? zI#1h|FVo~QTrh-V+QMiyoQBQy2%y>9#0b5P7(Jd4;&OO^u7n&JI*EXahhDOMw9Ar5 zh*l+g431(x(QxJ}o z!*p&rc~?NB1$q+))w-!w%}uS+&=tl2fp98aSiQ4k^Q2D*^kvey+sWm0uI=^ETS#V- zsf~EH?NumR*h&`)$&I$tE6|h7#?zU$%O~KiYWuptQ0B4rxfZKv)p9Iv){JU-Ucg^A z%+DG-0)dKA-P21(l~Yr%=;fNWFQA%V7^bP$1bq6wW>f@*&ujI%UNa3Qv~1M1or+#! zj!fFWU{norQQ#nQ{7e6zXL^$vCJsu>us>r|^;~0rN3RuRV5|l+GFf|5+cgDFMD87r zL+;QKr?NSElcBVb_ zGI-|zdbrTGLR>2x9z%#rM~2*0I65o2t8I;P%}Lxo?0BuFeJL;+nRY1x4}D>m9blcG z5|KfN@&}FDuD)W(I))voOR|N+n8k7!@8EnGQxYyncvnJ1!nA}Ba6OCx>3_hN8jVYn++~7=WU$jogU#m?8P`nae`O$Em|Io(H`%x-==l4!=9i$ z*bfyJQbhZU0da(s>blls5FFNjP!5x1jz&ra+8%4gumIyv#R0E&N$8)Vhz(WWs@OX zEIl(s+V)6iNOnz2@43^V?hM3mLI~IF>5Fh^cVFzj>iWp7X|^SWCTs0Qu5W=$9fsRt zcP!pSZ6YkA_B0&pnyjxQUS+&*8kUf*H>tH=vOrvEPH3zrNJ!ghY?<7wGbnxAbu|6a z^h{)ZsY~jeCrd>fii#XAIPxkkQDDey^r#|%J%;?opUbWcsi0kk^c)IEr-LG5C}feMS9*;QkpZdD8Yu0f(4O;O4Qbm5=ALWO&g#!C{_C5k{rWo*rmH0w7u($ zf5Kk&rZ--+Gi`M0Os7}9=s)OR>GbP4yGvl0rNeM`&)N5RKc4qFZ+`#h=U)I^#C94v zT+uL>MhsU{cnw$O+qE>`=H=VFa#@hu>uL1khFliYcn>$_QcmN2d>~CK(qu_)m*sXv zE+1<6NW-l(vbZAmRSl~eZY$`j*_LP2JXb-s^3d2ZiY?D<7Uvzu__AWUUP(c!YBnsx zYdJ!}Oq9*#iYr9DRSaDf7Xp{1If9dyP0RG=6vU_UcNC}#cAai|E2bruTU#5#Sv5AA zJV_h%dWcgnICY3e>EcLTG=(QR#_CjA9`^;u^UY@Xg%uqYb<+#C^IqAiizf<>Ppt<< zG!3g!ta^@VHA=pV%%r>l0$sfk5XY9O;Ol^Ll;9j{|l!LbNk z>KMe3j*oFy$0dyFxQBHepUAhj@V1Um@tKa#abE+yY@nv24x!G`y>`8FtRo55eP;f<;?OVca zH9dFHZdvt?3(b_1W97jiWK+g*lEdL9^-c|hY5Rk8Pa&oJ9h~4~&T-l+9KqBtpTpe6 zFan+L6g$^3o}59PZ$PH-0!rZ(Vs~F4{u9(6c&5+`&_fHL8!C~#IKtC6Fdm|3=rJa3 z3O_=fZX>Z)Xd`(Ln?VYFL>?t-0w+W4WQa{m>`)up+8$2+aDcxcDGbnhvXkuucQV^9 ziD{$jAR-5i)halJDXwF*e3PD3KJ~(I8>!{fOftQP3Thicl8kgSN=)9=5P6@wB$1Oj zM(UnT|3o6m zuOL;Nzx+Q-L_pvP`jyQ{g)KfRD-D#92xUGUI}@HEVVn(#__%W2C;5Z!(~F= Z!E6W|<5R{8b<}&XrV787_&tWp{{apK2TuS1 literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/contact/DetailType.class b/src/main/java/seedu/contact/DetailType.class new file mode 100644 index 0000000000000000000000000000000000000000..fef8722a710e2a79e72748fe63f5e33ee176926b GIT binary patch literal 1234 zcmaJ|XcEJ@0Q4yi6v;a-AGA+m?U2P}C85eDsKCQSh>)_Jx!>Nz`KYd87 zY-(!!+#l6+-;+U_(*1DHp7-v3_niCQuixK(0$70NgM@p2+{XhM6Ef!g7{)^$7WmGh zf)PLABTgPGh;qy-7~_~z5aakn!8pey1#yl~Wh^sD#r%fG5Gyn-Yp`q~DTO(AKx|8w_&krCus&TMQm;Bd-?-ZD-GV z%fNKno!rS6wl#xc{MDsR4$WHIYBD5}sY?^3mHM8=5G>e^Rcs&ZT8)yqTcZ_OoUr+t zVK!OVHxJEB&2*|6qt&pTYBqIg^PKJ2ttE!h|5WOFYKOsR*j2}DwHwq)N{S_=YPIw; zr|x8myehd$t$PqHP|-}E4$WyF(9Tt=Zg8@ca&Dxf>PN_|;FS$b;@8 zdeMccn8J#R+gMeRz*YX2R55~46;U3>c!=>Z&O;od41x1;ahY_3m0H~)5s_r7&%);J zzEx?F(E0u`t<=nBGuxNeoA}?SQr$>@T{n$JxjaYjahP7ZvOLC>0)!-1An6rIk_D1# zfh3$NT-+lNit*_X_rQnixB-Tn#5nTL-vRpq*D2f|i7`x4^ol(nlG{{ z*cDk8EG*cNq6iiVd4JHU?hd`dvebcUlsz2;jIy_bkWrR92peUkgNShqcJA;hWD?{@ cfc(XwlD9!D5?ezMC7P_O>p6qFl;^_SAENf|FaQ7m literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/duke/Duke.class b/src/main/java/seedu/duke/Duke.class index db6bd33b650dae70e17766b13dca23169359d65c..5950fd25d2076d3eb95f741490327668456f3d38 100644 GIT binary patch literal 2404 zcma)7=~5d<5dKzR7M9^Y%wZs48-s+Aa~NVnNMgW=W3B{n0*;+5(trhGMRr$2x${3y zkSEA*S6RXpSLFfnGmnvni1W?tN&*CBS4lHHJ>5OsUmyGTe}Dc3U=qJtxPm)%7{IJr z=1k06s17)HO?+g*3=SWgxM#r%4xgB~Z=nGTN@r0~ONv@n)QX}$HSw8+RjgT9#{*^Y zbBpXRENoy?Ef3Z5rCJ^-tB=+4m5HxwVb@|y$tKj2G$9Q%B{Gh0C;Ypqv|O?MCk9#< zcI`tup0=Hx_^R)woSi8Hrsro|dxr`a7d$DG*?7pHh`yjq&4KND(lyW>iUjBQqMdS9 z^c98b!}k_ao^PNxlnj~i*}xffN!g1B()BWqoetS$ADd3yl-)XIiB^gcdUG<7Nh<#a zPK6MfFA5yjnRi~H6ADnLW;*4h{22q+Mk*1k7&m+^j=K*JOe@sv1%1ZJM>eZ#&5qHQAr;aF>gKY0a$Hq|z&n@{xQbzc>lh~7K@n7BSYQ-U1AQlJsH#0?AuS~8cA2YxE!#8p7^ zuA6b^i!2jqfqgh8G6DzqM!R2QF@-9HyvldpxiE7S?AEX=Nx4Hq7|_t{SuP_(w8#grI99d@rKP|Aa>R} zB?L}(QmHHxL2DITj6)#h5lSYM9lB|t(UX1%X)y5m%gtE{stT)>8Wm_BYv~hOx}{B- zlZmX)8Wf&=D9ahVaYjU?fKJ%a^H#myrYuxEKla*&=nw|^ZMnh^U@anQV33NaM%6oq zgWlP$dgmjY2#@N-$seLH#tBO1#i5*^E1Aml$gwz3->=AeJ#iovYNkjK{o@jPG4)bt3YT z%qkNDCT{Tu!$iAD%Nz({eD`^(qHND|bS~11ny~^uw$WGtUHo_d{_@|aybXNm#0AnZ z`Z7kZt`oU&`V!Y~RnZ>BILJc7ztOBRJQJhUmI8Xz-c~>_&0ZoY_>Tlvec`c+J0!ZbAGjoR-!sK+efo+I}I-bL`?|H=|*%m4rY literal 1234 zcmaJ=>rN9v6#k}Mwp~|><&J_20+x%c;03jKqlQ3I)TBgWByNUwgoW*H)14(Y>4W$h z@&gh~d;lNHc&1xz8yaV_XU=}-GUqnGeqa6su!apC*D)N&NCKl6OA$7qV-mOHFf~jm za9W3kJBrMtz%Zd-gU=w(nU+#ha9t~+rnyd5wx!pUZ_C`b?IoK;`!;cQP1le%FpmX>{te%k zfvoWIj*v%wF-Z1eF^(kz_pq$NGH@R&45_^%E=?yetCWiA@sfDSaHF1WC>__z7r5t% zih)%;P2=kEs1y z+$*{wn28KCR|9H6+6;HAWzj*s^+iOz&a`IPaFOM%n|GwhXn4&qdnLb4u`x{kUk_6- z=;f;wqgPFDjcC7m{&X@rdloLhz7s=}Otd!wkw6Lq#4FX$=%Nj*ree7>bS++@8#qS~ z@u^-qe?a?qhWG^%I|MDAL%+nex<=FQIC%zi@{^?9j}h`eO*gDykg!3L#V~~DbsdHb UUSb_%7^nX}lH8<7Zq@1RAL&atpa1{> diff --git a/src/main/java/seedu/exception/FileErrorException.class b/src/main/java/seedu/exception/FileErrorException.class new file mode 100644 index 0000000000000000000000000000000000000000..23f233332eed1683fa9423e4bba6bed58e644879 GIT binary patch literal 229 zcmX^0Z`VEs1_pBmUM>b^1}=66ZgvJ9Mg}&U%)HDJJ4Oa(4b3n{1{UZ1lvG9rexJ;| zRKL>Pq|~C2#H1Xc2v=}^X;E^jTPBDj4x(I(it>wGE0R+SN;32F^s*Am5_uR{7+4t@ zl!{YRQ%dzyVRHJI${87iK^pXP67$ma;f63MGB5!h2Lg;h2s8{xvH^LrU_Ju_tJZb~ Y#*JWUb|A?H6lMTwU}WF`(o77T07_jlRR910 literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/exception/ForbiddenDetailException.class b/src/main/java/seedu/exception/ForbiddenDetailException.class new file mode 100644 index 0000000000000000000000000000000000000000..12078b9bc4a25ed76db048c7fceb677167d6bcf7 GIT binary patch literal 241 zcmZ`zy9&ZU5S;aqXpC4`TiB_EDQ(2YM+3~{U zq_c>V&}hwe#;G#V{JP^)YGOM)sEhJZL6y)uGwUqiuNV9a5!!hyh?Lz2zbbT5l1K9) dS*a9sgmnrIR0ns^t*~7|M`TEVP?K9i{R976Hw^#) literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/exception/InvalidDeleteDetailException.class b/src/main/java/seedu/exception/InvalidDeleteDetailException.class new file mode 100644 index 0000000000000000000000000000000000000000..e7603953c46847f9e40ddccf81f9652ad5a2d06c GIT binary patch literal 249 zcmaJ*Jr4m<5S(?~afm{#&>`YVjc9x%644O-bGMNv&pY8x{4JG4;RpCpVoyS8H<``M zWG4H3-5&t@sQPf=dnkLT5Zr;bIvEn2R(nmzkK%|4wYj#uNcS5)uGGee;xFU$81htS zq&c%^Wpp%V!wHW$QQAx{As-SQ+ulx{RRwtz2;CENlm`6uf`36mJ&OiL*=_KvLlZf9 gI2)3cT0vJ>pX&1C@q4F8}}l literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/exception/InvalidEmailException.class b/src/main/java/seedu/exception/InvalidEmailException.class new file mode 100644 index 0000000000000000000000000000000000000000..023bcc0a937ca2b344e4dcb7bb8ced8a36d1205d GIT binary patch literal 235 zcmX^0Z`VEs1_pBmUM>b^1}=66ZgvJ9Mg}&U%)HDJJ4Oa(4b3n{1{UZ1lvG9rexJ;| zRKL>Pq|~C2#H1Xc2v=}^X;E^jTPBDj<(XHOn3I{}nwyxJ<64oNT2PXipQo3VSeD4c zz{0@F$e>!BnwnCop9+)H$Et&oK^UY*KPNFST_0`^gCYYH(1{?x2!ufMfFv7`Cky5? cFtBQEXJFh2mSzW%Y(Qb4Adut$(o77T02t9UrvLx| literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/exception/InvalidFlagException.class b/src/main/java/seedu/exception/InvalidFlagException.class new file mode 100644 index 0000000000000000000000000000000000000000..594a7c422d0d54930d89c907eec0b2a9cccb7ceb GIT binary patch literal 233 zcmX^0Z`VEs1_pBmUM>b^1}=66ZgvJ9Mg}&U%)HDJJ4Oa(4b3n{1{UZ1lvG9rexJ;| zRKL>Pq|~C2#H1Xc2v=}^X;E^jTPBDj>6urSn3I{}mXnz7T9KSuP?DLSr^7yg!&VBrV&QQ{_`rMoc8 z%rL{g-j64MA?g;2uuRlU*aF5#X%&wJirwB$pfm|Q5@;-yrd4uwDcnfcXT@3vNw}w( z%1CFSQ|T*juHs|jZX*h{Jk#{Lr%S8?Jvhl!+9;tcFo=k}#G$X}{ErGWv#{e!eQvU^wdA%06GQTPBKC1xeGW|A{G zXXc#D^L2j!7^3E&2**anMpeKXDXr46K(W)^3K)~fCxQAxXecyvltr27YXmQ@%q1qKO`pSkqix&O=pjoj`AQt#bg kBw8r&<9P{gj%Ku&H9s6MdpC&dXKgcDEVIa1;#olX4TEt#$p8QV literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/exception/InvalidNameException.class b/src/main/java/seedu/exception/InvalidNameException.class new file mode 100644 index 0000000000000000000000000000000000000000..28b35bc368e70fc113e3d112623b1af755f3e2a7 GIT binary patch literal 233 zcmX^0Z`VEs1_pBmUM>b^1}=66ZgvJ9Mg}&U%)HDJJ4Oa(4b3n{1{UZ1lvG9rexJ;| zRKL>Pq|~C2#H1Xc2v=}^X;E^jTPBDj>6urSn3I{}mzbOCT9KSuP?DLSr0v;gvRGBMO4p_~iP#)J7*G0lU-P2o%OqKmzr-Hnd0&KE*5Lhpc$ZD2=x? z)fs8e%vpsxSY33IP`o}-Y}A1!*DW0r9hv@KomCYD6b0moC`cuJJ^3dq(8$sb^1}=66ZgvJ9Mg}&U%)HDJJ4Oa(4b3n{1{UZ1lvG9rexJ;| zRKL>Pq|~C2#H1Xc2v=}^X;E^jTPBDj?VDL#oSB#ISd{LVlHyvCoLW$lnV+YZl~|U@ z!@$D8%E+KroSK?as-Fsz)5orbkwF-wNk1nsFI^vQ5Q8EE6VQ<$zzBpu1A!zPkS7b~ dGcd4fZD(NI2$p6Cl59X>pdgUs0MbkhoB*SWHAMgb literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/exception/MissingArgEditException.class b/src/main/java/seedu/exception/MissingArgEditException.class new file mode 100644 index 0000000000000000000000000000000000000000..1321f1ef9b39fa4a0b9cc50cfbf1df1d225f8ce3 GIT binary patch literal 239 zcmX^0Z`VEs1_pBmUM>b^1}=66ZgvJ9Mg}&U%)HDJJ4Oa(4b3n{1{UZ1lvG9rexJ;| zRKL>Pq|~C2#H1Xc2v=}^X;E^jTPBDjFr`^<(dX-kiZ#hXEe1MM<+a}!XCbOBD z%w%8h#}mL14F@J18#Nns0c)hRI*$d+p1Tz&P2+$BnhT|Al^u7KY~(It#aYK$;?rE^ zq_b3Ms&qI>!Zpdn-_Nc-oz5!OgM+-tI!Y)DxG7PPdGz(XzbS!Mp7SE9L+{sxE)0G( eAHmC=j25$Y!GUuB4sk1No6%yKMaBwW1Jw_zn>XbE literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/exception/MissingDetailException.class b/src/main/java/seedu/exception/MissingDetailException.class new file mode 100644 index 0000000000000000000000000000000000000000..321502d8477a049aae1ec02a45db6305bb76cdc8 GIT binary patch literal 237 zcmZury$%6k5S(?~afm`G3XPy}rA9PPi8~1 cQYdH(YkoLT=-oiqkL?KBB0~a%qTC!xZ_)BKqW}N^ literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/exception/MissingIndexException.class b/src/main/java/seedu/exception/MissingIndexException.class new file mode 100644 index 0000000000000000000000000000000000000000..4f4ca45c61c51e0dd4f51de70c9d98c8d177bf89 GIT binary patch literal 235 zcmX^0Z`VEs1_pBmUM>b^1}=66ZgvJ9Mg}&U%)HDJJ4Oa(4b3n{1{UZ1lvG9rexJ;| zRKL>Pq|~C2#H1Xc2v=}^X;E^jTPBDj<(pYtoSB#InU|7U;aZWLT2PXipQo3VSeD4c zz{0@F$e>!BnwnCop9+)H$Et&oK^UY*KPNFST_0`^gCYYH(1{?x2!ufMfFv7`Cky5? cFtBQEXJFh2mSzW%Y(Qb4Adut$(o77T06S$g?EnA( literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/parser/AddContactParser.class b/src/main/java/seedu/parser/AddContactParser.class new file mode 100644 index 0000000000000000000000000000000000000000..39166be10deb5f5f15eab46afea50eb0eb7ffbe0 GIT binary patch literal 1113 zcmb7DU2hUW6g>kAgMbA=sq52R^TA|u@66qE?maVe@7G@+`vC6Yjvp?paNOcp^&#Ph8%d5e zKfGA+;}TLFX$J2DX-elIgFBZ$WKecGx?l+HOHEXjijrvC}aft?4`x zjwTJ8A)DKOsU2&op_whU?pV@n-OoRtjxk)W6Y;33b%*&lG7SFR*G% zJV$|JoukN6;wW>dgsXRYR#Q~uKu2s_*Z-<`GEiid2LgidBfzj^3!(Sap;Sv9gE53B zl`^~>ihqjKsE|f)_%AxQ$JQ_*k7uMRZv+uOKy9AdJQp3=>j&dTivt^PcFu8ApJ*$%K`T)sVU_%qghH?i$iz2n<{1{5L}`H{<=Ln>v4p z1kI6)rVV7NQ4t^;q+OgmBkw7kfqkF_4FFm1Ft|W=0U@Fcpl_hSLw+ml{S0??J))e# zQ!Dj7CkT9k_t_cv7iCL{DW(1iB86fprfizC#GwdI|(1H6I3Hf`!z(7 z!ZI>QBa1TmyT~I&ZeWQrFx(v0i2nhA CKr|!( literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/parser/AddPersonalContactParser.class b/src/main/java/seedu/parser/AddPersonalContactParser.class new file mode 100644 index 0000000000000000000000000000000000000000..080f44cab868e21ebcf2ae52fd32d4a4770db28b GIT binary patch literal 4706 zcmb`K>30)l6vm%v(hd!wh0;>GL1mFPV1pYVnz!d>piAaD?Bk~jtAO=mE`^3b>jEd34TqQ1JViMw)l)jWmrB!4C zxEhAM%Sv}nOkTx)={^v^IIfYNYsLFI@w#4`H;6f?;zsehNg9X5;bw8TMVhyYxlP6G z;&6vF?i7c+#Nlpf-XrE-759n5{nB_q93B*hhot$im`7ARDh`iH<8g6#LdBCRCKNPg zG$Wf%MG~9SsazzQQ_wn))wEbX9JM;a#TV-o)UDT3dTyfvUr+CD1^&(Hm_~&GJ*5rh zlOvk3GcuB3&%9_lkK=+DDdO+hD?w%r zGpn(|NT#UW;d0%o=SK4*yRw>*G6&6#j%v{{t9N%Kp~v*xH4NJ`a8+b~B%Fw(;^E<( zp{L^OdiN>_^p8iiOioXym|JUB%Wao5VqVcHhcmS`(GToE3{1T9zd@nQCUAqt#+-xt-nB z@|%xoF+Js^W>s72cl4ZUOYfX9O>r{!&cC*v-l{V&Fr3aCQEiJZ)2xeyct)Ea(CCw| z9mEE3sX^MiN|=POuZMbk?2D!eVVU#6iCN`>gD~Ka_JBW8Ai+9DmC$fVgJ0!9ztH^q1UzzYxQFvdpJ`i(En%hP2LJlQ)P*XVzE3b%1Ygq%H(q;>A766(#bPnpKc^0 zvUe(I=8CP@V7a~Q<8hH49p;dX9l0%Iq>~wY)yu-L-vx{6W=PgyZcpN2B37VsYm#Pp ziuTtmrMOVHmRxCPFqfWTqzyaFVs{Ge)n$A2dUV`w{Vv7X-s+jFp6zFyJbidr@~oL} z7ULEvmQ~NPtQTAg?%cdf)Xr|XCp)jBJHK}8*zlZC#qcv3zBHUWm?r`ElD6ZAyz$+B z?(l6^c(+S2dO)IEZxpnIZ3BF?bK&Rs7XBzW%hnj9wrDIbpf=>6L|y0@`~|25%-9o}L_L24{GG|)Ab)2S z(BKI7VJ3&pr+gb`pdF3qV3B%P z6ycm$ix>e|$|6o=*~>5sJ(z=DmJ?$1<&3z3dOVUDMc^D{%P%8*8#)STEMWFf=%h)^ z@o$g{`P6h6>QDjAofH55d6a|dDAURGYp{vKtkS}4t>l|i5x{9IZxutXrr%n6u3^YC zSll`+;kW7Mn3?eXjXGtQin%@x~DDbblXk78Zh zilQBsXoHYdCeeAA^M#M>?UWB#uD_f5d(ec7IbAL>_5G-6Qt88MQ&HB1tE+@-fr)FO zh3f=2uI^$C3)kgrT|rzUtRqTXG2)67m&Ww>5!Wbj=^k9&f{QmG+UmF#Rp3gnoFv0! zi0kS~T#^@WRMX>H?BH7L#g(W2e&QM@u4`Smc)^?s*OC&hr6#TuEnGcrT+5i&CVm(T z*9~kPB(6iO<7VQzg}81fu3L%gHsZR2xbF1eS|+%7zoV^=tG5EzJuK&5hIxRv9<0PA zdGWqDJ+6?0E9AxXDD@vBt|y3V!i9@h@u_fe+p`wq3KQ2!7Ot=xS0B@Ia6QA;v&8iR z>v)m4ULvkniR)$JdWE=NBd)_9Tz!Iz*H_x=xK>u+dXwe6#W3#>*SnRtBrjfvr^j`& zgX?53t`DexjJUWZ@P;jmy|ftlpO&d`ol?Ses)_3~3)d<)uG5*8gNw%!@7=Y$FW2Ks z;`)lXz9p`&iR&BU`i{81_ux8RaPgi_TOHTx3S2+1oF5tHC*u0K5|`w~d;j#f);PG< xcyawg{a=aeH{$xe43~n7xSv_aP8a{md0HzQ;Cp;fOcr%!=O46t*;j*0{sT~LSPuXI literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/parser/CommandType.class b/src/main/java/seedu/parser/CommandType.class new file mode 100644 index 0000000000000000000000000000000000000000..c84fdcc3f5b0de8c4caefc9a643b102574eefbf7 GIT binary patch literal 973 zcmaJux1V&r#;U0?ZMC)WQ)CS*Y?}B zPkkrH5PV-R9XA-%Vzp8`u9^(WVWDi6-co4$q+r%d7Q=%N_mxo2Y;Wug8P*fYdlThi zukA2|P1koS<8IR#)a<555mi*Eeq_ib%v1Z!&U&`r$y%d<>vwX=d&%>z?~e8vmi}|H zoIGI&S#HO-N8shughl0WX|@8;U4Zs}HUJZL$GE>|6y>STtiHn7Cs zY}vprUNWrQ)pi4MyfW|*8wTbPHL$=a<3r z>h<*1i=I6k=BCoFyZCR_+`%plOoXN`c(BT40EDDOAc+x3dVt6pzZhl82w?@QpqV1? z5g}jt1neuMO9VcXN7F)95qms8j`iz&NksLioce~~CFI-r67LEmQGWvg`T#YRj$c6e za;x|zMI>xNBPm-~Bz+ReSM3MnMpO-4Ks!fBIJzvH8Q~Z~;mitWP7zL6{Yi%c6B?O@ mJi(0B2u?6-HIxa$);ZXX0-boNao8g^37hmU;W4%aKKTnWBFN(a literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/parser/ContactDetails.class b/src/main/java/seedu/parser/ContactDetails.class new file mode 100644 index 0000000000000000000000000000000000000000..6d54ab1eac977215b85858bc6b25ae732dbfc9c6 GIT binary patch literal 1249 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 literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/parser/EditContactParser.class b/src/main/java/seedu/parser/EditContactParser.class new file mode 100644 index 0000000000000000000000000000000000000000..93c07d3eb013e3205b0a6e702a9224417e4652e6 GIT binary patch literal 1979 zcmb7F+fo}x5IrMlHDVD6M7WvQA&$V}BIFRqb}WJoLb6E^b}YcLotKezN?x?uRqd`w z{GN|U`6X3;@oO$sxXP*E_f+{$`~@lJ(z_BMkVsV?G`rJ#`poH`?$#fFzd8VL4d18; zVlIMtj+BZ%EO4Y%D46R(43{}RRuREmoUorpaMeRx=E%S>89>3 zGX#?}I}D+$r4c^1p__8EQ7cJ%%L5ZbUD%E!T33|aHR%f7a2PHnJ5Qf^+-W04MRKeb zMBV4(_?$t_eOH!sUlYeN$4!n~94j2F99fPvjvPmxA+l69S|Zh=)v(JluX~b4a+>b8 z6y5XG*$ZAOq8Py_1vklX&XH1UqsizvRt218&n|KURQT$P$`c5z9cb;`H8 z>q@(e$J7}fxf*pvTfmA_H*}XF*`-U?yS0gm`zU&~!Wc$tqU!ZqS-1}o#e~cu)AKHU!aWot1jxaStI*F!Z zrc-&F<%Hwb)4J>eZ_mcv(ylDKnf5HUD6+yZin=Q^9FG~MI^yf5je7aNarlsid5{Kt z0OJ@$9MshQE-*0W4H|k6l8xpVtz)!1PftcqW%ec5&-B8`5eWOnep=6Ag2+7R8-&OX z?9Rml;eCV(^9SMQ==}}K!g@_zEfz@7+gqGj*V};RnLM zqwhv2bX6HvQU}j5G&>$j4J(WL=>J|}FaCKu9{Pz+^8x`D5v6s6{=P=hPnHq9k6C$r$ze1tqM(X3120cIfRS;0IZKuF~sMmWw7y~6}O{z4C}>`x-N;1jAuGD%sxNF)hN zVVZ~(IwpCPp(}nWfWdfd9|O<8LoW~t{tE78tEuiVTi%HZ0?}Jky(Gl@JWG;5DPY*f RL+p^CMcPMb{|WuB{0ruO9((`* literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/parser/FailedCommandType.class b/src/main/java/seedu/parser/FailedCommandType.class new file mode 100644 index 0000000000000000000000000000000000000000..88d553ca1284b3d0d1db67d23a2c2c44f19140ae GIT binary patch literal 2072 zcma)+eN!4&6vm$glna8a@727hF=<4bP>seU7~={HZURfof(cCjEt2mr!q!bLtoZ%9Lr9ZjeOcE zn@OvnK|dEWl1U8%=R%HY`L9x= zi>9Mt^6C4}rTeH-Z&zCyrlzAGknT(DZ&x)$GPOq4ZtrbYn}y0|og#jjC-+>#!gOZ0 za#V@cD~+9)bJ(mkcH+?w*vN9NQ9E4GF#I3mt>}h^fK%IPR1VusTFyJo5w*NkKN&TD zW>K@z-dld(iYs&}gU)`txm8Wkb)|LRxwbdCju0$xha63ZQyyDaxu;w;N7_gPk09;_$&zA8v#eu*uE5)VbLkqo zw(9#0Drs;!dZsP8&E4wOA(g#&w!?{frPYd`Njp8V^RvcR=jhF!r@yh`)lseuAX0fk zs!&Kp3aL&Zl`5oag;cPRY8F!2LaJOy#S5u^A+ zzd+{~8e|l$fhaw&npim^0O=*A8COPrduke-n{odD5FA)$E^oi*a z6Y3HZ7Sr1;CL%`ni|G^7ufz<98Pt#ShQtk@B#wytNI%XT6*r~_WZVUD7xkdHOX4o; zJ>tg2P3R$Ulj5%EVR2L9uIjzwu8I3tkBGZ2Zd%vHMa9kNed1=teWLe^yCLqTJ|He8 z?o)kG+?+o28+FL*(%(VJ=c30cb-4&TrEV7yr{s6h=aiI-0jH!>Xox_u5dsBA2>}-u z2z2iH(C1>7(C^{~VZcR3%m6D1^oCEN}Hf7;lc6AZ{RWIc<|&OYnQHY literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/parser/IndexParser.class b/src/main/java/seedu/parser/IndexParser.class new file mode 100644 index 0000000000000000000000000000000000000000..40957f03e51da258cdfb4647b66937170ac912db GIT binary patch literal 1856 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 literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/parser/SearchContactParser.class b/src/main/java/seedu/parser/SearchContactParser.class new file mode 100644 index 0000000000000000000000000000000000000000..b361400cee7170575d146db79c94598a50c54f09 GIT binary patch literal 1546 zcmZ`(QF9tq6#gzOEG(Nq5*yRT##B=ZNhnFIR&9(yk|-9^cF1(b`m}*NWGmTac9+^d z`9J!i-910NV%Zlt;WP{&6GvMA`dY2aggqT^E?w*+RE zEZ>)2V7rdLWBb-&SGEPj1A*kG?byMVK)g`AFQ8T3wiL+LZAb3+j}N7HpqvGAJ@}+F|%V9xY`J9J|w=t(<%f#o{CP9lPD)_=g6*~gO=$;%RFE?!8XVDd} z6D2#X$;2+UP3+-I6JOzqj+%+Daoa>44HFkIOMD~hDnn^@JUMnZT{P-%GD*`BXLS_YeKB(^Qw##wN|OMQTo4 zK0a`pf$OPWh{|h4y-<$GIC#>dN!zb9cG(j3H@R?lQp14ZkkmLGBi5^34wk@dTl%&q z+ow{p-7!qJ=oS%S#TDfv0<3GUfzTrYBWnNOikmtP|GD_;nSYcf1ExX$Ap z#6s6&#Q6m_RtAVqYl#684fPryAek%ug!$E1iJy`A1Nt{Fk@|C0+ZZ5C`}39OycG-M zUSecm0vSvaLKX|iAy0^Fgm#&hG-CfCuVW#Nce&LFK<96fl|&$ZAOww;t+Sa+XAr#x zB2Ex-Z2)6`ximoL*$bEhOgv+R2+#uKgGEjd${cepFjpS$VIA-DZ!sT&$_zpMO|%MD zl9zQl2|5kgIXYoy{f$^&VDc%Zi0?;5QkEp;6iFj;W~mLZLULBATZyEXxvq_fxkzGW v&JdHr(y5R)h(>*;rl$s&ehOXt1zP+!Oe#^MT8E-4q7#Uj+e-SYp*jB_=}cKl literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/storage/ContactsDecoder.class b/src/main/java/seedu/storage/ContactsDecoder.class new file mode 100644 index 0000000000000000000000000000000000000000..ecbc933d2ea402c74c8a7a42333d2579ad6de479 GIT binary patch literal 4452 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 D*1BXq literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/storage/ContactsEncoder.class b/src/main/java/seedu/storage/ContactsEncoder.class new file mode 100644 index 0000000000000000000000000000000000000000..49281443c32472c6d931a438250d172bff3b9a93 GIT binary patch literal 1937 zcmb_d%TgOh6g`a|BZhH!2|Ez;2$n%Fkevh@gX6@=U@H;AiHHetvKXW;JZ6|t%?#Mi zDvNwX*4cP#Z=lMqO7{7Pd`PMi=d?!1U}RSof$H0@+h@+X_jc=#e_s3s;3|I5Fr{M% z(;Ct`BFN}SBCAF@W%3$kG|cMg#G$vLZ3p*cTu6Asq)y)s@Z6P>dTL7vJqIW;|mz-3oUO> zFa2levgHSa*Kk9_XZ(nCY827tm`lHn(P{1idezzbvJthXK_wopcxR$EhvZ$&kCfcc0M;Si3OGnX)pg%2ZGi=v#8#zz;mLu_}WHZr$&VV=aNZ z2EM}A0;4CTyrGxJU#E9%>!DORKeiNRTwu6k%2i$%tPXipwGexxV#B^>yFUA#Z5gN& zRqIF2SdAp#&$Sk%n?cE`%f|vE=~Ct`32kSlcCz*aGy+x3U6s;wrc>Ix>2TW$9_(!$ zF>!We-EzX&y0qoCXYR5*=(qmJ3Yb-a1SiY8re*7>Vx1K%^6h_J;M}gcqsp*m1{;Lt z$PY{>U~T`@Att9;{a-5`1Z((46~LxI>UDxGXW!jX<*cr8$a{si-1VMlxX+iO?7BO9 z4azJzj`WJQ>HCsmemO3tg%Q@;9n-1X(ocm47vHJp#KH9^4cWo{{xO8G8W)diYe5uE z+pe;-_{4oLaPgGBPTT~>-tEU%HOW_4{Y4?vO{aaIvr+bfeJp#3uIC)^HqgeKiw5lo zK0sH~wZZo~#=Ys6h-~H#5v^qN2Z$|1XNIE(h|e5AdkUlS65X4J(0_m4gc#u$5(H47 zlN?d*u zIK%cHTQ6H5TR+>t3&sbl`DgSAvogTs0U5H(GK4wu%M&5RwJ!4dmc35Td-x6;4EQ|f K3C^#vE&K~{K;td| literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/storage/Storage.class b/src/main/java/seedu/storage/Storage.class new file mode 100644 index 0000000000000000000000000000000000000000..3ec5ad437cfacbd331136be46879e8d05cd56980 GIT binary patch literal 2577 zcma)8SyS6q6#lL;78VMmCO{x84M_;tPMoIMTCxC%X%-U*W(nyk>>Cgmn@S>(_PIZx zGkt+Ske56pGlei^rhV^^>h!y^YVftE9eD%HM1FL4zsKm@5@sGv|(21vzfI3j(psqWQ{9 z70lv%D(l)-aehFcevg*o43dnsi*V=uVr3Rau8QfyiyE zXt{Rwe0b*%y?m+Xp=fdZBd6qV;MaGjvaI#u$ap=4kMKN`5E{NGa27s}ErrtL^OHI&aENYc1> zV8B+89o*628d$|E18Z0}@ESh}H1F>`KUV@LKaT3y+@j360wU=(3!AOEN>i&Qj7ZgJ zY?u@C(xrD<^roNISgasP{$NLzm-3daWOKGOUHMe5mFv}5j%d|NP0Dq5%3}LfBn|*n z3Zv3-IM#Gtki~g*&9I>#vwJE^dwQ`V+_@ii(3F)+!(dGLfGcpv2OQi>hbQ>>R&L3a z3I!%Hi2s3fO{+lgF_ozOQ^~=o9$e*iYI4k1@{m@tN>QrM*MO>3lR|jN$i)LdkATG) zi>=8*uCy$N)wL1SpuO)%kNkF=<@XBE5L5HVT}+Lew{qgVl|$#PoI7vj=y7esC7ugh z=01cJBHUlWXQWrjd5JJ;xn7NbfQToy5Q^`jW;XEw;Vsn0lUs;*jHJiV;+M8i7jNTP z^gXo%J}2!#9cc?KwIYhs{Oq;y%ht|l&T#xY=&O^SIeDbY=Pz7CTyMmGhqeuU6Ak5E z{Wgr5^7h0A4DKR3XsCJn21aHVCucw4lfS}m=@q%YVqQ7lI3%^0Q z<}EeLu2nKYfXZ|&LhXZs2fU0(4?)>Bb~t`Jon-ZBh=8f LFVMRlu6zFi4Wn-W literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/ui/ExceptionTextUi.class b/src/main/java/seedu/ui/ExceptionTextUi.class new file mode 100644 index 0000000000000000000000000000000000000000..2451d9b9bf486b724fbaa35c1fe707bad4eff29b GIT binary patch literal 11439 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 literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 82e6a61e7d..83e2e5c8d8 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -4,7 +4,7 @@ import seedu.contact.ContactList; import java.util.ArrayList; -public abstract class TextUi { +public class TextUi { private static final String LOGO = "\n _____ _______ _ \n" + " / ____| |__ __| | | \n" + " | | ___ _ __ | | ___ ___| |__ \n" + " | | / _ \\| '_ \\| |/ _ \\/ __| '_ \\ \n" + " | |___| (_) | | | | | __/ (__| | | |\n" diff --git a/src/main/java/seedu/ui/UserInputTextUi.class b/src/main/java/seedu/ui/UserInputTextUi.class new file mode 100644 index 0000000000000000000000000000000000000000..2bb7a6ba35c51eb5521d67c2d58091263b4689f8 GIT binary patch literal 993 zcmZ`&T~8B16g|@xwq2G2ZK+s5p(3^gS-(*sz7$Q2MIQ`%){gi`Zij(v+x5P2i(!0QDj7Ush?mL- z42i1S6bw@}sl>~$(-7VsZ?wr`wM4M*3-7t=h5}&)Xp{ATJMVXS zH;OWFlV}HlRaYHKufqfBDu(2?(;g6;bvN`J@l0x(+>m2W90&VyL+5N^1{n)en6|Ki zyagM12DWbD7H%`Z!X4Z-aL>YhJYbmlPp5%R3lH%~13hM#^Mz=Jb|~$0Yz)&;Y$WPc z<48Cpb;Q)yN!cq(PM3%ZM$$WEaabNA3~uVu~mLU{qRJ$%^ix| zxzO*z_>qfY$^VIYdhCdSvGc05wt4c3Vc{?I$lE{w literal 0 HcmV?d00001 diff --git a/src/main/java/seedu/ui/ViewMessageFormatterUi.class b/src/main/java/seedu/ui/ViewMessageFormatterUi.class new file mode 100644 index 0000000000000000000000000000000000000000..52116661c0cbab68a1230d927e86be5803d6b448 GIT binary patch literal 2473 zcmaJ@ZBr9h6n<_9NnBQe2!h3zXb}S{(bl(ur~wj;Cb5-(udQ8@+qjbK(#;0Pf704M(x0;U;dy za9fS(I43en%Elpl=}sIWU%DH|fG_3a2rFp0G{R8Wb2QZWNa3c0c<(o6F=^ z*Hx^Dz~O15(U6X7GPhN;VQkf8h3P&Kh}^Vx1>{2 z&H|&mrhHX2>N0CPb;EU~BXBO6Z%A2brpmVE8f7=dt*dcyHviJtHBvRhs;1Um$F!=8 z+`~HOwhP8ii}A2xTr=Gl&8+}uTv;=9!>k32+fAn|v!*(rsZHiskd1~>?VizwIj>Ga$9Y_c z;)#x@cqRZHU#oFs*|yz=>lix)>AtWljo}EsiQ&19Z^1QNcosuhM@5ZN$9HP1>Ug0> zQ^!SI(($>1s|v0txTfH;f;pTMnC#v|x?KPn$FX^NC;h8ynyLPYNAXg}Hfl_>OLBkf zr7XJw<9+X4AX=5KDiVRQWZ%;}KnMTMHPm4VOlZEkkVqt|UNOv$s7-eln%1tpEn9u%pHG%eXFIQ>XtJU6w!Pil;f`~bB^@t}B*PEELu+yPWp~H0 zDmB@d_7^Vpo^8PL!NSt(9ofhIX~5qvm=7L=7R8EDtF4=^T#RB@;7rf{`sF5Y;{W|{ ziVyWszIid?Cz#^XdyHBL$ElwP=qITs0{SWHrvv(@)Taab8R|0u{VerlK%X6%R2|1y z2N;vxPMoK9oFf|^gLCg8-ck@q5hI>4N@q4PW#xLEqjDXddxy|ph{Ol>l(a`v$Xj%X zf3bj3L=lIEF?>dC074@RUx60OQj2AbYr`Fu@ID5CkEtd}b(B<7K`K5TeW)TGs>nW9 z^-!IpF+r-+K`OpTeW+p`s@OhL@1dF@)mc)_2C4YM^`X)_RN6jI$i@1*xv%ix$<7yrU5BV{__fBLDC3koV5N`3BMOPY4hEiZNB6eyO$VQ$gu+#-?M<0sVC^RLffi`YaZr2yys!zU+V=6q5uE@ literal 0 HcmV?d00001 From 9bd4fe03e09594eb8b45f64bd8086c26fecc1878 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Mon, 1 Nov 2021 21:56:28 +0800 Subject: [PATCH 594/756] Rename main class and package --- .../{duke/Duke.java => contech/ConTech.java} | 2 +- src/main/java/seedu/duke/Duke.class | Bin 1234 -> 0 bytes .../DukeTest.java => contech/ConTechTest.java} | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename src/main/java/seedu/{duke/Duke.java => contech/ConTech.java} (99%) delete mode 100644 src/main/java/seedu/duke/Duke.class rename src/test/java/seedu/{duke/DukeTest.java => contech/ConTechTest.java} (89%) diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/contech/ConTech.java similarity index 99% rename from src/main/java/seedu/duke/Duke.java rename to src/main/java/seedu/contech/ConTech.java index 4515653cd5..c5f80c4fe5 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/contech/ConTech.java @@ -1,6 +1,6 @@ //@@author marcusbory -package seedu.duke; +package seedu.contech; import seedu.command.Command; import seedu.contact.Contact; diff --git a/src/main/java/seedu/duke/Duke.class b/src/main/java/seedu/duke/Duke.class deleted file mode 100644 index db6bd33b650dae70e17766b13dca23169359d65c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1234 zcmaJ=>rN9v6#k}Mwp~|><&J_20+x%c;03jKqlQ3I)TBgWByNUwgoW*H)14(Y>4W$h z@&gh~d;lNHc&1xz8yaV_XU=}-GUqnGeqa6su!apC*D)N&NCKl6OA$7qV-mOHFf~jm za9W3kJBrMtz%Zd-gU=w(nU+#ha9t~+rnyd5wx!pUZ_C`b?IoK;`!;cQP1le%FpmX>{te%k zfvoWIj*v%wF-Z1eF^(kz_pq$NGH@R&45_^%E=?yetCWiA@sfDSaHF1WC>__z7r5t% zih)%;P2=kEs1y z+$*{wn28KCR|9H6+6;HAWzj*s^+iOz&a`IPaFOM%n|GwhXn4&qdnLb4u`x{kUk_6- z=;f;wqgPFDjcC7m{&X@rdloLhz7s=}Otd!wkw6Lq#4FX$=%Nj*ree7>bS++@8#qS~ z@u^-qe?a?qhWG^%I|MDAL%+nex<=FQIC%zi@{^?9j}h`eO*gDykg!3L#V~~DbsdHb UUSb_%7^nX}lH8<7Zq@1RAL&atpa1{> diff --git a/src/test/java/seedu/duke/DukeTest.java b/src/test/java/seedu/contech/ConTechTest.java similarity index 89% rename from src/test/java/seedu/duke/DukeTest.java rename to src/test/java/seedu/contech/ConTechTest.java index 2dda5fd651..6f92ce327b 100644 --- a/src/test/java/seedu/duke/DukeTest.java +++ b/src/test/java/seedu/contech/ConTechTest.java @@ -1,4 +1,4 @@ -package seedu.duke; +package seedu.contech; import static org.junit.jupiter.api.Assertions.assertTrue; From 78ce0646b9b664c00fe41bc8e8fbd133f0340fa0 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Mon, 1 Nov 2021 21:57:13 +0800 Subject: [PATCH 595/756] Rename class to ConTech --- src/main/java/seedu/contech/ConTech.java | 6 +++--- src/test/java/seedu/contech/ConTechTest.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/seedu/contech/ConTech.java b/src/main/java/seedu/contech/ConTech.java index c5f80c4fe5..b3ea068ffb 100644 --- a/src/main/java/seedu/contech/ConTech.java +++ b/src/main/java/seedu/contech/ConTech.java @@ -13,7 +13,7 @@ import seedu.ui.ExceptionTextUi; import seedu.ui.UserInputTextUi; -public class Duke { +public class ConTech { private final ContactsDecoder contactsDecoder; private final ContactsEncoder contactsEncoder; private String contactFilePath; @@ -23,7 +23,7 @@ public class Duke { private String personalContactFilePath; private Contact personalContact; - public Duke(String contactFilePath, String personalContactFilePath) { + public ConTech(String contactFilePath, String personalContactFilePath) { this.contactFilePath = contactFilePath; this.personalContactFilePath = personalContactFilePath; this.parser = new MainParser(); @@ -43,7 +43,7 @@ public Duke(String contactFilePath, String personalContactFilePath) { * Main entry-point for the java.duke.Duke application. */ public static void main(String[] args) { - new Duke("data/contacts.txt", + new ConTech("data/contacts.txt", "data/me.txt").runConTech(); } diff --git a/src/test/java/seedu/contech/ConTechTest.java b/src/test/java/seedu/contech/ConTechTest.java index 6f92ce327b..b6fbb10814 100644 --- a/src/test/java/seedu/contech/ConTechTest.java +++ b/src/test/java/seedu/contech/ConTechTest.java @@ -4,7 +4,7 @@ import org.junit.jupiter.api.Test; -class DukeTest { +class ConTechTest { @Test public void sampleTest() { assertTrue(true); From 311689504471d4ea99cf8d22d26532ddd7c10daa Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Mon, 1 Nov 2021 21:57:34 +0800 Subject: [PATCH 596/756] Update IO test script --- src/main/java/META-INF/MANIFEST.MF | 2 +- text-ui-test/runtest.bat | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/META-INF/MANIFEST.MF b/src/main/java/META-INF/MANIFEST.MF index 19e86fe56e..4371ed4c3a 100644 --- a/src/main/java/META-INF/MANIFEST.MF +++ b/src/main/java/META-INF/MANIFEST.MF @@ -1,3 +1,3 @@ Manifest-Version: 1.0 -Main-Class: seedu.duke.Duke +Main-Class: seedu.contech.ConTech diff --git a/text-ui-test/runtest.bat b/text-ui-test/runtest.bat index 902b146db1..4c25fe4881 100644 --- a/text-ui-test/runtest.bat +++ b/text-ui-test/runtest.bat @@ -12,14 +12,14 @@ for /f "tokens=*" %%a in ( set jarloc=%%a ) -xcopy duke.jar ..\..\text-ui-test +xcopy ConTech.jar ..\..\text-ui-test cd ..\..\text-ui-test -java -jar duke.jar < input.txt > ACTUAL.TXT +java -jar ConTech.jar < input.txt > ACTUAL.TXT FC ACTUAL.TXT EXPECTED.TXT >NUL && ECHO Test passed! || Echo Test failed! del data\contacts.txt del data\me.txt -del duke.jar \ No newline at end of file +del ConTech.jar \ No newline at end of file From b580226d2d2e53ef31d044867a145dc9ff3fce5b Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Mon, 1 Nov 2021 21:57:45 +0800 Subject: [PATCH 597/756] Update gradle script --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index c358356036..90eb11d920 100644 --- a/build.gradle +++ b/build.gradle @@ -44,11 +44,11 @@ test { } application { - mainClassName = "seedu.duke.Duke" + mainClassName = "seedu.contech.ConTech" } shadowJar { - archiveBaseName = "duke" + archiveBaseName = "ConTech" archiveClassifier = null } From aa753fbc56075aa8c71667fc62ec8aa613bfa1fa Mon Sep 17 00:00:00 2001 From: lezong Date: Tue, 2 Nov 2021 15:29:53 +0800 Subject: [PATCH 598/756] Refactor exception handling in edit, view and rm --- .../java/seedu/command/DeleteContactCommand.java | 7 +++++-- .../java/seedu/command/EditContactCommand.java | 9 ++++++--- src/main/java/seedu/command/FailedCommand.java | 4 ++++ .../java/seedu/command/ViewContactCommand.java | 14 +++++++++++--- .../java/seedu/parser/FailedCommandType.java | 2 +- src/main/java/seedu/parser/IndexParser.java | 4 ++-- src/main/java/seedu/parser/MainParser.java | 16 ++++++++++------ src/main/java/seedu/ui/ExceptionTextUi.java | 11 +++++++++++ 8 files changed, 50 insertions(+), 17 deletions(-) diff --git a/src/main/java/seedu/command/DeleteContactCommand.java b/src/main/java/seedu/command/DeleteContactCommand.java index 41ce06bc99..67d49f8703 100644 --- a/src/main/java/seedu/command/DeleteContactCommand.java +++ b/src/main/java/seedu/command/DeleteContactCommand.java @@ -10,7 +10,8 @@ public class DeleteContactCommand extends Command { private static final String ACKNOWLEDGE_DELETE = "y"; - private static final int DELETE_ALL_CONTACTS = -2; + private static final int PERSONAL_CONTACT_INDEX = -1; + private static final int DELETE_ALL_CONTACTS_INDEX = -2; private final int contactIndex; private final boolean[] hasDeletedDetails; @@ -78,8 +79,10 @@ private void deleteFields() { public void execute() { try { - if (contactIndex == DELETE_ALL_CONTACTS) { + if (contactIndex == DELETE_ALL_CONTACTS_INDEX) { deleteAllContacts(); + } else if (contactIndex == PERSONAL_CONTACT_INDEX) { + ExceptionTextUi.missingIndexMessage(); } else if (hasDeletedDetails[6]) { //delete entire contact deleteSelectedContact(); } else { diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index 37cb254eb1..c3163e3d12 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -12,6 +12,7 @@ public class EditContactCommand extends Command { public static final int PERSONAL_CONTACT_INDEX = -1; + private static final int ALL_CONTACTS_INDEX = -2; public static final int NUMBER_OF_FIELDS = 6; public static final String EDIT_TYPE = "edit"; String[] contactDetails; @@ -26,23 +27,25 @@ public void execute() { try { if (contactIndex == PERSONAL_CONTACT_INDEX) { updatePersonalContact(); + } else if (contactIndex == ALL_CONTACTS_INDEX) { + ExceptionTextUi.missingIndexEditMessage(); } else { Contact editedContact = duplicateContact(contactList.getContactAtIndex(contactIndex)); editedContact.editContact(contactDetails); handleDuplicates(editedContact); } - } catch (IndexOutOfBoundsException | InvalidFlagException e) { + } catch (IndexOutOfBoundsException e) { //triggerred when inputs are "edit " ExceptionTextUi.numOutOfRangeEditMessage(contactList.getListSize()); } } - private void updatePersonalContact() throws InvalidFlagException { + private void updatePersonalContact() { personalContact.editContact(contactDetails); TextUi.editPersonalContactMessage(personalContact); } - private void handleDuplicates(Contact postEditContact) throws IndexOutOfBoundsException, InvalidFlagException { + private void handleDuplicates(Contact postEditContact) throws IndexOutOfBoundsException { if (hasDuplicates(postEditContact, contactList, contactIndex)) { TextUi.ignoreContact(EDIT_TYPE); } else { diff --git a/src/main/java/seedu/command/FailedCommand.java b/src/main/java/seedu/command/FailedCommand.java index fc9f818747..b5f6fcde2c 100644 --- a/src/main/java/seedu/command/FailedCommand.java +++ b/src/main/java/seedu/command/FailedCommand.java @@ -37,6 +37,7 @@ public void execute() { case MISSING_DETAIL: // Fallthrough case MISSING_NAME: // Fallthrough case MISSING_INDEX: // Fallthrough + case INVALID_INDEX_EDIT: missingUserInputExecute(); break; default: @@ -95,6 +96,9 @@ private void missingUserInputExecute() { case MISSING_INDEX: ExceptionTextUi.missingIndexMessage(); break; + case INVALID_INDEX_EDIT: + ExceptionTextUi.missingIndexEditMessage(); + break; default: return; } diff --git a/src/main/java/seedu/command/ViewContactCommand.java b/src/main/java/seedu/command/ViewContactCommand.java index 9504607fff..2ca1ab9ccc 100644 --- a/src/main/java/seedu/command/ViewContactCommand.java +++ b/src/main/java/seedu/command/ViewContactCommand.java @@ -8,6 +8,8 @@ public class ViewContactCommand extends Command { private final int contactIndex; + private static final int PERSONAL_CONTACT_INDEX = -1; + private static final int ALL_CONTACTS_INDEX = -2; public ViewContactCommand(int contactIndex) { this.contactIndex = contactIndex; @@ -19,9 +21,15 @@ public int getIndex() { public void execute() { try { - Contact viewingContact = contactList.getContactAtIndex(contactIndex); - assert contactIndex >= 0 && contactIndex < contactList.getListSize(); - TextUi.viewContactMessage(viewingContact, contactIndex); + if (contactIndex == PERSONAL_CONTACT_INDEX) { + TextUi.viewPersonalContactMessage(this.personalContact); + } else if (contactIndex == ALL_CONTACTS_INDEX) { + ExceptionTextUi.missingIndexMessage(); + } else { + Contact viewingContact = contactList.getContactAtIndex(contactIndex); + assert contactIndex >= 0 && contactIndex < contactList.getListSize(); + TextUi.viewContactMessage(viewingContact, contactIndex); + } } catch (IndexOutOfBoundsException e) { ExceptionTextUi.numOutOfRangeMessage(contactList.getListSize()); } diff --git a/src/main/java/seedu/parser/FailedCommandType.java b/src/main/java/seedu/parser/FailedCommandType.java index 91c045d20f..25578de407 100644 --- a/src/main/java/seedu/parser/FailedCommandType.java +++ b/src/main/java/seedu/parser/FailedCommandType.java @@ -2,7 +2,7 @@ public enum FailedCommandType { GENERAL, INVALID_FLAG, MISSING_ARGS_EDIT, MISSING_ARGS_ADD, MISSING_ARGS_SEARCH, - MISSING_DETAIL, MISSING_INDEX, INVALID_NUM, + MISSING_DETAIL, MISSING_INDEX, INVALID_NUM, INVALID_INDEX_EDIT, INVALID_FORMAT, NUM_OUT_OF_BOUND, NUM_OUT_OF_BOUND_EDIT, INVALID_INDEX, MISSING_NAME, FORBIDDEN_DETAIL, INVALID_NAME, INVALID_GITHUB_USERNAME, INVALID_LINKEDIN, INVALID_TELEGRAM, INVALID_MAIL, INVALID_TWITTER, INVALID_DELETE, diff --git a/src/main/java/seedu/parser/IndexParser.java b/src/main/java/seedu/parser/IndexParser.java index 2aae3ecb48..8aaf6236dc 100644 --- a/src/main/java/seedu/parser/IndexParser.java +++ b/src/main/java/seedu/parser/IndexParser.java @@ -37,12 +37,12 @@ public static int getIndexFromInput(String userInput) return REMOVE_ALL_ID; } if (!significantIndex.matches(numbers)) { - throw new MissingIndexException(); + throw new NumberFormatException(); } // takes only the first word/ element as given user input, and throws NumberFormatExcept if it is not integer int index = Integer.parseInt(significantIndex); if (index < 0) { - throw new NumberFormatException(); + throw new IndexOutOfBoundsException(); } return index; } diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index ba05858e1d..30ef7f18cd 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -29,6 +29,8 @@ import seedu.exception.MissingDetailException; import seedu.exception.MissingIndexException; +import java.lang.reflect.Array; + import static seedu.parser.ContactParser.NUMBER_OF_FIELDS; public class MainParser { @@ -193,9 +195,11 @@ private Command parseEditContact(String userInput) { // userInput is raw user in return new EditContactCommand(details, userIndex); } catch (InvalidFlagException e) { return new FailedCommand(FailedCommandType.INVALID_FLAG); - } catch (MissingDetailException | MissingIndexException | MissingArgEditException e) { - return new FailedCommand(FailedCommandType.MISSING_ARGS_EDIT); } catch (NumberFormatException e) { + return new FailedCommand(FailedCommandType.INVALID_INDEX_EDIT); + } catch (MissingIndexException | MissingDetailException | MissingArgEditException e) { + return new FailedCommand(FailedCommandType.MISSING_ARGS_EDIT); + } catch (IndexOutOfBoundsException e) { return new FailedCommand(FailedCommandType.NUM_OUT_OF_BOUND_EDIT); } catch (DuplicateDetailException e) { return new FailedCommand(FailedCommandType.DUPLICATE_DETAIL); @@ -238,9 +242,9 @@ private Command parseViewContact(String userInput) { try { int viewedIndex = IndexParser.getIndexFromInput(userInput); return new ViewContactCommand(viewedIndex); - } catch (NumberFormatException e) { + } catch (IndexOutOfBoundsException e) { return new FailedCommand(FailedCommandType.NUM_OUT_OF_BOUND); - } catch (MissingIndexException e) { + } catch (MissingIndexException | NumberFormatException e) { return new FailedCommand(FailedCommandType.MISSING_INDEX); } } @@ -251,9 +255,9 @@ private Command parseDeleteContact(String userInput) { int deletedIndex = IndexParser.getIndexFromInput(userInput); boolean[] hasDeletedDetail = deleteContactParser.hasDeletedDetail(userInput); return new DeleteContactCommand(deletedIndex, hasDeletedDetail); - } catch (NumberFormatException | IndexOutOfBoundsException e) { + } catch (IndexOutOfBoundsException e) { return new FailedCommand(FailedCommandType.NUM_OUT_OF_BOUND); - } catch (MissingIndexException e) { + } catch (MissingIndexException | NumberFormatException e) { return new FailedCommand(FailedCommandType.MISSING_INDEX); } catch (InvalidFlagException e) { return new FailedCommand(FailedCommandType.INVALID_FLAG); diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index fcab737b86..b0073b89f9 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -128,6 +128,17 @@ public static void missingDetailMessage() { printDoubleLineMessage(message); } + public static void missingIndexEditMessage() { + String message = "There seems to be missing or invalid index in your request.\n" + + "Please enter command in the following way:\n" + + " edit -n -g -e -te -l -tw \n" + + " example : edit 0 -n George -g procoder -te george123\n" + + "NOTE : At least one flag and description required\n" + + " Order of parameters do not matter except for INDEX\n" + + " \"me\" is used as the INDEX for personal contact."; + printDoubleLineMessage(message); + } + //@@author mayankp291 public static void missingArgEditMessage() { String message = "There seems to be missing parameters in your request.\n" From 46aac4dc43b26e77c8d12403ea29c73defcbfd00 Mon Sep 17 00:00:00 2001 From: lezong Date: Tue, 2 Nov 2021 23:44:44 +0800 Subject: [PATCH 599/756] Update userguide --- docs/UserGuide.md | 95 +++++++++++++++++---- src/main/java/seedu/parser/IndexParser.java | 1 - 2 files changed, 80 insertions(+), 16 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 660907753c..513ca580f3 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -176,12 +176,19 @@ ____________________________________________________________ ### Viewing a contact: `view` Displays all the details saved to a contact in the ConTech Book. -Command format: `view ` +Command formats: + +`view ` + * Displays all the details of the contact at the specified `INDEX`. * The index refers to the index number shown in the displayed contact list. * The index must be within the range of indexes displayed in the contact list _(zero-based)_. * Additional input after the `` in the command will be treated as erroneous input and discarded. +`view me` +* Displays all the details of the personal contact. +* Additional input after the `me` in the command will be treated as erroneous input and discarded. +
@@ -192,6 +199,9 @@ requiring indexes.
Expected outcome of usage: + +* View selected contact: + ``` view 0 ____________________________________________________________ @@ -201,12 +211,23 @@ ____________________________________________________________ Telegram: t.me/alexl33 ____________________________________________________________ ``` +* View personal contact: + +``` +view me +____________________________________________________________ +Name: Marcus Bo +Github: github.com/marcusbohre +Email: marcus.bo@contech.sg +Telegram: t.me/m4rcusb0 +____________________________________________________________ +```
### Viewing personal contact: `me` Displays all your details saved to the personal contact in the ConTech Book. -This refers to the details which you filled in while setting up **ConTech**. +Personal contact details are filled in by user while setting up **ConTech**. Command format: `me` * Displays all the details of the personal contact. @@ -252,6 +273,7 @@ Command formats: * Deletes all contacts in the ConTech Book. Expected outcome of usages: + * Remove selected contact: ``` @@ -306,19 +328,37 @@ ____________________________________________________________ ### Editing a contact : `edit` -Edits the details of a specified contact in the ConTech Book. +Edits the details of a specified contact in the ConTech Book, as well as the personal contact. -Command format: `edit {-n } {-g } {-l } {-te } {-tw } {-e }` +Command formats: +`edit {-n } {-g } {-l } {-te } {-tw } {-e }` + +- Edits the details of a selected contact. - Up to six `flags` and `details` can be specified, in any order. - The index refers to the index number shown in the displayed contact list. -- To edit personal fields, `me` can be specified in the `INDEX` parameter. - The index must be within the range of indexes displayed in the contact list (zero-based). -- ConTech also has built-in duplicate checkers and will alert you if there is already a contact with the same details when editing. +- ConTech also has built-in duplicate checkers and will alert you if there is already a contact with the same details + when editing. +- While all six `details` are optional, minimally **one** must be specified for any effect to take place. +- Additional input between the `edit` command and the first detail flag will be treated as erroneous input and + discarded. + +`edit me {-n } {-g } {-l } {-te } {-tw } {-e }` + +- Edits the details of the personal contact. +- Up to six `flags` and `details` can be specified, in any order. +- ConTech also has built-in duplicate checkers and will alert you if there is already a contact with the same details + when editing. - While all six `details` are optional, minimally **one** must be specified for any effect to take place. -- Additional input between the `edit` command and the first detail flag will be treated as erroneous input and discarded. +- Additional input between the `edit` command and the first detail flag will be treated as erroneous input and + discarded. + Expected outcome of usage: + +- Edit selected contact: + ``` edit 0 -n John Lee -g johnlee -te johnlee123 -e john.lee@contech.sg ____________________________________________________________ @@ -329,6 +369,19 @@ ____________________________________________________________ ____________________________________________________________ ``` +- Edit personal contact: + +``` +edit me -n Marcus Bo -g marcusbory -te boryy -e marcusong@gmail.com +____________________________________________________________ +ConTech has edited your personal contact: +Name: Marcus Bo +Github: github.com/marcusbory +Email: marcusong@gmail.com +Telegram: t.me/boryy +____________________________________________________________ +``` + ### Searching for a contact: `search` @@ -429,17 +482,26 @@ ls: Displays the name of all saved contacts. edit: Edit any parameter in an existing contact. Parameters: INDEX -n NAME -g GITHUB -e EMAIL -te TELEGRAM -l LINKEDIN -tw TWITTER Note: Parameters need not be in order and are optional except for INDEX. - Example: edit 1 -e john.doe@email.com + "me" is used as the INDEX for personal contact. + Examples: edit 1 -e john.doe@email.com + edit me -e john.doe@email.com view: Displays all details for index specified contact. Parameter: INDEX Note: Index starts from 0. + "me" is used as the INDEX to view personal contact details. Example: view 2 + view me + +me: Displays all details for personal contact. + Example: me rm: Deletes the index specified contact. Parameter: INDEX Note: Index starts from 0. - Example: rm 0 + "all" is used as the INDEX to delete all contacts. + Examples: rm 0 + rm all search: Search for a contact containing a specified query. Note: Flags may be used to specify a detail type to search. @@ -497,12 +559,15 @@ a quick view when using the application. Action | Command Format | Example --- | --- | --- | List all valid commands and usage | `help` | `help` -Add a new contact| `add -n {-g } {-e } {-te } {-l } {-tw }` | `add -n Marcus`
`add -n John Doe -g johndoecoder -e john@email.com -te johndoe`
+Add a new contact | `add -n {-g } {-e } {-te } {-l } {-tw }` | `add -n Marcus`
`add -n John Doe -g johndoecoder -e john@email.com -te johndoe`
List all contacts | `ls` | `ls` -View a contact| `view ` | `view 2` -Edit a contact| `edit {-n } {-g } {-e } {-te } {-l } {-tw }` | `edit 1 -e john.doe@email.com`
`edit 0 -n Tan -g tanned -te tantan`
-Delete contact fields| `rm {-g} {-l} {-te} {-tw} {-e}` | `rm 3 -g -te -l -e` +View a contact | `view ` | `view 2` +View personal contact | `view me` | `view me` +Edit a contact | `edit {-n } {-g } {-e } {-te } {-l } {-tw }` | `edit 1 -e john.doe@email.com`
`edit 0 -n Tan -g tanned -te tantan`
+Edit personal contact | `edit me {-n } {-g } {-e } {-te } {-l } {-tw }` |`edit me -e bobby@email.com`
`edit me -n Tan -g tanned -te tantan`
+Delete contact fields | `rm {-g} {-l} {-te} {-tw} {-e}` | `rm 3 -g -te -l -e` +Delete all contacts | `rm all` | `rm all` Delete a contact | `rm ` | `rm 1` -Search for a contact| search {-n | -g | -l | -te | -tw | -e} <QUERY> | `search Ashraf`
`search -g revflash`
-Import contacts from .txt file|`import` | `import` +Search for a contact | search {-n | -g | -l | -te | -tw | -e} <QUERY> | `search Ashraf`
`search -g revflash`
+Import contacts from .txt file |`import` | `import` Exit ConTech | `exit` | `exit` diff --git a/src/main/java/seedu/parser/IndexParser.java b/src/main/java/seedu/parser/IndexParser.java index 8aaf6236dc..b7f523579d 100644 --- a/src/main/java/seedu/parser/IndexParser.java +++ b/src/main/java/seedu/parser/IndexParser.java @@ -15,7 +15,6 @@ public class IndexParser { private static final int REMOVE_ALL_ID = -2; private static final String numbers = "^-?\\d+$"; - //@@author ng-andre public static int getIndexFromInput(String userInput) throws NumberFormatException, MissingIndexException { //split user input into 2 strings: command word string and index string From 382caaca8d1214b0f2691471a9ff27ef16a3280a Mon Sep 17 00:00:00 2001 From: lezong Date: Wed, 3 Nov 2021 00:10:20 +0800 Subject: [PATCH 600/756] Remove class files --- .gitignore | 1 + .../java/seedu/command/AddContactCommand.class | Bin 4052 -> 0 bytes src/main/java/seedu/command/Command.class | Bin 629 -> 0 bytes .../seedu/command/DeleteContactCommand.class | Bin 3189 -> 0 bytes .../java/seedu/command/EditContactCommand.class | Bin 4605 -> 0 bytes src/main/java/seedu/command/ExitCommand.class | Bin 316 -> 0 bytes .../java/seedu/command/FailedCommand$1.class | Bin 1383 -> 0 bytes src/main/java/seedu/command/FailedCommand.class | Bin 1946 -> 0 bytes src/main/java/seedu/command/HelpCommand.class | Bin 316 -> 0 bytes .../seedu/command/ImportContactCommand.class | Bin 1778 -> 0 bytes .../seedu/command/InvalidDetailCommand$1.class | Bin 1021 -> 0 bytes .../seedu/command/InvalidDetailCommand.class | Bin 1178 -> 0 bytes .../seedu/command/ListContactsCommand.class | Bin 1008 -> 0 bytes .../seedu/command/PersonalContactCommand.class | Bin 440 -> 0 bytes .../seedu/command/SearchContactCommand.class | Bin 701 -> 0 bytes .../java/seedu/command/ViewContactCommand.class | Bin 1199 -> 0 bytes src/main/java/seedu/contact/Contact.class | Bin 2292 -> 0 bytes .../java/seedu/contact/ContactComparator.class | Bin 691 -> 0 bytes src/main/java/seedu/contact/ContactList.class | Bin 2358 -> 0 bytes src/main/java/seedu/contact/DetailType.class | Bin 1234 -> 0 bytes src/main/java/seedu/duke/Duke.class | Bin 2404 -> 0 bytes .../seedu/exception/FileErrorException.class | Bin 229 -> 0 bytes .../exception/ForbiddenDetailException.class | Bin 241 -> 0 bytes .../InvalidDeleteDetailException.class | Bin 249 -> 0 bytes .../seedu/exception/InvalidEmailException.class | Bin 235 -> 0 bytes .../seedu/exception/InvalidFlagException.class | Bin 233 -> 0 bytes .../InvalidGithubUsernameException.class | Bin 253 -> 0 bytes .../InvalidLinkedinUsernameException.class | Bin 257 -> 0 bytes .../seedu/exception/InvalidNameException.class | Bin 233 -> 0 bytes .../InvalidTelegramUsernameException.class | Bin 257 -> 0 bytes .../InvalidTwitterUsernameException.class | Bin 255 -> 0 bytes .../exception/MissingArgAddException.class | Bin 237 -> 0 bytes .../exception/MissingArgEditException.class | Bin 239 -> 0 bytes .../exception/MissingArgSearchException.class | Bin 243 -> 0 bytes .../exception/MissingDetailException.class | Bin 237 -> 0 bytes .../seedu/exception/MissingIndexException.class | Bin 235 -> 0 bytes .../java/seedu/parser/AddContactParser.class | Bin 1113 -> 0 bytes .../seedu/parser/AddPersonalContactParser.class | Bin 4706 -> 0 bytes src/main/java/seedu/parser/CommandType.class | Bin 973 -> 0 bytes src/main/java/seedu/parser/ContactDetails.class | Bin 1249 -> 0 bytes src/main/java/seedu/parser/ContactParser.class | Bin 2382 -> 0 bytes .../java/seedu/parser/DeleteContactParser.class | Bin 1836 -> 0 bytes .../java/seedu/parser/EditContactParser.class | Bin 1979 -> 0 bytes .../java/seedu/parser/FailedCommandType.class | Bin 2072 -> 0 bytes src/main/java/seedu/parser/IndexParser.class | Bin 1856 -> 0 bytes src/main/java/seedu/parser/MainParser$1.class | Bin 713 -> 0 bytes src/main/java/seedu/parser/MainParser.class | Bin 8142 -> 0 bytes src/main/java/seedu/parser/RegexParser.class | Bin 3437 -> 0 bytes .../java/seedu/parser/SearchContactParser.class | Bin 1546 -> 0 bytes .../java/seedu/storage/ContactsDecoder.class | Bin 4452 -> 0 bytes .../java/seedu/storage/ContactsEncoder.class | Bin 1937 -> 0 bytes src/main/java/seedu/storage/Storage.class | Bin 2577 -> 0 bytes src/main/java/seedu/ui/ExceptionTextUi.class | Bin 11439 -> 0 bytes src/main/java/seedu/ui/TextUi.class | Bin 12383 -> 0 bytes src/main/java/seedu/ui/UserInputTextUi.class | Bin 993 -> 0 bytes .../java/seedu/ui/ViewMessageFormatterUi.class | Bin 2473 -> 0 bytes 56 files changed, 1 insertion(+) delete mode 100644 src/main/java/seedu/command/AddContactCommand.class delete mode 100644 src/main/java/seedu/command/Command.class delete mode 100644 src/main/java/seedu/command/DeleteContactCommand.class delete mode 100644 src/main/java/seedu/command/EditContactCommand.class delete mode 100644 src/main/java/seedu/command/ExitCommand.class delete mode 100644 src/main/java/seedu/command/FailedCommand$1.class delete mode 100644 src/main/java/seedu/command/FailedCommand.class delete mode 100644 src/main/java/seedu/command/HelpCommand.class delete mode 100644 src/main/java/seedu/command/ImportContactCommand.class delete mode 100644 src/main/java/seedu/command/InvalidDetailCommand$1.class delete mode 100644 src/main/java/seedu/command/InvalidDetailCommand.class delete mode 100644 src/main/java/seedu/command/ListContactsCommand.class delete mode 100644 src/main/java/seedu/command/PersonalContactCommand.class delete mode 100644 src/main/java/seedu/command/SearchContactCommand.class delete mode 100644 src/main/java/seedu/command/ViewContactCommand.class delete mode 100644 src/main/java/seedu/contact/Contact.class delete mode 100644 src/main/java/seedu/contact/ContactComparator.class delete mode 100644 src/main/java/seedu/contact/ContactList.class delete mode 100644 src/main/java/seedu/contact/DetailType.class delete mode 100644 src/main/java/seedu/duke/Duke.class delete mode 100644 src/main/java/seedu/exception/FileErrorException.class delete mode 100644 src/main/java/seedu/exception/ForbiddenDetailException.class delete mode 100644 src/main/java/seedu/exception/InvalidDeleteDetailException.class delete mode 100644 src/main/java/seedu/exception/InvalidEmailException.class delete mode 100644 src/main/java/seedu/exception/InvalidFlagException.class delete mode 100644 src/main/java/seedu/exception/InvalidGithubUsernameException.class delete mode 100644 src/main/java/seedu/exception/InvalidLinkedinUsernameException.class delete mode 100644 src/main/java/seedu/exception/InvalidNameException.class delete mode 100644 src/main/java/seedu/exception/InvalidTelegramUsernameException.class delete mode 100644 src/main/java/seedu/exception/InvalidTwitterUsernameException.class delete mode 100644 src/main/java/seedu/exception/MissingArgAddException.class delete mode 100644 src/main/java/seedu/exception/MissingArgEditException.class delete mode 100644 src/main/java/seedu/exception/MissingArgSearchException.class delete mode 100644 src/main/java/seedu/exception/MissingDetailException.class delete mode 100644 src/main/java/seedu/exception/MissingIndexException.class delete mode 100644 src/main/java/seedu/parser/AddContactParser.class delete mode 100644 src/main/java/seedu/parser/AddPersonalContactParser.class delete mode 100644 src/main/java/seedu/parser/CommandType.class delete mode 100644 src/main/java/seedu/parser/ContactDetails.class delete mode 100644 src/main/java/seedu/parser/ContactParser.class delete mode 100644 src/main/java/seedu/parser/DeleteContactParser.class delete mode 100644 src/main/java/seedu/parser/EditContactParser.class delete mode 100644 src/main/java/seedu/parser/FailedCommandType.class delete mode 100644 src/main/java/seedu/parser/IndexParser.class delete mode 100644 src/main/java/seedu/parser/MainParser$1.class delete mode 100644 src/main/java/seedu/parser/MainParser.class delete mode 100644 src/main/java/seedu/parser/RegexParser.class delete mode 100644 src/main/java/seedu/parser/SearchContactParser.class delete mode 100644 src/main/java/seedu/storage/ContactsDecoder.class delete mode 100644 src/main/java/seedu/storage/ContactsEncoder.class delete mode 100644 src/main/java/seedu/storage/Storage.class delete mode 100644 src/main/java/seedu/ui/ExceptionTextUi.class delete mode 100644 src/main/java/seedu/ui/TextUi.class delete mode 100644 src/main/java/seedu/ui/UserInputTextUi.class delete mode 100644 src/main/java/seedu/ui/ViewMessageFormatterUi.class diff --git a/.gitignore b/.gitignore index d04b9c5c84..03a80ea984 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ bin/ # ensure that no existing contact data exists on remote, so that runtest.sh is always on fresh build /text-ui-test/data/contacts.txt /text-ui-test/data/me.txt +*.class \ No newline at end of file diff --git a/src/main/java/seedu/command/AddContactCommand.class b/src/main/java/seedu/command/AddContactCommand.class deleted file mode 100644 index ec2989565fe8e6b96126a1aba134ee8ce34b62c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4052 zcmb_f`Fj)B6+L4uBgkK+?woWqkMo|54wReZ{er}2!6PkYf0OMIV|$DdJgUIw4_;yHXyo_$`# z7i88Kz4#Ko?7>&OSc|W!xFCC76!A3?Ul;KW5#JQ?EeYb=D!$`IKsIPC>~cvaf7gTW zdGNfb-xo3M#Sid96_*t_Q~HFVz!yHQpVR|MJ(UQIS{XBy*rvdpFs);`BMLl8Gc|6+ z%@kG3NE(TZKA}LhPMMZvWE8lJ3EfO8XpHO|-WA+CHZnLi7z&05MinR_1@-;uRMyf{ z)_y&iGaSr-TY)#yHyj)bMFxToi3JL@p-^=9zFo66MZuzQD6%Iw5Q@xNYiNxI!@;4w zeZ#X>2e*kH2t}jZzPzYYL0xdTFBG0NxfCp3rDwB7#xfbzfSJ{gB#k%&Jw)e(VTH>_ zy`!VE8Y<5IbexDa(9wwGCXN`Hs4P*K9WA5d}F59^b~-RqC(*@4_-(v0brkyWszu%J2qFBT2~Db}T&VLQ5wTQ=heKvOj6)DJi%$Rc2OAmS=m6wQD2m9ZlylF=Nn_ zT($JY zFNt_r#4C7#xK%}8mdIG4X@&cil1qC4X+Gz)QYQv8nRG^jiQ^jng15NG3I)*cSNu)G-w{>u4-NmsI~Bkdj!;Y= zk6yLzT1y8mG(n+!qf?Wt0jDsKg7$e0G3!DKl*SFE;>Kya?Z{>B0!i^niJ7RD=!jif zCuatt?DKslTg^Y5(taByg>VHi9%u}z7oo)d4?Hjnw>XnWV3pLwxze59+D`E>1F)o zW+)wGv03O8JALKlnz&&xw7ybi+dD#?)lp&vG|d)kC}kN5p&ykkm@`I>3SD#R0uN4` z1KY@v;|7^mm`pXZ!HG$0%C0Alm&DSkqh@BJOx@*3gGJ!yHuL|Y?}|W*@9?=0?c-Z7 zl$y+0Wrzrd7zv2PpbO=*sf`mkJ(&#^>Ojvj33Etc&K8$o8wT$ z_=yExsRh|yp#Cg>UtTB9rImR(~0C<#nn0AwUbUH_$sch`K~>5;%lIat9!oddO97(hl{Rf z;UNCNaMyLHUESB<$)k3|D@264x1hU4uPf+^=vqOq5xu^kJ49bp(4AMyNZt((^U<<2(uUzd<0{~aGs~Xgfnsj4F{PNNsL>P!>fjugO~F<8pB=P z)SB|}T|k|0@eJ;mMvGXw^Jp$UYMH^3X{g~Dv|Z)$U`5@}5A_;5#cNPY%Y9hEF#N2= zURL6E*5MF#(`%5`HG~Lj?h$%5!uc+GRW#g!ZC}!xz*{|L^Juw*(Jp_pE01MjcRMzz&1$3j5;nIvo7D|(ptH?w-&c0o278pp z@(XC}X?D$EMII{;Or!Rks!adq&2uiw%RPDAeG$uh{BrbrX0U3jtIg$GoyVGsP@U6o zI<7dbFs8y;cku+wFr$p{ugeIQ;sO3Gc@XQ_5q<22y)2x=Jj)nu2A_|!>M|^+DOw+6 zrJU!JN4Uajc;1IkMZ1ca@*bARt@qz>-Gb{~tWdFbr*eyKab8XWE>QDZs0dRn3(d(V z=NsLxVePPE$1=g-?6S+W>Ad9U;0@XC$&Dmi&_`8 z&3-qvZfZS#m71U0J$?_h9%^mZu zb??C=Fm>13zj~Ee%>jrXfW^{ZLx3C%VNn;0W`h*bhCDtfS*#?bvkaG?ZN)jOiruSq z`+9vF^VpQf=K1~pB=bIAZm?d?lwXtYt~~B7Rm)3QCp}w0qQHLj_6c05(RK<)Chf-) F{{@0Lv)=#! diff --git a/src/main/java/seedu/command/Command.class b/src/main/java/seedu/command/Command.class deleted file mode 100644 index 208c2cc5481211b30b3424a0091a8774e15fa84d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 629 zcmZ`$!A`9Ogti3(+XduN=h86IG_hl%B~bJNKXScjpu$L?IS8d3 z#ZC%3{jAv&DBa6h82Iiag#~KM`NTDjm9L@`fm~<*MnLZeBS{Ve<;(MUI+U|(cQ_$r zEtJu(DFW@za!(G}W2*`&E*FC|{!t|gQ_iIqM>Ne);ptq_k5Z~z0qZJ=XP!J$oW$-2 z)2Zu^4#)0;YoiF;hKUs$1y}<0@5Lk>hh0*>K=p6$2QRaeGjaVp=VCaPUZn5R_6>Rx z4LW<%O=o*L^PsnYO?8#NT679VyDtz=bfHC2H4>0(31zBG-6J!Nd)|VL n={hRQ__;-XiTGt*V1raVbraQ8mqmJq{+KkgNKD!yOhfGpP4Isb diff --git a/src/main/java/seedu/command/DeleteContactCommand.class b/src/main/java/seedu/command/DeleteContactCommand.class deleted file mode 100644 index 5a1d0d5c749dcb104c9e50c60b4f9ad4d1b9d3b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3189 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 diff --git a/src/main/java/seedu/command/ExitCommand.class b/src/main/java/seedu/command/ExitCommand.class deleted file mode 100644 index 2cc00988e604cedfa5f04ad93f13a4e6ecc35aaf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 316 zcmY*UyH3ME5S+CgA2@~t5CsJibU=YinusQX3TO!Q7kh;cVOxrQ$iGDeqTmDgD8!f` z9#_oH&Cbqh-#=d80GwbeL4-8H8rBU)24g`yag}RN1>wQrtst7#g$hO&uF@-C&UG=f z^9L$MJI#GdmR#3nkXQ6Cfb`plhQD1_VI3SjL!L+kE5yD{k+}L} Y-TUeS(F=lKXTm@*D&!o`Bo8qB1V$D+^8f$< diff --git a/src/main/java/seedu/command/FailedCommand$1.class b/src/main/java/seedu/command/FailedCommand$1.class deleted file mode 100644 index 4258b9bc5f84e77c8cede298e8b93fb1efe17da4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1383 zcma)**>2N76o&t4L!G2<2`y#s0u9izH0*0xOzfnF#6fimNL&Qhv1q`xD?0&khXfCR z1P_1&61QwZ2oOSoE3S~>0gw={fjB26xIqXZMgKqFnKQ>TXEGmuym|}ZAPPxr#HIxL zF`A%JnsKv)Eeu;(##qK#wy|ty*}<}tWr8KcvWsOm%N~}!681?rATXXbuh;7KT+v!c zhmKQiq!+9pbb@rws<}=z>(9?yUbTEc<5-$HvbI#Ik;sCYKj# zo?|rTXPuyI&AJrnG3%Cnl?wmjr0F*T+sRQ~fxfo-6IZNj7S+%^+x5emce&`)=lrUK zgY-ee3F}jSSeI}}#$g6gd6zSWZ#L|?T+MN-S`hewj1!!8 zl0{)T#gb)FSu~a$OP*zlMQ1t9at4zEgUz;N?8Q!G+V-8^EgR1g?ioLy{td-=t-cU`mG2A3Wk8^2iiclJ>MDX$sYv{Dcl`Hy5jsMb8o zZC)nbuB;p9l!C5Sas?$%SJ*<`P_+vJ-7Pj|iUPeY%9W;zN}0}1;Yw+yTq)%$r%E%1 zDlqV8sG_MlrT$*4Y6Y#V39KmUrl}kGiZY!yed;tFeq4Fp4eYTd@cG$q&$@QOPx&g-KqCBKLJctHLTkMWHBIo{zt`3HQ$XYw!jif`l{SV!&cYBsqK>uEfN4d*4ADgH$a hj{UD7h7DA&1A`bMk71Z}q!}5eGXY8ZYCkzr@t=`SEGYm0 diff --git a/src/main/java/seedu/command/FailedCommand.class b/src/main/java/seedu/command/FailedCommand.class deleted file mode 100644 index 4d899f637e4724056d06f1d23fca85b46d47ad67..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1946 zcmah~ZBr9h6n-`kLN+V!2v)I*(L$&M6v4`iVjwjIf)c;96bCOLkI<1*G&)z+6_c`~RyZQ5<-~RxxfG>57Vk(Led>q9& zT-Py;q>dTP>eSs3xGAr50=ER_1r{XYwvJD5M_v~NmIRgsRs`+}+!I(8xG#{3U@e06 z2+|sijBTrGs$@Ejax`?h-yJCpmo^=x3bo{sS#?x3nKrGGDx@mqvS}A~>9MGxYss=L zcSXaMiT62A?lWLW znVf6pzu7X6f^;L6{mLv^g+21l*he*Yz3D$vwj9T@i|<>Aj^ zhJk%NHtvfftBtIN#_=zR`yErf3*$w+7A9FxIYbt1dpPVKSck z)^hV-@d)E}*Lb7p@ixy!he8J#4Hp{;|7$eZqDr-3*=DKUA_j~$0%}%r{W!0VT&rU5 zs$+N0BI%%80oyI*IA&3r5a`n-v)ED&2Fi?GP{%E8f1u@1wRA(x@Jh98vTs4wSiWL& zTHH;`ae17eR^bKG!_9dc>PXP6J0)a^$S<$#uxCmA7l|_Ti3c7gcMs&WVi7 z=V+UCy1wsu<~ww%Uo8|`n>1&d?m1;v*~Mn9&44xK^76LS z13{jwSw5vY7%1O7SX}0(Wt1N$4I!CzuEJc8;Ue)vz9py+@u??%gO-^36`|L4?@PoU zbP%KHgieex;xfjAxG_F8TEmH75c-J=erEu7^LPL%dJWIsF6Q zpHf8MLs_S6{EzI=_Kx@ndl*QZpvyyykBEoP*Fry3=W>mtfdO9HA>=U3TRO(8d6D<= zDokGQ0w$n%09WZ1Mfh(#40m-&FmHZ9{jY$!{T6kzz6sFH=OiUbxkXu|tWvU+10UTU z=6ysx%=pkfBz(j?#CZnB3C{TF@i5YQ>Gh!d=xZ+_jecgjjydkIz)$`i+`uw!;vRQP zVIFDRMuz_zo7{OHOFYsQ`53MjbGE&h74$MH!!kBl!Y1iw zNqw8NACdA7>F#n4_V56Y>G6ctXS5tp`<&Vrbq+eZXQYTQYv^GAq>@SY5FAq8c6`8< KUSDz1*ZnWZq^f}c diff --git a/src/main/java/seedu/command/HelpCommand.class b/src/main/java/seedu/command/HelpCommand.class deleted file mode 100644 index b6e80b4a5b93a5015145d1264d048995892551a5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 316 zcmY+9u};H45JYEf#|IaKLm~uvc9*3_Dr_ia#fi}#tD46qIn*u*(O!V?^rrXZ=J6|uObLLQkxh8 b5O%j{|2qYOH+a9KmVpq;hZb6k_R#(UBs)9C diff --git a/src/main/java/seedu/command/ImportContactCommand.class b/src/main/java/seedu/command/ImportContactCommand.class deleted file mode 100644 index f783b2de428d0044db95e34fffb03e94a02b367e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1778 zcmaJ>ZBrXn6n<`!X2WJ_LJ$ZEAhxyAv?dhLs!%Kjs?kuZp(yye>|Ss+Z?n5`GJbUY z6Y|k7eDONL%YR~4u8pa?nOJt%WrZ?|RW`E31(6{8-oP;0G@ZAc$y(gzI?%B@C2Z<<9e zUc-yHN;FN~)k}WmMYro}cpkF?nx{`tJ-go5@B%JrxQ-hdUdB}oMP8;cqu>J#AEKsU zOTzm+bvsQ+P^r*ZQ1&P3@^@Emj=mbYuLpn0+)Oz z*)?RFZ@{}04`3sFrQuU1`59(3e2yC)!-cIl5 z{@pHo)03gU*M%WgU42ej|2s$Neahm= z-cOYbCeE*VgsKjDZOyGTP1zO5Q6=Z2^33UG$d5h$!;h6n4O*yNr%@CbH>G3Q((HE> zO_kems84hBfdYMJBHW+!6yc`!cIsguo#n2ia~y)FfYz7jv`P_z_FUlvqL7IkBU(5^ zY^U%T(Gy%aM*JaJ1?FhYkS_tzIs*P~O=6TR*ZNr7bYiU8LJ!K1$kLXe{}5rRJtR+| z9U*>-VMdI2h&f^dj6=Z$lE@-Om{Z6T^Jx^wLe)$~$d?9?keTl+?VKY)pz$6q{!Gt4 zJFW|4kMN|@Gkbr}2(+&}Lh2A>LChhNXGrgyVC2^`WN06)7Ou06{?Q(uJBE6MWR*{+ z7=K7uS4qh>7^J#oB|Vf2h-i0M(|L-C;O0NWh?Cj? diff --git a/src/main/java/seedu/command/InvalidDetailCommand$1.class b/src/main/java/seedu/command/InvalidDetailCommand$1.class deleted file mode 100644 index 71567a2ac6682a3041fad77c86dd76340fd7a6e2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1021 zcmah{T~8B16g^W)x2+4Tic(M!p&<2xiV8evOiFhP8`{OR3q0_E+uaFWTy~q?EyiEu zvzi!V3_rkM<1aAYX=%zs1Igr^Id|^dd*|Ny^Y7O=fDLS9F@t*<$he=O-2)+KB|H>j zPQW7p^8ywG5*lu5nJ|03Vflnji3|Syh3pq zrgi_!@?1ydF(tZ4vvOjcSrkh1Z7+yi|G38ER^Uh|P+o&a@pcf!5}wF-if1y$F(KnQ zR%8_Mf?-D7E_#-KTr`44$8J?z?m1c*2BC~q;r3F%D*>+stO;1h3PbPdMZ5Rf;;`EC zs|>R4`#darRuu7wK^Y|6ZJuyDW|;5x@XA08vpuI?ql-ftoubxsM23as!eRAl?>C|> zW4~0@)gz-+(-`Kizaa&oAk!qJfy|Ih4`i04a>@IK z&^`CBkdVP7rZ9>e7O+J8n7+>%@j6OSi8Z`OgV@9e*u)Onh=>!oO=YLL#ZOWUU=ia7 l5}nkBfFW#MKoWPzIf1*B7Nl~7(_KrBk^@-^DHB6U{|Efu<>&wa diff --git a/src/main/java/seedu/command/InvalidDetailCommand.class b/src/main/java/seedu/command/InvalidDetailCommand.class deleted file mode 100644 index 56ac2f56b98d4cad33a040760feb507aa5b29fa1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1178 zcmah}ZBNrs6n^d)l$8PlVK5jkj)B_{CJLgW1~Y*yVVJmKOi0vjy+UQ{mcAhVq9%S4 z<4fZQzw3`Op4(Oph|=Ud_w>Bqb58sH$Cs}FRt9^tu;s@?Q>g%WJqUo7eyj- ze$4BRP39e05x2KutM$XO+783Xm6l`H`6d<2kSrNTYD3o^a+_`t*1z~lJyIEZcDQAi zxv0caFo>jrI0h6fq9Ea#f+bv+a6`ee(5wi!DPUE=EdjR$+(D8G51LgE`cpVBDZ}t- zqp%o;%xU>~&Y2~KT&D6`x9bOV)4(GW%qH{KY#1VYC5FlWPmns$8-6FrVKi`X z^uoq*owsehWmNgGy{j|C^`MVCYLl0YwqrAlg`zFpK5%Ngv?azLWhzuwd4unpYV#jz z+J!?-HJniogx(uX8d{ic{8vP3g3Zk{9*LJNv!-hrH-br*xn-&QoW2HyJ`jLfB8E#` z2l0crL^womd6Gxyl=Gj#^79`NIq|KB3H!(v=s}cX#3%|w0wbZ{1f7huo%s)ly!-9a zT7RWcVOrv)=YBld4A_P-+zDo24ER?EhLeR!$!_R9vv3|4OcYEkD#TX&z}F8HB8A1L3emMz%~ME~{lMGkG`GB+O?Rt7jp^-r z)s7~YtZ29TYTexqEvbgz)~k)iS}UMIw+T`x3D#KM)1h+1Z89=Lefg#P+I1RkPM|TC3S~gW8e=*%(90MiCcHT(WT)OC}r}S45dc#>Q14 zlbEt`4cBel5W`K}GO=vqHts0Qw>_`cajFAQ=a@vS@u*K&fI^}=XitI^a^<00zh@_` zSB&gu=D$Yba46zd@!zsp4!y)_5Bxj6v+3>XCq9P|W@|rcZtFMVzwWi$Zk-_$L(>s$ zW}CAdj_sMRUzCEHx2rH&DE&KeSx%}S@UW$It0~J?IC-$HRUL+BWn;&7!#4Lvbz}xS z6#@+wo-Q1-Z_M*1lRRD^3SJ3Pq$eoN@>P6CieI2Ukzq}wvA)tI9p86dhrth+E`Em5 zMPw!S9`PQcdl)U|x)_mYqaQtq5%O`2LVkq=F_M@f&IGk4j9(a6QM&Sgm_Vv{jtDkQK@P?8R8>3}6$T_iqIKHPJb(lm7jX8r=-X5C)^ diff --git a/src/main/java/seedu/command/PersonalContactCommand.class b/src/main/java/seedu/command/PersonalContactCommand.class deleted file mode 100644 index 1ebd30a174c24c7d51786b5059de5eb1019ce12c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 440 zcmZ{g%TB^j5QhILlmoSjH^g9En6LmAcIiUnrim*wCL;SoJ2A)5*7SnBmWheRg%99E z83#cPMmKXi-~2OY-riqc0UTl1fsNG~%2;zy$GXCX!X}||Vq%k@5=x!!kWluMkO}p^ ziTR?4Mw|}xXe<@QQx1w;BIhb8(tyv*th{&0X_mx#>?d)qgWOM|NXOyft)6HX6(|>5 z*j8w`*g=!f&X~i(3+9;jcQ>K2j4f1Uue;@Ogl7K>{haSD_Ba-H{!kciz|;KN5Ly$% z_rFG-bC&5F`AMtuk5YGt138;5X9O(B$)LnmCEFKI;_coO=s^NPO>AXe6zhDWZOLY6 Xwf6|?8KocE5m5-IM3S%~u?6=77BOW9 diff --git a/src/main/java/seedu/command/SearchContactCommand.class b/src/main/java/seedu/command/SearchContactCommand.class deleted file mode 100644 index 5419bcdfb6b945a66462b827e4a26904b666162a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 701 zcmZ`$%Wl&^6g^`nF>xG16OuNxQ2GEuknn;93lN)#N|9U^B(R^_qcGI5iyu|^BG#2C zAQpT8AB8wWQXT>p_t^K|bI;s4^Yz>3F9055;G&N8Ixbjf)q!t2VEKqx_6J0zJ=neiJ7~g#< zP#L9>5@-cFQP0Zxk;C}zb`3l)|H|LlPwHYbG)j}PU^s_#zHG7Hs#Hst<9$t-*| zN)wWbQ97T?B)V@_^l%v+4=x%WJTyJ*V$Z?8hg)a~?B_~FrLPvDIw^FT_~YbM#yUEP znQ@t#jCCED5X;+o%v-VuOOl=O#OCbXEdWj+;Z)hwo8gSPc6Es_)U1ik>by({%0~}b-9n@?Nb(vb|eFtD$oD%>5 diff --git a/src/main/java/seedu/command/ViewContactCommand.class b/src/main/java/seedu/command/ViewContactCommand.class deleted file mode 100644 index 878ade66bdabb49a13b04830f52e0c62cc33e839..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1199 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 Z!E6W|<5R{8b<}&XrV787_&tWp{{apK2TuS1 diff --git a/src/main/java/seedu/contact/DetailType.class b/src/main/java/seedu/contact/DetailType.class deleted file mode 100644 index fef8722a710e2a79e72748fe63f5e33ee176926b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1234 zcmaJ|XcEJ@0Q4yi6v;a-AGA+m?U2P}C85eDsKCQSh>)_Jx!>Nz`KYd87 zY-(!!+#l6+-;+U_(*1DHp7-v3_niCQuixK(0$70NgM@p2+{XhM6Ef!g7{)^$7WmGh zf)PLABTgPGh;qy-7~_~z5aakn!8pey1#yl~Wh^sD#r%fG5Gyn-Yp`q~DTO(AKx|8w_&krCus&TMQm;Bd-?-ZD-GV z%fNKno!rS6wl#xc{MDsR4$WHIYBD5}sY?^3mHM8=5G>e^Rcs&ZT8)yqTcZ_OoUr+t zVK!OVHxJEB&2*|6qt&pTYBqIg^PKJ2ttE!h|5WOFYKOsR*j2}DwHwq)N{S_=YPIw; zr|x8myehd$t$PqHP|-}E4$WyF(9Tt=Zg8@ca&Dxf>PN_|;FS$b;@8 zdeMccn8J#R+gMeRz*YX2R55~46;U3>c!=>Z&O;od41x1;ahY_3m0H~)5s_r7&%);J zzEx?F(E0u`t<=nBGuxNeoA}?SQr$>@T{n$JxjaYjahP7ZvOLC>0)!-1An6rIk_D1# zfh3$NT-+lNit*_X_rQnixB-Tn#5nTL-vRpq*D2f|i7`x4^ol(nlG{{ z*cDk8EG*cNq6iiVd4JHU?hd`dvebcUlsz2;jIy_bkWrR92peUkgNShqcJA;hWD?{@ cfc(XwlD9!D5?ezMC7P_O>p6qFl;^_SAENf|FaQ7m diff --git a/src/main/java/seedu/duke/Duke.class b/src/main/java/seedu/duke/Duke.class deleted file mode 100644 index 5950fd25d2076d3eb95f741490327668456f3d38..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2404 zcma)7=~5d<5dKzR7M9^Y%wZs48-s+Aa~NVnNMgW=W3B{n0*;+5(trhGMRr$2x${3y zkSEA*S6RXpSLFfnGmnvni1W?tN&*CBS4lHHJ>5OsUmyGTe}Dc3U=qJtxPm)%7{IJr z=1k06s17)HO?+g*3=SWgxM#r%4xgB~Z=nGTN@r0~ONv@n)QX}$HSw8+RjgT9#{*^Y zbBpXRENoy?Ef3Z5rCJ^-tB=+4m5HxwVb@|y$tKj2G$9Q%B{Gh0C;Ypqv|O?MCk9#< zcI`tup0=Hx_^R)woSi8Hrsro|dxr`a7d$DG*?7pHh`yjq&4KND(lyW>iUjBQqMdS9 z^c98b!}k_ao^PNxlnj~i*}xffN!g1B()BWqoetS$ADd3yl-)XIiB^gcdUG<7Nh<#a zPK6MfFA5yjnRi~H6ADnLW;*4h{22q+Mk*1k7&m+^j=K*JOe@sv1%1ZJM>eZ#&5qHQAr;aF>gKY0a$Hq|z&n@{xQbzc>lh~7K@n7BSYQ-U1AQlJsH#0?AuS~8cA2YxE!#8p7^ zuA6b^i!2jqfqgh8G6DzqM!R2QF@-9HyvldpxiE7S?AEX=Nx4Hq7|_t{SuP_(w8#grI99d@rKP|Aa>R} zB?L}(QmHHxL2DITj6)#h5lSYM9lB|t(UX1%X)y5m%gtE{stT)>8Wm_BYv~hOx}{B- zlZmX)8Wf&=D9ahVaYjU?fKJ%a^H#myrYuxEKla*&=nw|^ZMnh^U@anQV33NaM%6oq zgWlP$dgmjY2#@N-$seLH#tBO1#i5*^E1Aml$gwz3->=AeJ#iovYNkjK{o@jPG4)bt3YT z%qkNDCT{Tu!$iAD%Nz({eD`^(qHND|bS~11ny~^uw$WGtUHo_d{_@|aybXNm#0AnZ z`Z7kZt`oU&`V!Y~RnZ>BILJc7ztOBRJQJhUmI8Xz-c~>_&0ZoY_>Tlvec`c+J0!ZbAGjoR-!sK+efo+I}I-bL`?|H=|*%m4rY diff --git a/src/main/java/seedu/exception/FileErrorException.class b/src/main/java/seedu/exception/FileErrorException.class deleted file mode 100644 index 23f233332eed1683fa9423e4bba6bed58e644879..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 229 zcmX^0Z`VEs1_pBmUM>b^1}=66ZgvJ9Mg}&U%)HDJJ4Oa(4b3n{1{UZ1lvG9rexJ;| zRKL>Pq|~C2#H1Xc2v=}^X;E^jTPBDj4x(I(it>wGE0R+SN;32F^s*Am5_uR{7+4t@ zl!{YRQ%dzyVRHJI${87iK^pXP67$ma;f63MGB5!h2Lg;h2s8{xvH^LrU_Ju_tJZb~ Y#*JWUb|A?H6lMTwU}WF`(o77T07_jlRR910 diff --git a/src/main/java/seedu/exception/ForbiddenDetailException.class b/src/main/java/seedu/exception/ForbiddenDetailException.class deleted file mode 100644 index 12078b9bc4a25ed76db048c7fceb677167d6bcf7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 241 zcmZ`zy9&ZU5S;aqXpC4`TiB_EDQ(2YM+3~{U zq_c>V&}hwe#;G#V{JP^)YGOM)sEhJZL6y)uGwUqiuNV9a5!!hyh?Lz2zbbT5l1K9) dS*a9sgmnrIR0ns^t*~7|M`TEVP?K9i{R976Hw^#) diff --git a/src/main/java/seedu/exception/InvalidDeleteDetailException.class b/src/main/java/seedu/exception/InvalidDeleteDetailException.class deleted file mode 100644 index e7603953c46847f9e40ddccf81f9652ad5a2d06c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 249 zcmaJ*Jr4m<5S(?~afm{#&>`YVjc9x%644O-bGMNv&pY8x{4JG4;RpCpVoyS8H<``M zWG4H3-5&t@sQPf=dnkLT5Zr;bIvEn2R(nmzkK%|4wYj#uNcS5)uGGee;xFU$81htS zq&c%^Wpp%V!wHW$QQAx{As-SQ+ulx{RRwtz2;CENlm`6uf`36mJ&OiL*=_KvLlZf9 gI2)3cT0vJ>pX&1C@q4F8}}l diff --git a/src/main/java/seedu/exception/InvalidEmailException.class b/src/main/java/seedu/exception/InvalidEmailException.class deleted file mode 100644 index 023bcc0a937ca2b344e4dcb7bb8ced8a36d1205d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 235 zcmX^0Z`VEs1_pBmUM>b^1}=66ZgvJ9Mg}&U%)HDJJ4Oa(4b3n{1{UZ1lvG9rexJ;| zRKL>Pq|~C2#H1Xc2v=}^X;E^jTPBDj<(XHOn3I{}nwyxJ<64oNT2PXipQo3VSeD4c zz{0@F$e>!BnwnCop9+)H$Et&oK^UY*KPNFST_0`^gCYYH(1{?x2!ufMfFv7`Cky5? cFtBQEXJFh2mSzW%Y(Qb4Adut$(o77T02t9UrvLx| diff --git a/src/main/java/seedu/exception/InvalidFlagException.class b/src/main/java/seedu/exception/InvalidFlagException.class deleted file mode 100644 index 594a7c422d0d54930d89c907eec0b2a9cccb7ceb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 233 zcmX^0Z`VEs1_pBmUM>b^1}=66ZgvJ9Mg}&U%)HDJJ4Oa(4b3n{1{UZ1lvG9rexJ;| zRKL>Pq|~C2#H1Xc2v=}^X;E^jTPBDj>6urSn3I{}mXnz7T9KSuP?DLSr^7yg!&VBrV&QQ{_`rMoc8 z%rL{g-j64MA?g;2uuRlU*aF5#X%&wJirwB$pfm|Q5@;-yrd4uwDcnfcXT@3vNw}w( z%1CFSQ|T*juHs|jZX*h{Jk#{Lr%S8?Jvhl!+9;tcFo=k}#G$X}{ErGWv#{e!eQvU^wdA%06GQTPBKC1xeGW|A{G zXXc#D^L2j!7^3E&2**anMpeKXDXr46K(W)^3K)~fCxQAxXecyvltr27YXmQ@%q1qKO`pSkqix&O=pjoj`AQt#bg kBw8r&<9P{gj%Ku&H9s6MdpC&dXKgcDEVIa1;#olX4TEt#$p8QV diff --git a/src/main/java/seedu/exception/InvalidNameException.class b/src/main/java/seedu/exception/InvalidNameException.class deleted file mode 100644 index 28b35bc368e70fc113e3d112623b1af755f3e2a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 233 zcmX^0Z`VEs1_pBmUM>b^1}=66ZgvJ9Mg}&U%)HDJJ4Oa(4b3n{1{UZ1lvG9rexJ;| zRKL>Pq|~C2#H1Xc2v=}^X;E^jTPBDj>6urSn3I{}mzbOCT9KSuP?DLSr0v;gvRGBMO4p_~iP#)J7*G0lU-P2o%OqKmzr-Hnd0&KE*5Lhpc$ZD2=x? z)fs8e%vpsxSY33IP`o}-Y}A1!*DW0r9hv@KomCYD6b0moC`cuJJ^3dq(8$sb^1}=66ZgvJ9Mg}&U%)HDJJ4Oa(4b3n{1{UZ1lvG9rexJ;| zRKL>Pq|~C2#H1Xc2v=}^X;E^jTPBDj?VDL#oSB#ISd{LVlHyvCoLW$lnV+YZl~|U@ z!@$D8%E+KroSK?as-Fsz)5orbkwF-wNk1nsFI^vQ5Q8EE6VQ<$zzBpu1A!zPkS7b~ dGcd4fZD(NI2$p6Cl59X>pdgUs0MbkhoB*SWHAMgb diff --git a/src/main/java/seedu/exception/MissingArgEditException.class b/src/main/java/seedu/exception/MissingArgEditException.class deleted file mode 100644 index 1321f1ef9b39fa4a0b9cc50cfbf1df1d225f8ce3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 239 zcmX^0Z`VEs1_pBmUM>b^1}=66ZgvJ9Mg}&U%)HDJJ4Oa(4b3n{1{UZ1lvG9rexJ;| zRKL>Pq|~C2#H1Xc2v=}^X;E^jTPBDjFr`^<(dX-kiZ#hXEe1MM<+a}!XCbOBD z%w%8h#}mL14F@J18#Nns0c)hRI*$d+p1Tz&P2+$BnhT|Al^u7KY~(It#aYK$;?rE^ zq_b3Ms&qI>!Zpdn-_Nc-oz5!OgM+-tI!Y)DxG7PPdGz(XzbS!Mp7SE9L+{sxE)0G( eAHmC=j25$Y!GUuB4sk1No6%yKMaBwW1Jw_zn>XbE diff --git a/src/main/java/seedu/exception/MissingDetailException.class b/src/main/java/seedu/exception/MissingDetailException.class deleted file mode 100644 index 321502d8477a049aae1ec02a45db6305bb76cdc8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 237 zcmZury$%6k5S(?~afm`G3XPy}rA9PPi8~1 cQYdH(YkoLT=-oiqkL?KBB0~a%qTC!xZ_)BKqW}N^ diff --git a/src/main/java/seedu/exception/MissingIndexException.class b/src/main/java/seedu/exception/MissingIndexException.class deleted file mode 100644 index 4f4ca45c61c51e0dd4f51de70c9d98c8d177bf89..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 235 zcmX^0Z`VEs1_pBmUM>b^1}=66ZgvJ9Mg}&U%)HDJJ4Oa(4b3n{1{UZ1lvG9rexJ;| zRKL>Pq|~C2#H1Xc2v=}^X;E^jTPBDj<(pYtoSB#InU|7U;aZWLT2PXipQo3VSeD4c zz{0@F$e>!BnwnCop9+)H$Et&oK^UY*KPNFST_0`^gCYYH(1{?x2!ufMfFv7`Cky5? cFtBQEXJFh2mSzW%Y(Qb4Adut$(o77T06S$g?EnA( diff --git a/src/main/java/seedu/parser/AddContactParser.class b/src/main/java/seedu/parser/AddContactParser.class deleted file mode 100644 index 39166be10deb5f5f15eab46afea50eb0eb7ffbe0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1113 zcmb7DU2hUW6g>kAgMbA=sq52R^TA|u@66qE?maVe@7G@+`vC6Yjvp?paNOcp^&#Ph8%d5e zKfGA+;}TLFX$J2DX-elIgFBZ$WKecGx?l+HOHEXjijrvC}aft?4`x zjwTJ8A)DKOsU2&op_whU?pV@n-OoRtjxk)W6Y;33b%*&lG7SFR*G% zJV$|JoukN6;wW>dgsXRYR#Q~uKu2s_*Z-<`GEiid2LgidBfzj^3!(Sap;Sv9gE53B zl`^~>ihqjKsE|f)_%AxQ$JQ_*k7uMRZv+uOKy9AdJQp3=>j&dTivt^PcFu8ApJ*$%K`T)sVU_%qghH?i$iz2n<{1{5L}`H{<=Ln>v4p z1kI6)rVV7NQ4t^;q+OgmBkw7kfqkF_4FFm1Ft|W=0U@Fcpl_hSLw+ml{S0??J))e# zQ!Dj7CkT9k_t_cv7iCL{DW(1iB86fprfizC#GwdI|(1H6I3Hf`!z(7 z!ZI>QBa1TmyT~I&ZeWQrFx(v0i2nhA CKr|!( diff --git a/src/main/java/seedu/parser/AddPersonalContactParser.class b/src/main/java/seedu/parser/AddPersonalContactParser.class deleted file mode 100644 index 080f44cab868e21ebcf2ae52fd32d4a4770db28b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4706 zcmb`K>30)l6vm%v(hd!wh0;>GL1mFPV1pYVnz!d>piAaD?Bk~jtAO=mE`^3b>jEd34TqQ1JViMw)l)jWmrB!4C zxEhAM%Sv}nOkTx)={^v^IIfYNYsLFI@w#4`H;6f?;zsehNg9X5;bw8TMVhyYxlP6G z;&6vF?i7c+#Nlpf-XrE-759n5{nB_q93B*hhot$im`7ARDh`iH<8g6#LdBCRCKNPg zG$Wf%MG~9SsazzQQ_wn))wEbX9JM;a#TV-o)UDT3dTyfvUr+CD1^&(Hm_~&GJ*5rh zlOvk3GcuB3&%9_lkK=+DDdO+hD?w%r zGpn(|NT#UW;d0%o=SK4*yRw>*G6&6#j%v{{t9N%Kp~v*xH4NJ`a8+b~B%Fw(;^E<( zp{L^OdiN>_^p8iiOioXym|JUB%Wao5VqVcHhcmS`(GToE3{1T9zd@nQCUAqt#+-xt-nB z@|%xoF+Js^W>s72cl4ZUOYfX9O>r{!&cC*v-l{V&Fr3aCQEiJZ)2xeyct)Ea(CCw| z9mEE3sX^MiN|=POuZMbk?2D!eVVU#6iCN`>gD~Ka_JBW8Ai+9DmC$fVgJ0!9ztH^q1UzzYxQFvdpJ`i(En%hP2LJlQ)P*XVzE3b%1Ygq%H(q;>A766(#bPnpKc^0 zvUe(I=8CP@V7a~Q<8hH49p;dX9l0%Iq>~wY)yu-L-vx{6W=PgyZcpN2B37VsYm#Pp ziuTtmrMOVHmRxCPFqfWTqzyaFVs{Ge)n$A2dUV`w{Vv7X-s+jFp6zFyJbidr@~oL} z7ULEvmQ~NPtQTAg?%cdf)Xr|XCp)jBJHK}8*zlZC#qcv3zBHUWm?r`ElD6ZAyz$+B z?(l6^c(+S2dO)IEZxpnIZ3BF?bK&Rs7XBzW%hnj9wrDIbpf=>6L|y0@`~|25%-9o}L_L24{GG|)Ab)2S z(BKI7VJ3&pr+gb`pdF3qV3B%P z6ycm$ix>e|$|6o=*~>5sJ(z=DmJ?$1<&3z3dOVUDMc^D{%P%8*8#)STEMWFf=%h)^ z@o$g{`P6h6>QDjAofH55d6a|dDAURGYp{vKtkS}4t>l|i5x{9IZxutXrr%n6u3^YC zSll`+;kW7Mn3?eXjXGtQin%@x~DDbblXk78Zh zilQBsXoHYdCeeAA^M#M>?UWB#uD_f5d(ec7IbAL>_5G-6Qt88MQ&HB1tE+@-fr)FO zh3f=2uI^$C3)kgrT|rzUtRqTXG2)67m&Ww>5!Wbj=^k9&f{QmG+UmF#Rp3gnoFv0! zi0kS~T#^@WRMX>H?BH7L#g(W2e&QM@u4`Smc)^?s*OC&hr6#TuEnGcrT+5i&CVm(T z*9~kPB(6iO<7VQzg}81fu3L%gHsZR2xbF1eS|+%7zoV^=tG5EzJuK&5hIxRv9<0PA zdGWqDJ+6?0E9AxXDD@vBt|y3V!i9@h@u_fe+p`wq3KQ2!7Ot=xS0B@Ia6QA;v&8iR z>v)m4ULvkniR)$JdWE=NBd)_9Tz!Iz*H_x=xK>u+dXwe6#W3#>*SnRtBrjfvr^j`& zgX?53t`DexjJUWZ@P;jmy|ftlpO&d`ol?Ses)_3~3)d<)uG5*8gNw%!@7=Y$FW2Ks z;`)lXz9p`&iR&BU`i{81_ux8RaPgi_TOHTx3S2+1oF5tHC*u0K5|`w~d;j#f);PG< xcyawg{a=aeH{$xe43~n7xSv_aP8a{md0HzQ;Cp;fOcr%!=O46t*;j*0{sT~LSPuXI diff --git a/src/main/java/seedu/parser/CommandType.class b/src/main/java/seedu/parser/CommandType.class deleted file mode 100644 index c84fdcc3f5b0de8c4caefc9a643b102574eefbf7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 973 zcmaJux1V&r#;U0?ZMC)WQ)CS*Y?}B zPkkrH5PV-R9XA-%Vzp8`u9^(WVWDi6-co4$q+r%d7Q=%N_mxo2Y;Wug8P*fYdlThi zukA2|P1koS<8IR#)a<555mi*Eeq_ib%v1Z!&U&`r$y%d<>vwX=d&%>z?~e8vmi}|H zoIGI&S#HO-N8shughl0WX|@8;U4Zs}HUJZL$GE>|6y>STtiHn7Cs zY}vprUNWrQ)pi4MyfW|*8wTbPHL$=a<3r z>h<*1i=I6k=BCoFyZCR_+`%plOoXN`c(BT40EDDOAc+x3dVt6pzZhl82w?@QpqV1? z5g}jt1neuMO9VcXN7F)95qms8j`iz&NksLioce~~CFI-r67LEmQGWvg`T#YRj$c6e za;x|zMI>xNBPm-~Bz+ReSM3MnMpO-4Ks!fBIJzvH8Q~Z~;mitWP7zL6{Yi%c6B?O@ mJi(0B2u?6-HIxa$);ZXX0-boNao8g^37hmU;W4%aKKTnWBFN(a diff --git a/src/main/java/seedu/parser/ContactDetails.class b/src/main/java/seedu/parser/ContactDetails.class deleted file mode 100644 index 6d54ab1eac977215b85858bc6b25ae732dbfc9c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1249 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 diff --git a/src/main/java/seedu/parser/EditContactParser.class b/src/main/java/seedu/parser/EditContactParser.class deleted file mode 100644 index 93c07d3eb013e3205b0a6e702a9224417e4652e6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1979 zcmb7F+fo}x5IrMlHDVD6M7WvQA&$V}BIFRqb}WJoLb6E^b}YcLotKezN?x?uRqd`w z{GN|U`6X3;@oO$sxXP*E_f+{$`~@lJ(z_BMkVsV?G`rJ#`poH`?$#fFzd8VL4d18; zVlIMtj+BZ%EO4Y%D46R(43{}RRuREmoUorpaMeRx=E%S>89>3 zGX#?}I}D+$r4c^1p__8EQ7cJ%%L5ZbUD%E!T33|aHR%f7a2PHnJ5Qf^+-W04MRKeb zMBV4(_?$t_eOH!sUlYeN$4!n~94j2F99fPvjvPmxA+l69S|Zh=)v(JluX~b4a+>b8 z6y5XG*$ZAOq8Py_1vklX&XH1UqsizvRt218&n|KURQT$P$`c5z9cb;`H8 z>q@(e$J7}fxf*pvTfmA_H*}XF*`-U?yS0gm`zU&~!Wc$tqU!ZqS-1}o#e~cu)AKHU!aWot1jxaStI*F!Z zrc-&F<%Hwb)4J>eZ_mcv(ylDKnf5HUD6+yZin=Q^9FG~MI^yf5je7aNarlsid5{Kt z0OJ@$9MshQE-*0W4H|k6l8xpVtz)!1PftcqW%ec5&-B8`5eWOnep=6Ag2+7R8-&OX z?9Rml;eCV(^9SMQ==}}K!g@_zEfz@7+gqGj*V};RnLM zqwhv2bX6HvQU}j5G&>$j4J(WL=>J|}FaCKu9{Pz+^8x`D5v6s6{=P=hPnHq9k6C$r$ze1tqM(X3120cIfRS;0IZKuF~sMmWw7y~6}O{z4C}>`x-N;1jAuGD%sxNF)hN zVVZ~(IwpCPp(}nWfWdfd9|O<8LoW~t{tE78tEuiVTi%HZ0?}Jky(Gl@JWG;5DPY*f RL+p^CMcPMb{|WuB{0ruO9((`* diff --git a/src/main/java/seedu/parser/FailedCommandType.class b/src/main/java/seedu/parser/FailedCommandType.class deleted file mode 100644 index 88d553ca1284b3d0d1db67d23a2c2c44f19140ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2072 zcma)+eN!4&6vm$glna8a@727hF=<4bP>seU7~={HZURfof(cCjEt2mr!q!bLtoZ%9Lr9ZjeOcE zn@OvnK|dEWl1U8%=R%HY`L9x= zi>9Mt^6C4}rTeH-Z&zCyrlzAGknT(DZ&x)$GPOq4ZtrbYn}y0|og#jjC-+>#!gOZ0 za#V@cD~+9)bJ(mkcH+?w*vN9NQ9E4GF#I3mt>}h^fK%IPR1VusTFyJo5w*NkKN&TD zW>K@z-dld(iYs&}gU)`txm8Wkb)|LRxwbdCju0$xha63ZQyyDaxu;w;N7_gPk09;_$&zA8v#eu*uE5)VbLkqo zw(9#0Drs;!dZsP8&E4wOA(g#&w!?{frPYd`Njp8V^RvcR=jhF!r@yh`)lseuAX0fk zs!&Kp3aL&Zl`5oag;cPRY8F!2LaJOy#S5u^A+ zzd+{~8e|l$fhaw&npim^0O=*A8COPrduke-n{odD5FA)$E^oi*a z6Y3HZ7Sr1;CL%`ni|G^7ufz<98Pt#ShQtk@B#wytNI%XT6*r~_WZVUD7xkdHOX4o; zJ>tg2P3R$Ulj5%EVR2L9uIjzwu8I3tkBGZ2Zd%vHMa9kNed1=teWLe^yCLqTJ|He8 z?o)kG+?+o28+FL*(%(VJ=c30cb-4&TrEV7yr{s6h=aiI-0jH!>Xox_u5dsBA2>}-u z2z2iH(C1>7(C^{~VZcR3%m6D1^oCEN}Hf7;lc6AZ{RWIc<|&OYnQHY diff --git a/src/main/java/seedu/parser/IndexParser.class b/src/main/java/seedu/parser/IndexParser.class deleted file mode 100644 index 40957f03e51da258cdfb4647b66937170ac912db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1856 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 diff --git a/src/main/java/seedu/parser/SearchContactParser.class b/src/main/java/seedu/parser/SearchContactParser.class deleted file mode 100644 index b361400cee7170575d146db79c94598a50c54f09..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1546 zcmZ`(QF9tq6#gzOEG(Nq5*yRT##B=ZNhnFIR&9(yk|-9^cF1(b`m}*NWGmTac9+^d z`9J!i-910NV%Zlt;WP{&6GvMA`dY2aggqT^E?w*+RE zEZ>)2V7rdLWBb-&SGEPj1A*kG?byMVK)g`AFQ8T3wiL+LZAb3+j}N7HpqvGAJ@}+F|%V9xY`J9J|w=t(<%f#o{CP9lPD)_=g6*~gO=$;%RFE?!8XVDd} z6D2#X$;2+UP3+-I6JOzqj+%+Daoa>44HFkIOMD~hDnn^@JUMnZT{P-%GD*`BXLS_YeKB(^Qw##wN|OMQTo4 zK0a`pf$OPWh{|h4y-<$GIC#>dN!zb9cG(j3H@R?lQp14ZkkmLGBi5^34wk@dTl%&q z+ow{p-7!qJ=oS%S#TDfv0<3GUfzTrYBWnNOikmtP|GD_;nSYcf1ExX$Ap z#6s6&#Q6m_RtAVqYl#684fPryAek%ug!$E1iJy`A1Nt{Fk@|C0+ZZ5C`}39OycG-M zUSecm0vSvaLKX|iAy0^Fgm#&hG-CfCuVW#Nce&LFK<96fl|&$ZAOww;t+Sa+XAr#x zB2Ex-Z2)6`ximoL*$bEhOgv+R2+#uKgGEjd${cepFjpS$VIA-DZ!sT&$_zpMO|%MD zl9zQl2|5kgIXYoy{f$^&VDc%Zi0?;5QkEp;6iFj;W~mLZLULBATZyEXxvq_fxkzGW v&JdHr(y5R)h(>*;rl$s&ehOXt1zP+!Oe#^MT8E-4q7#Uj+e-SYp*jB_=}cKl diff --git a/src/main/java/seedu/storage/ContactsDecoder.class b/src/main/java/seedu/storage/ContactsDecoder.class deleted file mode 100644 index ecbc933d2ea402c74c8a7a42333d2579ad6de479..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4452 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 D*1BXq diff --git a/src/main/java/seedu/storage/ContactsEncoder.class b/src/main/java/seedu/storage/ContactsEncoder.class deleted file mode 100644 index 49281443c32472c6d931a438250d172bff3b9a93..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1937 zcmb_d%TgOh6g`a|BZhH!2|Ez;2$n%Fkevh@gX6@=U@H;AiHHetvKXW;JZ6|t%?#Mi zDvNwX*4cP#Z=lMqO7{7Pd`PMi=d?!1U}RSof$H0@+h@+X_jc=#e_s3s;3|I5Fr{M% z(;Ct`BFN}SBCAF@W%3$kG|cMg#G$vLZ3p*cTu6Asq)y)s@Z6P>dTL7vJqIW;|mz-3oUO> zFa2levgHSa*Kk9_XZ(nCY827tm`lHn(P{1idezzbvJthXK_wopcxR$EhvZ$&kCfcc0M;Si3OGnX)pg%2ZGi=v#8#zz;mLu_}WHZr$&VV=aNZ z2EM}A0;4CTyrGxJU#E9%>!DORKeiNRTwu6k%2i$%tPXipwGexxV#B^>yFUA#Z5gN& zRqIF2SdAp#&$Sk%n?cE`%f|vE=~Ct`32kSlcCz*aGy+x3U6s;wrc>Ix>2TW$9_(!$ zF>!We-EzX&y0qoCXYR5*=(qmJ3Yb-a1SiY8re*7>Vx1K%^6h_J;M}gcqsp*m1{;Lt z$PY{>U~T`@Att9;{a-5`1Z((46~LxI>UDxGXW!jX<*cr8$a{si-1VMlxX+iO?7BO9 z4azJzj`WJQ>HCsmemO3tg%Q@;9n-1X(ocm47vHJp#KH9^4cWo{{xO8G8W)diYe5uE z+pe;-_{4oLaPgGBPTT~>-tEU%HOW_4{Y4?vO{aaIvr+bfeJp#3uIC)^HqgeKiw5lo zK0sH~wZZo~#=Ys6h-~H#5v^qN2Z$|1XNIE(h|e5AdkUlS65X4J(0_m4gc#u$5(H47 zlN?d*u zIK%cHTQ6H5TR+>t3&sbl`DgSAvogTs0U5H(GK4wu%M&5RwJ!4dmc35Td-x6;4EQ|f K3C^#vE&K~{K;td| diff --git a/src/main/java/seedu/storage/Storage.class b/src/main/java/seedu/storage/Storage.class deleted file mode 100644 index 3ec5ad437cfacbd331136be46879e8d05cd56980..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2577 zcma)8SyS6q6#lL;78VMmCO{x84M_;tPMoIMTCxC%X%-U*W(nyk>>Cgmn@S>(_PIZx zGkt+Ske56pGlei^rhV^^>h!y^YVftE9eD%HM1FL4zsKm@5@sGv|(21vzfI3j(psqWQ{9 z70lv%D(l)-aehFcevg*o43dnsi*V=uVr3Rau8QfyiyE zXt{Rwe0b*%y?m+Xp=fdZBd6qV;MaGjvaI#u$ap=4kMKN`5E{NGa27s}ErrtL^OHI&aENYc1> zV8B+89o*628d$|E18Z0}@ESh}H1F>`KUV@LKaT3y+@j360wU=(3!AOEN>i&Qj7ZgJ zY?u@C(xrD<^roNISgasP{$NLzm-3daWOKGOUHMe5mFv}5j%d|NP0Dq5%3}LfBn|*n z3Zv3-IM#Gtki~g*&9I>#vwJE^dwQ`V+_@ii(3F)+!(dGLfGcpv2OQi>hbQ>>R&L3a z3I!%Hi2s3fO{+lgF_ozOQ^~=o9$e*iYI4k1@{m@tN>QrM*MO>3lR|jN$i)LdkATG) zi>=8*uCy$N)wL1SpuO)%kNkF=<@XBE5L5HVT}+Lew{qgVl|$#PoI7vj=y7esC7ugh z=01cJBHUlWXQWrjd5JJ;xn7NbfQToy5Q^`jW;XEw;Vsn0lUs;*jHJiV;+M8i7jNTP z^gXo%J}2!#9cc?KwIYhs{Oq;y%ht|l&T#xY=&O^SIeDbY=Pz7CTyMmGhqeuU6Ak5E z{Wgr5^7h0A4DKR3XsCJn21aHVCucw4lfS}m=@q%YVqQ7lI3%^0Q z<}EeLu2nKYfXZ|&LhXZs2fU0(4?)>Bb~t`Jon-ZBh=8f LFVMRlu6zFi4Wn-W diff --git a/src/main/java/seedu/ui/ExceptionTextUi.class b/src/main/java/seedu/ui/ExceptionTextUi.class deleted file mode 100644 index 2451d9b9bf486b724fbaa35c1fe707bad4eff29b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11439 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 diff --git a/src/main/java/seedu/ui/UserInputTextUi.class b/src/main/java/seedu/ui/UserInputTextUi.class deleted file mode 100644 index 2bb7a6ba35c51eb5521d67c2d58091263b4689f8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 993 zcmZ`&T~8B16g|@xwq2G2ZK+s5p(3^gS-(*sz7$Q2MIQ`%){gi`Zij(v+x5P2i(!0QDj7Ush?mL- z42i1S6bw@}sl>~$(-7VsZ?wr`wM4M*3-7t=h5}&)Xp{ATJMVXS zH;OWFlV}HlRaYHKufqfBDu(2?(;g6;bvN`J@l0x(+>m2W90&VyL+5N^1{n)en6|Ki zyagM12DWbD7H%`Z!X4Z-aL>YhJYbmlPp5%R3lH%~13hM#^Mz=Jb|~$0Yz)&;Y$WPc z<48Cpb;Q)yN!cq(PM3%ZM$$WEaabNA3~uVu~mLU{qRJ$%^ix| zxzO*z_>qfY$^VIYdhCdSvGc05wt4c3Vc{?I$lE{w diff --git a/src/main/java/seedu/ui/ViewMessageFormatterUi.class b/src/main/java/seedu/ui/ViewMessageFormatterUi.class deleted file mode 100644 index 52116661c0cbab68a1230d927e86be5803d6b448..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2473 zcmaJ@ZBr9h6n<_9NnBQe2!h3zXb}S{(bl(ur~wj;Cb5-(udQ8@+qjbK(#;0Pf704M(x0;U;dy za9fS(I43en%Elpl=}sIWU%DH|fG_3a2rFp0G{R8Wb2QZWNa3c0c<(o6F=^ z*Hx^Dz~O15(U6X7GPhN;VQkf8h3P&Kh}^Vx1>{2 z&H|&mrhHX2>N0CPb;EU~BXBO6Z%A2brpmVE8f7=dt*dcyHviJtHBvRhs;1Um$F!=8 z+`~HOwhP8ii}A2xTr=Gl&8+}uTv;=9!>k32+fAn|v!*(rsZHiskd1~>?VizwIj>Ga$9Y_c z;)#x@cqRZHU#oFs*|yz=>lix)>AtWljo}EsiQ&19Z^1QNcosuhM@5ZN$9HP1>Ug0> zQ^!SI(($>1s|v0txTfH;f;pTMnC#v|x?KPn$FX^NC;h8ynyLPYNAXg}Hfl_>OLBkf zr7XJw<9+X4AX=5KDiVRQWZ%;}KnMTMHPm4VOlZEkkVqt|UNOv$s7-eln%1tpEn9u%pHG%eXFIQ>XtJU6w!Pil;f`~bB^@t}B*PEELu+yPWp~H0 zDmB@d_7^Vpo^8PL!NSt(9ofhIX~5qvm=7L=7R8EDtF4=^T#RB@;7rf{`sF5Y;{W|{ ziVyWszIid?Cz#^XdyHBL$ElwP=qITs0{SWHrvv(@)Taab8R|0u{VerlK%X6%R2|1y z2N;vxPMoK9oFf|^gLCg8-ck@q5hI>4N@q4PW#xLEqjDXddxy|ph{Ol>l(a`v$Xj%X zf3bj3L=lIEF?>dC074@RUx60OQj2AbYr`Fu@ID5CkEtd}b(B<7K`K5TeW)TGs>nW9 z^-!IpF+r-+K`OpTeW+p`s@OhL@1dF@)mc)_2C4YM^`X)_RN6jI$i@1*xv%ix$<7yrU5BV{__fBLDC3koV5N`3BMOPY4hEiZNB6eyO$VQ$gu+#-?M<0sVC^RLffi`YaZr2yys!zU+V=6q5uE@ From a971169bc91abc57b568abd234cd380a64bcdfc9 Mon Sep 17 00:00:00 2001 From: lezong Date: Wed, 3 Nov 2021 12:02:19 +0800 Subject: [PATCH 601/756] Change ExceptionTextUi messages to be consistent with UG --- src/main/java/seedu/ui/ExceptionTextUi.java | 12 +++++++----- src/main/java/seedu/ui/TextUi.java | 4 +++- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index b0073b89f9..0439d681b4 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -131,7 +131,8 @@ public static void missingDetailMessage() { public static void missingIndexEditMessage() { String message = "There seems to be missing or invalid index in your request.\n" + "Please enter command in the following way:\n" - + " edit -n -g -e -te -l -tw \n" + + " edit {-n } {-g } {-e } {-te } {-l } " + + "{-tw }\n" + " example : edit 0 -n George -g procoder -te george123\n" + "NOTE : At least one flag and description required\n" + " Order of parameters do not matter except for INDEX\n" @@ -143,7 +144,8 @@ public static void missingIndexEditMessage() { public static void missingArgEditMessage() { String message = "There seems to be missing parameters in your request.\n" + "Please enter command in this format:\n" - + " edit -n -g -e -te -l -tw \n" + + " edit {-n } {-g } {-e } {-te } {-l } " + + "{-tw }\n" + " example : edit 0 -n George -g procoder -te george123\n" + "NOTE : At least one flag and description required\n" + " Order of parameters do not matter except for INDEX\n" @@ -155,7 +157,7 @@ public static void missingArgEditMessage() { public static void missingArgAddMessage() { String message = "There seems to be missing parameters in your request.\n" + "Please enter command in this format:\n" - + " add -n -g -e -te -l -tw \n" + + " add -n {-g } {-e } {-te } {-l } {-tw }\n" + " example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe\n" + "NOTE : At least name and description required\n" + " Order of parameters do not matter"; @@ -166,7 +168,7 @@ public static void missingArgAddMessage() { public static void missingArgSearchMessage() { String message = "There seems to be missing parameters in your request.\n" + "Please enter command in this format:\n" - + " search \n" + + " search {FLAG} \n" + " example : search Ashraf\n" + " search -g revflash\n" + "NOTE : Flag is optional and only one can be specified"; @@ -177,7 +179,7 @@ public static void missingArgSearchMessage() { public static void missingIndexMessage() { String message = "There seems to be missing or invalid index in your request.\n" + "Please enter command in the following way:\n" - + " \n" + + " {REMOVE_DETAIL_FLAGS}\n" + "Where is rm or view"; printDoubleLineMessage(message); } diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 523d9b2ae4..9bea70ed80 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -269,7 +269,9 @@ public static void helpMessage() { + "view: Displays all details for index specified contact.\n" + " Parameter: INDEX\n" + " Note: Index starts from 0.\n" - + " Example: view 2\n\n" + + " \"me\" is used as INDEX for personal contact\n" + + " Examples: view 2\n" + + " view me\n\n" + "me: Displays all details for personal contact.\n" + " Example: me\n\n" + "rm: Deletes the index specified contact.\n" From 7920ffe65c537d0faf5b77fa41d226561639c6a6 Mon Sep 17 00:00:00 2001 From: lezong Date: Wed, 3 Nov 2021 12:08:34 +0800 Subject: [PATCH 602/756] Change EXPECTED.TXT --- text-ui-test/ACTUAL.TXT | 32 ++++++++++++++++---------------- text-ui-test/EXPECTED-UNIX.TXT | 32 ++++++++++++++++---------------- text-ui-test/EXPECTED.TXT | 32 ++++++++++++++++---------------- 3 files changed, 48 insertions(+), 48 deletions(-) diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index ca49ea8ccb..c800d82d9f 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -98,7 +98,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. Please enter command in this format: - edit -n -g -e -te -l -tw + edit {-n } {-g } {-e } {-te } {-l } {-tw } example : edit 0 -n George -g procoder -te george123 NOTE : At least one flag and description required Order of parameters do not matter except for INDEX @@ -133,7 +133,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing or invalid index in your request. Please enter command in the following way: - + {REMOVE_DETAIL_FLAGS} Where is rm or view ____________________________________________________________ @@ -224,7 +224,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. Please enter command in this format: - add -n -g -e -te -l -tw + add -n {-g } {-e } {-te } {-l } {-tw } example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe NOTE : At least name and description required Order of parameters do not matter @@ -233,7 +233,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing or invalid index in your request. Please enter command in the following way: - + {REMOVE_DETAIL_FLAGS} Where is rm or view ____________________________________________________________ @@ -248,7 +248,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. Please enter command in this format: - add -n -g -e -te -l -tw + add -n {-g } {-e } {-te } {-l } {-tw } example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe NOTE : At least name and description required Order of parameters do not matter @@ -297,7 +297,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. Please enter command in this format: - add -n -g -e -te -l -tw + add -n {-g } {-e } {-te } {-l } {-tw } example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe NOTE : At least name and description required Order of parameters do not matter @@ -377,14 +377,14 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing or invalid index in your request. Please enter command in the following way: - + {REMOVE_DETAIL_FLAGS} Where is rm or view ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. Please enter command in this format: - add -n -g -e -te -l -tw + add -n {-g } {-e } {-te } {-l } {-tw } example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe NOTE : At least name and description required Order of parameters do not matter @@ -443,7 +443,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. Please enter command in this format: - add -n -g -e -te -l -tw + add -n {-g } {-e } {-te } {-l } {-tw } example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe NOTE : At least name and description required Order of parameters do not matter @@ -562,7 +562,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. Please enter command in this format: - search + search {FLAG} example : search Ashraf search -g revflash NOTE : Flag is optional and only one can be specified @@ -571,7 +571,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. Please enter command in this format: - search + search {FLAG} example : search Ashraf search -g revflash NOTE : Flag is optional and only one can be specified @@ -580,7 +580,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. Please enter command in this format: - search + search {FLAG} example : search Ashraf search -g revflash NOTE : Flag is optional and only one can be specified @@ -789,14 +789,14 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing or invalid index in your request. Please enter command in the following way: - + {REMOVE_DETAIL_FLAGS} Where is rm or view ____________________________________________________________ ____________________________________________________________ There seems to be missing or invalid index in your request. Please enter command in the following way: - + {REMOVE_DETAIL_FLAGS} Where is rm or view ____________________________________________________________ @@ -810,7 +810,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing or invalid index in your request. Please enter command in the following way: - edit -n -g -e -te -l -tw + edit {-n } {-g } {-e } {-te } {-l } {-tw } example : edit 0 -n George -g procoder -te george123 NOTE : At least one flag and description required Order of parameters do not matter except for INDEX @@ -820,7 +820,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing or invalid index in your request. Please enter command in the following way: - edit -n -g -e -te -l -tw + edit {-n } {-g } {-e } {-te } {-l } {-tw } example : edit 0 -n George -g procoder -te george123 NOTE : At least one flag and description required Order of parameters do not matter except for INDEX diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index ca49ea8ccb..c800d82d9f 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -98,7 +98,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. Please enter command in this format: - edit -n -g -e -te -l -tw + edit {-n } {-g } {-e } {-te } {-l } {-tw } example : edit 0 -n George -g procoder -te george123 NOTE : At least one flag and description required Order of parameters do not matter except for INDEX @@ -133,7 +133,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing or invalid index in your request. Please enter command in the following way: - + {REMOVE_DETAIL_FLAGS} Where is rm or view ____________________________________________________________ @@ -224,7 +224,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. Please enter command in this format: - add -n -g -e -te -l -tw + add -n {-g } {-e } {-te } {-l } {-tw } example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe NOTE : At least name and description required Order of parameters do not matter @@ -233,7 +233,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing or invalid index in your request. Please enter command in the following way: - + {REMOVE_DETAIL_FLAGS} Where is rm or view ____________________________________________________________ @@ -248,7 +248,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. Please enter command in this format: - add -n -g -e -te -l -tw + add -n {-g } {-e } {-te } {-l } {-tw } example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe NOTE : At least name and description required Order of parameters do not matter @@ -297,7 +297,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. Please enter command in this format: - add -n -g -e -te -l -tw + add -n {-g } {-e } {-te } {-l } {-tw } example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe NOTE : At least name and description required Order of parameters do not matter @@ -377,14 +377,14 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing or invalid index in your request. Please enter command in the following way: - + {REMOVE_DETAIL_FLAGS} Where is rm or view ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. Please enter command in this format: - add -n -g -e -te -l -tw + add -n {-g } {-e } {-te } {-l } {-tw } example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe NOTE : At least name and description required Order of parameters do not matter @@ -443,7 +443,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. Please enter command in this format: - add -n -g -e -te -l -tw + add -n {-g } {-e } {-te } {-l } {-tw } example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe NOTE : At least name and description required Order of parameters do not matter @@ -562,7 +562,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. Please enter command in this format: - search + search {FLAG} example : search Ashraf search -g revflash NOTE : Flag is optional and only one can be specified @@ -571,7 +571,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. Please enter command in this format: - search + search {FLAG} example : search Ashraf search -g revflash NOTE : Flag is optional and only one can be specified @@ -580,7 +580,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. Please enter command in this format: - search + search {FLAG} example : search Ashraf search -g revflash NOTE : Flag is optional and only one can be specified @@ -789,14 +789,14 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing or invalid index in your request. Please enter command in the following way: - + {REMOVE_DETAIL_FLAGS} Where is rm or view ____________________________________________________________ ____________________________________________________________ There seems to be missing or invalid index in your request. Please enter command in the following way: - + {REMOVE_DETAIL_FLAGS} Where is rm or view ____________________________________________________________ @@ -810,7 +810,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing or invalid index in your request. Please enter command in the following way: - edit -n -g -e -te -l -tw + edit {-n } {-g } {-e } {-te } {-l } {-tw } example : edit 0 -n George -g procoder -te george123 NOTE : At least one flag and description required Order of parameters do not matter except for INDEX @@ -820,7 +820,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing or invalid index in your request. Please enter command in the following way: - edit -n -g -e -te -l -tw + edit {-n } {-g } {-e } {-te } {-l } {-tw } example : edit 0 -n George -g procoder -te george123 NOTE : At least one flag and description required Order of parameters do not matter except for INDEX diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index ca49ea8ccb..c800d82d9f 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -98,7 +98,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. Please enter command in this format: - edit -n -g -e -te -l -tw + edit {-n } {-g } {-e } {-te } {-l } {-tw } example : edit 0 -n George -g procoder -te george123 NOTE : At least one flag and description required Order of parameters do not matter except for INDEX @@ -133,7 +133,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing or invalid index in your request. Please enter command in the following way: - + {REMOVE_DETAIL_FLAGS} Where is rm or view ____________________________________________________________ @@ -224,7 +224,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. Please enter command in this format: - add -n -g -e -te -l -tw + add -n {-g } {-e } {-te } {-l } {-tw } example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe NOTE : At least name and description required Order of parameters do not matter @@ -233,7 +233,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing or invalid index in your request. Please enter command in the following way: - + {REMOVE_DETAIL_FLAGS} Where is rm or view ____________________________________________________________ @@ -248,7 +248,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. Please enter command in this format: - add -n -g -e -te -l -tw + add -n {-g } {-e } {-te } {-l } {-tw } example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe NOTE : At least name and description required Order of parameters do not matter @@ -297,7 +297,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. Please enter command in this format: - add -n -g -e -te -l -tw + add -n {-g } {-e } {-te } {-l } {-tw } example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe NOTE : At least name and description required Order of parameters do not matter @@ -377,14 +377,14 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing or invalid index in your request. Please enter command in the following way: - + {REMOVE_DETAIL_FLAGS} Where is rm or view ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. Please enter command in this format: - add -n -g -e -te -l -tw + add -n {-g } {-e } {-te } {-l } {-tw } example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe NOTE : At least name and description required Order of parameters do not matter @@ -443,7 +443,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. Please enter command in this format: - add -n -g -e -te -l -tw + add -n {-g } {-e } {-te } {-l } {-tw } example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe NOTE : At least name and description required Order of parameters do not matter @@ -562,7 +562,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. Please enter command in this format: - search + search {FLAG} example : search Ashraf search -g revflash NOTE : Flag is optional and only one can be specified @@ -571,7 +571,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. Please enter command in this format: - search + search {FLAG} example : search Ashraf search -g revflash NOTE : Flag is optional and only one can be specified @@ -580,7 +580,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. Please enter command in this format: - search + search {FLAG} example : search Ashraf search -g revflash NOTE : Flag is optional and only one can be specified @@ -789,14 +789,14 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing or invalid index in your request. Please enter command in the following way: - + {REMOVE_DETAIL_FLAGS} Where is rm or view ____________________________________________________________ ____________________________________________________________ There seems to be missing or invalid index in your request. Please enter command in the following way: - + {REMOVE_DETAIL_FLAGS} Where is rm or view ____________________________________________________________ @@ -810,7 +810,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing or invalid index in your request. Please enter command in the following way: - edit -n -g -e -te -l -tw + edit {-n } {-g } {-e } {-te } {-l } {-tw } example : edit 0 -n George -g procoder -te george123 NOTE : At least one flag and description required Order of parameters do not matter except for INDEX @@ -820,7 +820,7 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing or invalid index in your request. Please enter command in the following way: - edit -n -g -e -te -l -tw + edit {-n } {-g } {-e } {-te } {-l } {-tw } example : edit 0 -n George -g procoder -te george123 NOTE : At least one flag and description required Order of parameters do not matter except for INDEX From 28c88f01d180bdb396b0ac68648370fe69fdc9a1 Mon Sep 17 00:00:00 2001 From: lezong Date: Wed, 3 Nov 2021 12:18:25 +0800 Subject: [PATCH 603/756] Minor edits --- src/main/java/seedu/parser/MainParser.java | 1 - src/main/java/seedu/ui/ExceptionTextUi.java | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 73482b509c..f625ffd873 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -29,7 +29,6 @@ import seedu.exception.MissingDetailException; import seedu.exception.MissingIndexException; -import java.lang.reflect.Array; import static seedu.parser.ContactParser.NUMBER_OF_FIELDS; diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index 0439d681b4..6dd263df28 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -159,7 +159,7 @@ public static void missingArgAddMessage() { + "Please enter command in this format:\n" + " add -n {-g } {-e } {-te } {-l } {-tw }\n" + " example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe\n" - + "NOTE : At least name and description required\n" + + "NOTE : At least NAME required\n" + " Order of parameters do not matter"; printDoubleLineMessage(message); } From 3e511e4f965bf1f3b5d47386a9dcfe4fc70ce72c Mon Sep 17 00:00:00 2001 From: lezong Date: Wed, 3 Nov 2021 12:21:29 +0800 Subject: [PATCH 604/756] Update EXPECTED.TXT --- text-ui-test/ACTUAL.TXT | 10 +++++----- text-ui-test/EXPECTED-UNIX.TXT | 10 +++++----- text-ui-test/EXPECTED.TXT | 10 +++++----- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index c800d82d9f..772c26cace 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -226,7 +226,7 @@ There seems to be missing parameters in your request. Please enter command in this format: add -n {-g } {-e } {-te } {-l } {-tw } example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe -NOTE : At least name and description required +NOTE : At least NAME required Order of parameters do not matter ____________________________________________________________ @@ -250,7 +250,7 @@ There seems to be missing parameters in your request. Please enter command in this format: add -n {-g } {-e } {-te } {-l } {-tw } example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe -NOTE : At least name and description required +NOTE : At least NAME required Order of parameters do not matter ____________________________________________________________ @@ -299,7 +299,7 @@ There seems to be missing parameters in your request. Please enter command in this format: add -n {-g } {-e } {-te } {-l } {-tw } example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe -NOTE : At least name and description required +NOTE : At least NAME required Order of parameters do not matter ____________________________________________________________ @@ -386,7 +386,7 @@ There seems to be missing parameters in your request. Please enter command in this format: add -n {-g } {-e } {-te } {-l } {-tw } example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe -NOTE : At least name and description required +NOTE : At least NAME required Order of parameters do not matter ____________________________________________________________ @@ -445,7 +445,7 @@ There seems to be missing parameters in your request. Please enter command in this format: add -n {-g } {-e } {-te } {-l } {-tw } example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe -NOTE : At least name and description required +NOTE : At least NAME required Order of parameters do not matter ____________________________________________________________ diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index c800d82d9f..772c26cace 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -226,7 +226,7 @@ There seems to be missing parameters in your request. Please enter command in this format: add -n {-g } {-e } {-te } {-l } {-tw } example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe -NOTE : At least name and description required +NOTE : At least NAME required Order of parameters do not matter ____________________________________________________________ @@ -250,7 +250,7 @@ There seems to be missing parameters in your request. Please enter command in this format: add -n {-g } {-e } {-te } {-l } {-tw } example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe -NOTE : At least name and description required +NOTE : At least NAME required Order of parameters do not matter ____________________________________________________________ @@ -299,7 +299,7 @@ There seems to be missing parameters in your request. Please enter command in this format: add -n {-g } {-e } {-te } {-l } {-tw } example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe -NOTE : At least name and description required +NOTE : At least NAME required Order of parameters do not matter ____________________________________________________________ @@ -386,7 +386,7 @@ There seems to be missing parameters in your request. Please enter command in this format: add -n {-g } {-e } {-te } {-l } {-tw } example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe -NOTE : At least name and description required +NOTE : At least NAME required Order of parameters do not matter ____________________________________________________________ @@ -445,7 +445,7 @@ There seems to be missing parameters in your request. Please enter command in this format: add -n {-g } {-e } {-te } {-l } {-tw } example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe -NOTE : At least name and description required +NOTE : At least NAME required Order of parameters do not matter ____________________________________________________________ diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index c800d82d9f..772c26cace 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -226,7 +226,7 @@ There seems to be missing parameters in your request. Please enter command in this format: add -n {-g } {-e } {-te } {-l } {-tw } example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe -NOTE : At least name and description required +NOTE : At least NAME required Order of parameters do not matter ____________________________________________________________ @@ -250,7 +250,7 @@ There seems to be missing parameters in your request. Please enter command in this format: add -n {-g } {-e } {-te } {-l } {-tw } example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe -NOTE : At least name and description required +NOTE : At least NAME required Order of parameters do not matter ____________________________________________________________ @@ -299,7 +299,7 @@ There seems to be missing parameters in your request. Please enter command in this format: add -n {-g } {-e } {-te } {-l } {-tw } example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe -NOTE : At least name and description required +NOTE : At least NAME required Order of parameters do not matter ____________________________________________________________ @@ -386,7 +386,7 @@ There seems to be missing parameters in your request. Please enter command in this format: add -n {-g } {-e } {-te } {-l } {-tw } example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe -NOTE : At least name and description required +NOTE : At least NAME required Order of parameters do not matter ____________________________________________________________ @@ -445,7 +445,7 @@ There seems to be missing parameters in your request. Please enter command in this format: add -n {-g } {-e } {-te } {-l } {-tw } example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe -NOTE : At least name and description required +NOTE : At least NAME required Order of parameters do not matter ____________________________________________________________ From 71dd867e2276ec762d4402fa0ff40a15aa81c9f2 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 3 Nov 2021 22:29:44 +0800 Subject: [PATCH 605/756] Update exceptions --- .../java/seedu/command/FailedCommand.java | 6 +++ .../MissingIndexDeleteException.java | 4 ++ .../exception/MissingIndexViewException.java | 4 ++ .../java/seedu/parser/FailedCommandType.java | 2 +- src/main/java/seedu/parser/MainParser.java | 2 +- src/main/java/seedu/parser/RegexParser.java | 2 +- src/main/java/seedu/ui/ExceptionTextUi.java | 44 +++++++++++++++++++ 7 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 src/main/java/seedu/exception/MissingIndexDeleteException.java create mode 100644 src/main/java/seedu/exception/MissingIndexViewException.java diff --git a/src/main/java/seedu/command/FailedCommand.java b/src/main/java/seedu/command/FailedCommand.java index fc9f818747..74fc6933a3 100644 --- a/src/main/java/seedu/command/FailedCommand.java +++ b/src/main/java/seedu/command/FailedCommand.java @@ -95,6 +95,12 @@ private void missingUserInputExecute() { case MISSING_INDEX: ExceptionTextUi.missingIndexMessage(); break; + case MISSING_INDEX_VIEW: + ExceptionTextUi.missingIndexViewMessage(contactList.getListSize()); + break; + case MISSING_INDEX_DELETE: + ExceptionTextUi.missingIndexDeleteMessage(contactList.getListSize()); + break; default: return; } diff --git a/src/main/java/seedu/exception/MissingIndexDeleteException.java b/src/main/java/seedu/exception/MissingIndexDeleteException.java new file mode 100644 index 0000000000..683cae65e2 --- /dev/null +++ b/src/main/java/seedu/exception/MissingIndexDeleteException.java @@ -0,0 +1,4 @@ +package seedu.exception; + +public class MissingIndexDeleteException extends Exception { +} diff --git a/src/main/java/seedu/exception/MissingIndexViewException.java b/src/main/java/seedu/exception/MissingIndexViewException.java new file mode 100644 index 0000000000..de5f5a0ae5 --- /dev/null +++ b/src/main/java/seedu/exception/MissingIndexViewException.java @@ -0,0 +1,4 @@ +package seedu.exception; + +public class MissingIndexViewException extends Exception { +} diff --git a/src/main/java/seedu/parser/FailedCommandType.java b/src/main/java/seedu/parser/FailedCommandType.java index 91c045d20f..08660089e6 100644 --- a/src/main/java/seedu/parser/FailedCommandType.java +++ b/src/main/java/seedu/parser/FailedCommandType.java @@ -2,7 +2,7 @@ public enum FailedCommandType { GENERAL, INVALID_FLAG, MISSING_ARGS_EDIT, MISSING_ARGS_ADD, MISSING_ARGS_SEARCH, - MISSING_DETAIL, MISSING_INDEX, INVALID_NUM, + MISSING_DETAIL, MISSING_INDEX, MISSING_INDEX_VIEW, MISSING_INDEX_DELETE, INVALID_NUM, INVALID_FORMAT, NUM_OUT_OF_BOUND, NUM_OUT_OF_BOUND_EDIT, INVALID_INDEX, MISSING_NAME, FORBIDDEN_DETAIL, INVALID_NAME, INVALID_GITHUB_USERNAME, INVALID_LINKEDIN, INVALID_TELEGRAM, INVALID_MAIL, INVALID_TWITTER, INVALID_DELETE, diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index c71e8c81c2..9abdb10b98 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -241,7 +241,7 @@ private Command parseViewContact(String userInput) { } catch (NumberFormatException e) { return new FailedCommand(FailedCommandType.NUM_OUT_OF_BOUND); } catch (MissingIndexException e) { - return new FailedCommand(FailedCommandType.MISSING_INDEX); + return new FailedCommand(FailedCommandType.MISSING_INDEX_VIEW); } } diff --git a/src/main/java/seedu/parser/RegexParser.java b/src/main/java/seedu/parser/RegexParser.java index 3cfffdb321..373c09601e 100644 --- a/src/main/java/seedu/parser/RegexParser.java +++ b/src/main/java/seedu/parser/RegexParser.java @@ -62,7 +62,7 @@ protected void checkEmailRegex(String detailToParse) throws InvalidEmailExceptio + "(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|" + "(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$"; if (!detailToParse.matches(emailRegex)) { - LOGGER.log(Level.INFO, "Regex check for Email id failed"); + LOGGER.log(Level.FINE, "Regex check for Email id failed"); throw new InvalidEmailException(); } } diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index fcab737b86..aaca95f424 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -171,6 +171,50 @@ public static void missingIndexMessage() { printDoubleLineMessage(message); } + //@@author mayankp291 + public static void missingIndexViewMessage(int ListSize) { + String message; + if (ListSize == 0) { + message = "There seems to be missing index in your request.\n" + + "Please enter command in the following way:\n" + + " view \n" + + "Enter as \"me\" to view personal contact"; + } else if (ListSize == 1) { + message = "There seems to be missing index in your request.\n" + + "Please enter command in the following way:\n" + + " view \n" + + "Enter as 0 or \"me\" (personal contact)"; + } else { + message = "There seems to be missing index in your request.\n" + + "Please enter command in the following way:\n" + + " view \n" + + "Enter between 0 and " + (ListSize - 1) + " or \"me\" (personal contact)"; + } + printDoubleLineMessage(message); + } + + //@@author mayankp291 + public static void missingIndexDeleteMessage(int ListSize) { + String message; + if (ListSize == 0) { + message = "There seems to be missing index in your request.\n" + + "Please enter command in the following way:\n" + + " rm \n" + + "Enter as \"me\" to view personal contact"; + } else if (ListSize == 1) { + message = "There seems to be missing index in your request.\n" + + "Please enter command in the following way:\n" + + " view \n" + + "Enter as 0 or \"me\" (personal contact)"; + } else { + message = "There seems to be missing index in your request.\n" + + "Please enter command in the following way:\n" + + " view \n" + + "Enter between 0 and " + (ListSize - 1) + " or \"me\" (personal contact)"; + } + printDoubleLineMessage(message); + } + //@@author public static void invalidNumMessage() { String message = "That does not seem to be a number.\n" + "Please provide a number instead."; From eb8775c33632f9d53896b513757139bbd4497817 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Wed, 3 Nov 2021 23:19:07 +0800 Subject: [PATCH 606/756] Refactor sequence of code for author --- .../java/seedu/command/EditContactCommand.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index c3163e3d12..2b95c0529f 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -89,6 +89,14 @@ && hasDuplicateField(postEditContactDetails[j], currentContactDetails[j])) { return false; } + private boolean hasDuplicateField(String input, String saved) { + return cleanString(saved).equals(cleanString(input)); + } + + private String cleanString(String input) { + return input.replace(" ", "").toLowerCase(); + } + //@@author ng-andre private boolean[] hasEditedFields(String[] contactDetails) { boolean[] hasEditedField = new boolean[NUMBER_OF_FIELDS]; @@ -98,14 +106,6 @@ private boolean[] hasEditedFields(String[] contactDetails) { return hasEditedField; } - private boolean hasDuplicateField(String input, String saved) { - return cleanString(saved).equals(cleanString(input)); - } - - private String cleanString(String input) { - return input.replace(" ", "").toLowerCase(); - } - //@@author ng-andre private Contact duplicateContact(Contact contact) { String name = contact.getName(); From 79cb9e55b67da316b71c1130558cd793daa04d3c Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Wed, 3 Nov 2021 23:19:46 +0800 Subject: [PATCH 607/756] Refactor view UI output for consistency --- src/main/java/seedu/ui/TextUi.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 9bea70ed80..e82d6c5d85 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -151,7 +151,7 @@ public static String formatContactFields(Contact addedContact) { public static void viewContactMessage(Contact viewingContact, int index) { String viewName = ViewMessageFormatterUi.viewNameFormatter(viewingContact); - String message = index + ". " + viewName + formatContactFields(viewingContact); + String message = "Name: " + viewName + formatContactFields(viewingContact); printDoubleLineMessage(message); } @@ -299,11 +299,11 @@ public static void confirmDuplicateMessage(ArrayList duplicatedIndex, String message; if (type.equals("add")) { message = "One of your saved contacts has a duplicate field:\n" - + "\n" + duplicatedIndex.get(0) + ". " + currentContact.getName() + + "\n" + duplicatedIndex.get(0) + ".\n" + "Name: " + currentContact.getName() + formatContactFields(currentContact) + "\n\nDo you still want to add the contact? (y/n)\n"; } else { message = "One of your saved contacts has a duplicate field:\n" - + "\n" + duplicatedIndex.get(0) + ". " + currentContact.getName() + + "\n" + duplicatedIndex.get(0) + ".\n" + "Name: " + currentContact.getName() + formatContactFields(currentContact) + "\n\nDo you still want to edit the contact? (y/n)\n"; } printDoubleLineMessage(message); @@ -324,7 +324,7 @@ public static void confirmDuplicateMessage(ArrayList duplicatedIndex, public static void duplicatedContactsMessage(Contact viewingContact, int index) { String viewName = ViewMessageFormatterUi.viewNameFormatter(viewingContact); - String message = index + ". " + viewName + formatContactFields(viewingContact); + String message = index + ".\n" + "Name: " + viewName + formatContactFields(viewingContact); System.out.println(message + "\n"); } From 0af56b431032a306c77782680e5e8a5c717955ee Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Wed, 3 Nov 2021 23:20:21 +0800 Subject: [PATCH 608/756] Update view example outputs on UG --- docs/UserGuide.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 513ca580f3..b95ec3af2d 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -205,10 +205,10 @@ Expected outcome of usage: ``` view 0 ____________________________________________________________ -0. Alex Lee - Github: github.com/alexlee - Email: alex.lee@contech.sg - Telegram: t.me/alexl33 +Name: Alex Lee +Github: github.com/alexlee +Email: alex.lee@contech.sg +Telegram: t.me/alexl33 ____________________________________________________________ ``` * View personal contact: @@ -562,7 +562,7 @@ List all valid commands and usage | `help` | `help` Add a new contact | `add -n {-g } {-e } {-te } {-l } {-tw }` | `add -n Marcus`
`add -n John Doe -g johndoecoder -e john@email.com -te johndoe`
List all contacts | `ls` | `ls` View a contact | `view ` | `view 2` -View personal contact | `view me` | `view me` +View personal contact | `view me` or `me` | `view me` or `me` Edit a contact | `edit {-n } {-g } {-e } {-te } {-l } {-tw }` | `edit 1 -e john.doe@email.com`
`edit 0 -n Tan -g tanned -te tantan`
Edit personal contact | `edit me {-n } {-g } {-e } {-te } {-l } {-tw }` |`edit me -e bobby@email.com`
`edit me -n Tan -g tanned -te tantan`
Delete contact fields | `rm {-g} {-l} {-te} {-tw} {-e}` | `rm 3 -g -te -l -e` From 7af4d1ed6680ba4ae7940c31d80f4823fd609c6d Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Wed, 3 Nov 2021 23:21:00 +0800 Subject: [PATCH 609/756] Update Search output on UG --- docs/UserGuide.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index b95ec3af2d..6331dab625 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -398,17 +398,17 @@ Expected outcome of usage: ``` search -g lee ____________________________________________________________ -0. Alex Lee - Github: github.com/alexlee - Email: alex.lee@contech.sg - Telegram: t.me/alexl33 +Name: Alex Lee +Github: github.com/alexlee +Email: alex.lee@contech.sg +Telegram: t.me/alexl33 ____________________________________________________________ ____________________________________________________________ -1. John Lee - Github: github.com/johnlee - Email: john.lee@contech.sg - Telegram: t.me/johnlee123 +Name: John Lee +Github: github.com/johnlee +Email: john.lee@contech.sg +Telegram: t.me/johnlee123 ____________________________________________________________ ``` From e54fbfb9fb2fdcc68f25cfe8015e5df6a1e1eb33 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Wed, 3 Nov 2021 23:21:14 +0800 Subject: [PATCH 610/756] Update Edit output on UG --- docs/UserGuide.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 6331dab625..15cc1214c8 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -362,10 +362,11 @@ Expected outcome of usage: ``` edit 0 -n John Lee -g johnlee -te johnlee123 -e john.lee@contech.sg ____________________________________________________________ -0. John Lee - Github: github.com/johnlee - Email: john.lee@contech.sg - Telegram: t.me/johnlee123 +ConTech has edited the specified contact: +Name: John Lee +Github: github.com/johnlee +Email: john.lee@contech.sg +Telegram: t.me/johnlee123 ____________________________________________________________ ``` From 735426e2d4b9dba3b54a819ac90dbc675631f57d Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Wed, 3 Nov 2021 23:25:49 +0800 Subject: [PATCH 611/756] Update text-ui-test for new UI --- text-ui-test/ACTUAL.TXT | 33 +++++++++++++++++++-------------- text-ui-test/EXPECTED-UNIX.TXT | 33 +++++++++++++++++++-------------- text-ui-test/EXPECTED.TXT | 33 +++++++++++++++++++-------------- 3 files changed, 57 insertions(+), 42 deletions(-) diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index 772c26cace..e4d727ecc6 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -189,7 +189,8 @@ ____________________________________________________________ ____________________________________________________________ One of your saved contacts has a duplicate field: -3. ng andre +3. +Name: ng andre Github: github.com/ng-andre Do you still want to add the contact? (y/n) @@ -217,7 +218,7 @@ ____________________________________________________________ ____________________________________________________________ ____________________________________________________________ -1. ashraf +Name: ashraf Github: github.com/ashraf ____________________________________________________________ @@ -268,7 +269,7 @@ ____________________________________________________________ ____________________________________________________________ ____________________________________________________________ -3. lezong +Name: lezong Github: github.com/lezongmun ____________________________________________________________ @@ -304,7 +305,7 @@ NOTE : At least NAME required ____________________________________________________________ ____________________________________________________________ -2. mayank +Name: mayank Github: github.com/mayankp123 ____________________________________________________________ @@ -436,7 +437,7 @@ You now have 6 contact(s). ____________________________________________________________ ____________________________________________________________ -0. asjoda sadfsd +Name: asjoda sadfsd Telegram: t.me/_123adad ____________________________________________________________ @@ -457,7 +458,8 @@ add -n lezong mun -g lezaimun ____________________________________________________________ One of your saved contacts has a duplicate field: -2. lezongmun +2. +Name: lezongmun Github: github.com/lezong Do you still want to add the contact? (y/n) @@ -512,7 +514,8 @@ ____________________________________________________________ ____________________________________________________________ One of your saved contacts has a duplicate field: -0. asjoda sadfsd +0. +Name: asjoda sadfsd Telegram: t.me/_123adad Do you still want to add the contact? (y/n) @@ -591,12 +594,12 @@ No search results found. ____________________________________________________________ ____________________________________________________________ -1. bory +Name: bory Github: github.com/marcus ____________________________________________________________ ____________________________________________________________ -5. lezongmun +Name: lezongmun Github: github.com/lezong ____________________________________________________________ @@ -638,7 +641,8 @@ ____________________________________________________________ ____________________________________________________________ One of your saved contacts has a duplicate field: -0. ashraf +0. +Name: ashraf Github: github.com/ashrafjfr Do you still want to add the contact? (y/n) @@ -656,7 +660,8 @@ ____________________________________________________________ ____________________________________________________________ One of your saved contacts has a duplicate field: -1. ashraf +1. +Name: ashraf Telegram: t.me/ashrafjfr Do you still want to edit the contact? (y/n) @@ -679,7 +684,7 @@ Telegram: t.me/ashrafjfr ____________________________________________________________ ____________________________________________________________ -0. ashraf +Name: ashraf Github: github.com/ashrafjfr Email: ashrafjfr@gmail.com Telegram: t.me/ashrafjfr @@ -702,7 +707,7 @@ ConTech has successfully imported 3 lines ____________________________________________________________ ____________________________________________________________ -6. lezai +Name: lezai Github: github.com/lezongmun ____________________________________________________________ @@ -772,7 +777,7 @@ The specified fields for ashraf have been deleted. ____________________________________________________________ ____________________________________________________________ -0. ashraf +Name: ashraf Github: github.com/ashrafjfr ____________________________________________________________ diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index 772c26cace..e4d727ecc6 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -189,7 +189,8 @@ ____________________________________________________________ ____________________________________________________________ One of your saved contacts has a duplicate field: -3. ng andre +3. +Name: ng andre Github: github.com/ng-andre Do you still want to add the contact? (y/n) @@ -217,7 +218,7 @@ ____________________________________________________________ ____________________________________________________________ ____________________________________________________________ -1. ashraf +Name: ashraf Github: github.com/ashraf ____________________________________________________________ @@ -268,7 +269,7 @@ ____________________________________________________________ ____________________________________________________________ ____________________________________________________________ -3. lezong +Name: lezong Github: github.com/lezongmun ____________________________________________________________ @@ -304,7 +305,7 @@ NOTE : At least NAME required ____________________________________________________________ ____________________________________________________________ -2. mayank +Name: mayank Github: github.com/mayankp123 ____________________________________________________________ @@ -436,7 +437,7 @@ You now have 6 contact(s). ____________________________________________________________ ____________________________________________________________ -0. asjoda sadfsd +Name: asjoda sadfsd Telegram: t.me/_123adad ____________________________________________________________ @@ -457,7 +458,8 @@ add -n lezong mun -g lezaimun ____________________________________________________________ One of your saved contacts has a duplicate field: -2. lezongmun +2. +Name: lezongmun Github: github.com/lezong Do you still want to add the contact? (y/n) @@ -512,7 +514,8 @@ ____________________________________________________________ ____________________________________________________________ One of your saved contacts has a duplicate field: -0. asjoda sadfsd +0. +Name: asjoda sadfsd Telegram: t.me/_123adad Do you still want to add the contact? (y/n) @@ -591,12 +594,12 @@ No search results found. ____________________________________________________________ ____________________________________________________________ -1. bory +Name: bory Github: github.com/marcus ____________________________________________________________ ____________________________________________________________ -5. lezongmun +Name: lezongmun Github: github.com/lezong ____________________________________________________________ @@ -638,7 +641,8 @@ ____________________________________________________________ ____________________________________________________________ One of your saved contacts has a duplicate field: -0. ashraf +0. +Name: ashraf Github: github.com/ashrafjfr Do you still want to add the contact? (y/n) @@ -656,7 +660,8 @@ ____________________________________________________________ ____________________________________________________________ One of your saved contacts has a duplicate field: -1. ashraf +1. +Name: ashraf Telegram: t.me/ashrafjfr Do you still want to edit the contact? (y/n) @@ -679,7 +684,7 @@ Telegram: t.me/ashrafjfr ____________________________________________________________ ____________________________________________________________ -0. ashraf +Name: ashraf Github: github.com/ashrafjfr Email: ashrafjfr@gmail.com Telegram: t.me/ashrafjfr @@ -702,7 +707,7 @@ ConTech has successfully imported 3 lines ____________________________________________________________ ____________________________________________________________ -6. lezai +Name: lezai Github: github.com/lezongmun ____________________________________________________________ @@ -772,7 +777,7 @@ The specified fields for ashraf have been deleted. ____________________________________________________________ ____________________________________________________________ -0. ashraf +Name: ashraf Github: github.com/ashrafjfr ____________________________________________________________ diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 772c26cace..e4d727ecc6 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -189,7 +189,8 @@ ____________________________________________________________ ____________________________________________________________ One of your saved contacts has a duplicate field: -3. ng andre +3. +Name: ng andre Github: github.com/ng-andre Do you still want to add the contact? (y/n) @@ -217,7 +218,7 @@ ____________________________________________________________ ____________________________________________________________ ____________________________________________________________ -1. ashraf +Name: ashraf Github: github.com/ashraf ____________________________________________________________ @@ -268,7 +269,7 @@ ____________________________________________________________ ____________________________________________________________ ____________________________________________________________ -3. lezong +Name: lezong Github: github.com/lezongmun ____________________________________________________________ @@ -304,7 +305,7 @@ NOTE : At least NAME required ____________________________________________________________ ____________________________________________________________ -2. mayank +Name: mayank Github: github.com/mayankp123 ____________________________________________________________ @@ -436,7 +437,7 @@ You now have 6 contact(s). ____________________________________________________________ ____________________________________________________________ -0. asjoda sadfsd +Name: asjoda sadfsd Telegram: t.me/_123adad ____________________________________________________________ @@ -457,7 +458,8 @@ add -n lezong mun -g lezaimun ____________________________________________________________ One of your saved contacts has a duplicate field: -2. lezongmun +2. +Name: lezongmun Github: github.com/lezong Do you still want to add the contact? (y/n) @@ -512,7 +514,8 @@ ____________________________________________________________ ____________________________________________________________ One of your saved contacts has a duplicate field: -0. asjoda sadfsd +0. +Name: asjoda sadfsd Telegram: t.me/_123adad Do you still want to add the contact? (y/n) @@ -591,12 +594,12 @@ No search results found. ____________________________________________________________ ____________________________________________________________ -1. bory +Name: bory Github: github.com/marcus ____________________________________________________________ ____________________________________________________________ -5. lezongmun +Name: lezongmun Github: github.com/lezong ____________________________________________________________ @@ -638,7 +641,8 @@ ____________________________________________________________ ____________________________________________________________ One of your saved contacts has a duplicate field: -0. ashraf +0. +Name: ashraf Github: github.com/ashrafjfr Do you still want to add the contact? (y/n) @@ -656,7 +660,8 @@ ____________________________________________________________ ____________________________________________________________ One of your saved contacts has a duplicate field: -1. ashraf +1. +Name: ashraf Telegram: t.me/ashrafjfr Do you still want to edit the contact? (y/n) @@ -679,7 +684,7 @@ Telegram: t.me/ashrafjfr ____________________________________________________________ ____________________________________________________________ -0. ashraf +Name: ashraf Github: github.com/ashrafjfr Email: ashrafjfr@gmail.com Telegram: t.me/ashrafjfr @@ -702,7 +707,7 @@ ConTech has successfully imported 3 lines ____________________________________________________________ ____________________________________________________________ -6. lezai +Name: lezai Github: github.com/lezongmun ____________________________________________________________ @@ -772,7 +777,7 @@ The specified fields for ashraf have been deleted. ____________________________________________________________ ____________________________________________________________ -0. ashraf +Name: ashraf Github: github.com/ashrafjfr ____________________________________________________________ From a2c65a0afe6c57f3660681711de40493ba2d8ac6 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 4 Nov 2021 17:24:35 +0800 Subject: [PATCH 612/756] Create marcusbory PPP --- docs/team/marcusbory.md | 51 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 docs/team/marcusbory.md diff --git a/docs/team/marcusbory.md b/docs/team/marcusbory.md new file mode 100644 index 0000000000..6f6d3db24c --- /dev/null +++ b/docs/team/marcusbory.md @@ -0,0 +1,51 @@ +# marcusbory's Product Portfolio Page (PPP) + +## Overview +**ConTech** is a Command Line Interface (CLI) application for managing computing-related contacts. + +The project started on 3 September 2021, where our team brainstormed and came up with our target users and app +direction. We proceeded to create user stories related to our desired product and narrowed them down for each +iteration so that we were able to comfortably deliver our features. + +## Summary of contributions +### Code contributed +The code written by me (`marcusbory`) can be found [here](https://nus-cs2113-ay2122s1.github.io/tp-dashboard/?search=marcusbory&sort=groupTitle&sortWithin=title&timeframe=commit&mergegroup=&groupSelect=groupByRepos&breakdown=true&checkedFileTypes=docs~functional-code~test-code~other&since=2021-09-25&tabOpen=true&tabType=authorship&tabAuthor=marcusbory&tabRepo=AY2122S1-CS2113T-T09-1%2Ftp%5Bmaster%5D&authorshipIsMergeGroup=false&authorshipFileTypes=docs~functional-code~test-code~other&authorshipIsBinaryFileTypeChecked=false). +
+ +### Enhancements implemented +1. Application System Architecture + - Created an overall application system with inspiration from AB3 + - Allowed developers on the team to easily implement features and exception handling +2. `Add` feature, `Import` feature + - Features created for users to add and import contacts +3. Implementation of enumerations + - `DetailType`: Effective enumeration of details within each contact, providing each detail an inherent index to + be used across the entire application + - `FailedCommandType`: Usage of enumerations to better identify failed commands, improving parsing and error message processing +4. Application Storage System + - `Storage.java`: System to locate or create storage files + - `ContactsDecoder.java`: System for decoding contacts correctly from the storage file + - `ContactsEncoder.java`: System for storing contacts from the app to storage file +5. Parsers + - `ContactParser.java`: Abstract class which inherits RegexParser, created for `Add` and `Edit` feature + - `AddContactParser.java`: Parser which will attempt to create a syntactically valid `AddContactCommand`. + +### Contributions to UG +The link to the User Guide (UG) can be found [here](https://ay2122s1-cs2113t-t09-1.github.io/tp/UserGuide.html). + +### Contributions to DG +The link to the Developer Guide (DG) can be found [here](https://ay2122s1-cs2113t-t09-1.github.io/tp/DeveloperGuide. +html). + +### Team-based tasks +- Hosted and conducted weekly brainstorming session during ideation phases (V1.0, V2.0, V2.1) +- Set up the Github team organisation and repository +- Maintained issue tracker (ensured that PRs were tagged to according Milestones and labels) +- Updated User Guide (UG) and Developer Guide (DG) documentation that were not specific to any feature: + - UG: Added sections "How to use the User Guide", "Common Notations used" + - DG: Set up DG with System Architecture diagram, Product Scope, Non-functional Requirements +- Refactored entire codebase (on 27/10/21) to improve code quality (apply SLAP) and fix any coding standard violations +- Updated `runtest.bat` and `runtest.sh` to automatically delete data files, and work with `import` feature + +### Community +Reported Bugs during PE Dry Run. From cadd4df7deeac25cd7216ccafe7ece32e1d3139a Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 4 Nov 2021 17:24:47 +0800 Subject: [PATCH 613/756] Update AboutUs.md with marcusbory PPP --- docs/AboutUs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index d6f2bfa183..d7616a4fe8 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) | Marcus Ong | [Github](https://github.com/marcusbory) | [Portfolio](marcusbory.github.io/) +![](https://via.placeholder.com/100.png?text=Photo) | Marcus Ong | [Github](https://github.com/marcusbory) | [Portfolio](docs/team/marcusbory.md) ![](https://via.placeholder.com/100.png?text=Photo) | Andre | [Github](https://github.com/ng-andre) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Mun Le Zong | [Github](https://github.com/lezongmun) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Mayank Panjiyara | [Github](https://github.com/mayankp291) | [Portfolio](docs/team/johndoe.md) From 8dfdfc1153f3c379680e486ad93650f6e40392d8 Mon Sep 17 00:00:00 2001 From: lezong Date: Thu, 4 Nov 2021 17:28:15 +0800 Subject: [PATCH 614/756] Update Remove feature in DG --- docs/DeveloperGuide.md | 9 ++- docs/diagrams/DeleteContactCommand.puml | 3 + docs/diagrams/DeleteContactFields.puml | 55 ++++++++++++++++++ docs/diagrams/DeleteSelectedContact.puml | 4 +- .../DeleteContactCommandSequenceDiagram.png | Bin 9347 -> 12190 bytes .../DeleteContactFieldsSequenceDiagram.png | Bin 0 -> 38195 bytes docs/images/DeleteSelectedContact.png | Bin 42011 -> 41733 bytes docs/team/lezongmun.md | 6 ++ 8 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 docs/diagrams/DeleteContactFields.puml create mode 100644 docs/images/DeleteContactFieldsSequenceDiagram.png create mode 100644 docs/team/lezongmun.md diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 5fa59e8452..562faf4214 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -167,6 +167,14 @@ If user cancels deletion, a message is printed to show that the deletion has bee ![Delete Selected Sequence Diagram](images/DeleteSelectedContact.png) +To delete specific details of a selected contact, a user must enter a command in the form `rm [CONTACT INDEX] +[FLAGS]`. The sequence diagram below shows how the removal of a contact's fields works. Before any +deletion, details of the contact fields specified will be displayed to the user, along with a prompt to confirm +deletion. If the user confirms deletion, deletion of the selected contact will be executed, along with a message to show +that deletion has been executed. If user cancels, deletion, a message is printed to show that the deletion has been +cancelled. + +![Delete Fields Sequence Diagram](images/DeleteContactFieldsSequenceDiagram.png) ###
Searching a contact: `search` This feature is processed using `SearchContactParser` under `MainParser`. In order to edit a contact in the contact list, @@ -177,7 +185,6 @@ will be created and executed in `Duke`. The sequence diagram below shows how the ![Search Sequence Diagram](images/SearchContactCommandSequenceDiagram.png) - ### Listing all contacts: `ls` This feature is processed using `MainParser`. The control is sent to `ListContactsCommand` under `Command` to execute the command which uses a loop to get the Contact object at every available index and print it using the `printContactWithIndex` diff --git a/docs/diagrams/DeleteContactCommand.puml b/docs/diagrams/DeleteContactCommand.puml index 02dce84bfc..e040f5cbdd 100644 --- a/docs/diagrams/DeleteContactCommand.puml +++ b/docs/diagrams/DeleteContactCommand.puml @@ -8,6 +8,9 @@ alt#gold #lightgreen delete all contacts else #lightblue delete selected contact ref over ":DeleteContactCommand", ":DeleteContactCommand" :delete selected contact + +else #gold delete selected contact fields + ref over ":DeleteContactCommand", ":DeleteContactCommand" :delete selected contact fields end deactivate ":DeleteContactCommand" diff --git a/docs/diagrams/DeleteContactFields.puml b/docs/diagrams/DeleteContactFields.puml new file mode 100644 index 0000000000..16a3629322 --- /dev/null +++ b/docs/diagrams/DeleteContactFields.puml @@ -0,0 +1,55 @@ +@startuml +hide footbox +mainframe sd delete selected contact fields +":DeleteContactCommand" -> ":DeleteContactCommand":deleteFields() +activate ":DeleteContactCommand" + +'obtain contact to be deleted using index +":DeleteContactCommand" -> ":IndexParser": getContactFromIndex(contactIndex: int, contactList: ContactList) +activate ":IndexParser" +":IndexParser" --> ":DeleteContactCommand": deletedContact:Contact +deactivate ":IndexParser" + + +opt#gold #lightgreen no fields to delete + ":DeleteContactCommand" -> ":TextUi": noDeleteFields() + activate ":TextUi" + ":TextUi" --> ":DeleteContactCommand" + deactivate ":TextUi" +end + +'confirm delete message +":DeleteContactCommand" -> ":TextUi" :confirmDeleteFieldMessage(hasDeleteDetails: boolean[], deletedContact: Contact) +activate ":TextUi" +":TextUi" --> ":DeleteContactCommand" +deactivate ":TextUi" + +'get confirmation from user to delete +":DeleteContactCommand" -> ":UserInputTextUi":getUserConfirmation() +activate ":UserInputTextUi" +":UserInputTextUi" --> ":DeleteContactCommand" :userConfirmation:String +deactivate ":UserInputTextUi" + +alt#gold #lightgreen delete confirmed + 'execute delete for selected contact + ":DeleteContactCommand" -> ":ContactList":deleteContactFields(hasDeletedDetails: boolean[]) + activate ":ContactList" + ":ContactList" --> ":DeleteContactCommand" + deactivate ":ContactList" + + 'Print message to show delete executed + ":DeleteContactCommand" -> ":TextUi": deleteFieldsMessage(deletedContact: Contact) + activate ":TextUi" + ":TextUi" --> ":DeleteContactCommand" + deactivate ":TextUi" + +else #lightblue delete cancelled + 'Print message to show delete cancelled + ":DeleteContactCommand" -> ":TextUi":cancelDeleteContactMessage() + activate ":TextUi" + ":TextUi" --> ":DeleteContactCommand" + deactivate ":TextUi" +end + +deactivate ":DeleteContactCommand" +@enduml \ No newline at end of file diff --git a/docs/diagrams/DeleteSelectedContact.puml b/docs/diagrams/DeleteSelectedContact.puml index 636e112e5b..176b692ef4 100644 --- a/docs/diagrams/DeleteSelectedContact.puml +++ b/docs/diagrams/DeleteSelectedContact.puml @@ -1,11 +1,11 @@ @startuml hide footbox mainframe sd delete selected contact -":DeleteContactCommand" -> ":DeleteContactCommand":deleteOnConfirmation(deletedContact:Contact) +":DeleteContactCommand" -> ":DeleteContactCommand":deleteSelectedContact() activate ":DeleteContactCommand" 'obtain contact to be deleted using index -":DeleteContactCommand" -> ":IndexParser": getContactFromIndex(contactIndex: int, contactList: ContactList) +":DeleteContactCommand" -> ":IndexParser": getContactAtIndex(contactIndex: int, contactList: ContactList) activate ":IndexParser" ":IndexParser" --> ":DeleteContactCommand": deletedContact:Contact deactivate ":IndexParser" diff --git a/docs/images/DeleteContactCommandSequenceDiagram.png b/docs/images/DeleteContactCommandSequenceDiagram.png index 5e8c9e2e83b61ea2b25179e8f1f43134b50a9f32..a9e4bde7034b2475e9598f7fb4b15d99f7d19ea9 100644 GIT binary patch literal 12190 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 literal 9347 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 diff --git a/docs/images/DeleteContactFieldsSequenceDiagram.png b/docs/images/DeleteContactFieldsSequenceDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..f84b6a8b9f0996d65c7fb87ee835175c8e9ef8d4 GIT binary patch literal 38195 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

o1;#I*sN!>S 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 literal 0 HcmV?d00001 diff --git a/docs/images/DeleteSelectedContact.png b/docs/images/DeleteSelectedContact.png index e1df16f10f977a8c0feef5d48c1310c417c37888..ffc429b5e5f3bd2bc3344492655b49aae195b184 100644 GIT binary patch literal 41733 zcmc$`bySsG+daGiF+fT|5TvBLK{^Bh>5vfElysMLOGpb6A`MDPN~d(A(v5U?=eIU^ z%H#9A@A%$7evEO3oXx&tt$VHOn%A83x?jsmi=rUmB0(S!6mc(sy&%$YBr>$Mwd7)8ur$>+x3x1frPsAE z!(ilm0M2k`q^M&1$LA0@a2kiWIprRiQAW%fwdIRVMO4gN=$Y)Oe3GVgLisNhX)Ns{ z26dAfff-grGBGP6fV@M<3q@0hG6pPDXYG%XS@ zc#WB=4(rgp%%F(!M}*g6llH8o{Y28sHPa{cvxXxN^bM=~mDRd!dEAcb zZ+#=U5smOp4YfKt+HU@tR!j0RDg}!6t%s+NHhj=2%CHiq1#>=re?k2C{(O1N54`0K zOYIFkyfV#deJ*t&TVofm*=IyhogxA_v~|jB{3sPB$4Y_XxO#{@g4!RH7}>Z|AEa6t zX?}NpyvTcBGdsQBNnJX|JV)8{QzX>&^^Po|$(?Ie8JttPCK>c5Pc=`7aWi>imRLQ# z6}t)6I*GEvR0(fMKEJ(a?~fdWjAxv9JYZ@lV=#=9^c3H(`!;?#RTpYrN^%9)qwEki ziizPopBMPuE4I&)#@N%+v-#Xh`Pz|woD#)!D`D9ocC9UEJ`zJE{xXXBDZ6cMLtg4B zS4UO9^MR|XO=a{62l>$2@;S9=RmBqLX(8&%t}%Zv9dGKv!lTr4tj6PQsh6^NPT1kT zW?8ZRGr^xV{q*}CC6Kt+l=9M)N3eSzxUNWl*XfTfkY)O~lx2fABhNBH#n{1y$Fb#3 zhx=^$ZJv}lTshI`cET6>{gv)5V){EL?wW^5*qʝ-G16Bi^$B=|)ab8VbYeF_g6 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°BKhx6_K=5Sl(dT~;{p#y1g{h{` zTd`9SdVSdsc!jGM#Bq}o_zR7xEk0d@eru?$PL*AR}W^ z{P;7ak54!uQB8Ly3D28KYsn8Nrowcc1xCuOONc!&xp@M16HD}Z-s7t%m-Vg*-pI6d zOKXg95{YqYrVo<`qtM$kxWNXwOTx2ToId#Ck8k zf6Xr0F`A(eGQV=(`WFPsHUq@Z#Jm#`BFQs;J zICh%$xT*durz6gRp8a=(x{Jq87sk@gid=M?fch{0NPpO9|5&-cgk3HtAAmHMfLt+M~6%j$+tH|u*en* z+|}d(54VVeNnb(xOWQ-Sx3*;tcd`o$Qa&dxZ7tM^951{`k<;g~fYq5U7{iX5L?hTl zl(DkmO#XLje5ww=vmSKD^OWpur-RzncBW08Nug%b?)%ZP@pywjcS5j{CMQ$)Hhor! zhUrm{Y={ZT*3#3l>No;0v@>*r6(4^8mPp^EY*m6>r~cYf?tn^6dqj!KC&%|E!m%`1 z6!=?d?X8Y8Af?*IZ}O^fF}(fGg1|Rt(`MSGs6x}YNp~Z=eY7g`PPk5m^}+Vi!Pu#g ziiJ1x6GFNuak=j=Mvn0m>kk=kV8TY8 zAgUHnhx`dRhZ3SezZb8)eT=vh-0HdO@AnDzwbmb(LcL6Z-w8k^64XBrdX8QHTT$`* zW87hD^YbLd6NM{sP08}0f$>zIpLGAfmH~C<&}xw-JFSa#F=7s5KL4#^03Y=i?K?nZ zpIQ^9i?kTtOaCZ)3|dnVrQ|KworY!sjU%&!>$w-Q{xT;wUz#L2dSRjwREzK$P-iSn@Y;lGxFv z3-DVqoBX0{eKC-D&G8`~5g*eVJ@HdKw8N1d`%9Is!q=(BoBWU=Yd86d`2y?k1KX9U za!Ghik)af*Bc)0Z2n;=y5JNc<*;*5G`u>!Z+<2o`EfFUXiwXoX{?O9Yis}UuRYbBV zjN7~q^}jO1fP*+A7A}*4OL&mhXh8ma(>)A_Ki<`Ylou0H+dkemDT=8g$|mbsX*!a2 zu@Zjy!o$RtNy<=BDx)nkv9$R8X3{MYpSaDWvWBpjb3(RAcSyN&H_>#q^Q)6 zgNmnerUYwEVyYUs5#lL*HSX>tT4|{Emuu4rGX631r8a;bCcbHK$JTaBV70P7nGFh6 zP*4bX{hFB5s3VHgSVLKP=@6+3UBc9Ku{DH2Gl~8U>UyI z4d?^~1@Vr#Y<@5s?yG{o8{$xj<}}9nMz4krVspeF7dDbFxHs+vM1pe531ouOK9!Vv zfNkxbX^$X+!UWBRxWc(KG6$$=XeI$eUWx5>M8l%ED-%K=C*WY-pK;$HL!&^<3w`7+ zb0nYDB;an-TxY6%Mp5);`6Pm;7BxO;#1id9Rf{qmq^KstE( z3&bvKlm2wn)DvqH^{RaEHL8emyQMGF(`lkFi_L~Vu$ttlB!fv^S;V zlafAw!MfT$EadVlt}wIGwDp5iZ*#6&S2y=tCYaG%t_QYLO@1%#f`_VY+#7Esm#uQz zZb?+twQ15`1VMJ_MkOd1ONaesk$b)`J!F!Tc^Y59;d@7$o&!u?PVQTY1!Z@LWP5At zBSVsBRqgVp{Vu$r5!{!K^l^P|vUnRtZ)Ry0_Vo4+7nvkhhidQ$)AhujYU#zCM5FZQ z)b-!8R&rpwDZNZL8OZb*o2K#kUk|dV@_?6oFX(BNl5 z8y-j~DRMC%>{o__oOfDsAG+MNva&iFxH7yoK$d1tkn<%d69^kX3aP{vKYOIG&`_=? zU+#e|^>D3k1NoOTchZZfgwo61(zx#VMX-YqiVsl1+LGP&CSEzLj>@&ZxCEG*e{^3QqmyP zQptIJl_BRriT}&4*4ByBD>OTZxSK~uTibmgip>Exbws-J2(!hIDNx;ylzaW7?{L6J zzuV?}JHr+V_wH%u>!C%I7ZurpQxBVzXZdqt^JtZ`rZP+bL~cvV9T}8K5U;zV&K4n{ z?&dYWhqkkB_%bDtrp0f2WjG=yHaNJzp!G^T6r432dJ^E+0v}KB00A0=|0Z;EW8;?X zyy$^}q2YQ`sYX1PaB?$+^V6N>uUStK@o<0OW!>bbXzL(cc?E^kecRR1ICqo#D&jA% zrbzHUKG<5w!g^Xio<4*2OB!pyfSQY#k1$erRvN92mJ0Z%sOQ4KF>~L@v+>{A$8t() z9S5BBhVEZT_%4@o3ps5m8hLL2>4QX2#rDD9Ugs#nJsMfE75b}`INFn<&`ahrqxtz?z z_d1T=%@`bk^>rLWof|;5Kn(RV>v&__9Yd4-YNFG+yxf=P z^Lv3}ZPLDWxmaJEUk3syrQmfVZ=?Cg7)NlX-6Bj`WZO^I8{B7jiOVNnR(DY5njQB( zpSFti&cfK0Wb;gtc z@=vmVJ>Y|@b+fAMX*CdQ_9WfB9WnnAOC>1#U4d|`m&vDNasY7olGflD;{78y%rUsP z&clf6x+hTy$`AeLEjnxjXT0&u0N_Caw-WfN@tck}u0X&djGK<^*)jV5_JD{_m6GgJ z&occ!mjWn=FIoP1P~fH>^?#mC#53SX|8Zc5oAHtTY32UggCpWA?N1}kY4X#3RdC_A z`OB=@1A<&b#NqBLCBL-+kXVC5LWo#3sMLrhti-&$t6Z3$zvQmlOMX*=zrR+G`wEvb zrz1L5jSJt@;F`q((S9=WgHR@9(z;ypXc_;HV&oekbbT$sWTVF)hRqXKTwRluexDP{ z%2MnW2dT~~xVAPKlv2ovi;2ku$e_mE@jx24h+xwpWYcCW;(iVnoAR#88YXSZeOj5^ za-(FV;K=}+;TJ)B)5n#D*cYEFrCfOGU28jajkvE$M6*)B?CH?xfI7*a!z8VYh{&QL zlu6|#C+B|q`}gl*RZi;>=ogo}e5#Nup5eXG{R)@u`iT?KB_N6F7#Z)@!?_z?dLon3 zuz%x|Dlgq-kX`Npm@&Fc(FFguFhCrvC>wF_<{A~^1^MA?<9mC1XqN~r(?Le|=h!w`+?g2nkpHVfeH>O*Gj%;YSO_I4i z_cZrx%I8j!ooY4x?P~{)rr=lBNq}j8k+Y2^vCd+>D_m$P!~94@MSp8 zG4G1yFKTs^o@&A6P(b?S>=cGuk%ApA1dR_0;&4AX>P=NZ;6zy=!?sX>E`TKNxIWnk zEF}6e>rz~gKY7Hkqg`c?Pf`MYgowB}p+|M7;YrmXkG`MIxSu)C)D=>x-t12fk|dat zG@{dH^JvnQNZ`rn;cDSZbGE{$y}Su{w^@+iGq&f%my+qGXJ+T$E0i>}2e?@SyGahRfR%}bVk zap5#RAt9~-0{m|h@L=@!UVDhtDO_V&Bp91TPrg9}7K=RYwd$K{((*`>!;dy-`Z$A03{)iDlLU6EK9;i7xY5#iw*mE~{a9dF;Ro2Y-4iR~>Fc>k`ftn+ey zGn}4>=R;*>Y#8?dV*)1&3nq=HNt)v^NscP+{@Z9@<+o)yZ|CXjLO|Xo9tB7Wkx^&GjulY!14Jt@pwg8FqT#h8dy>tmUhA;_0L08rXEFZhaqHs8$tPd{@ zH@Dqbwd)aG*{j%CGPRWI1&3o~Jj@DnYG#3^Y%!Z0492dJzJ>wG{nb1P# z$hT+fNgu-$buPDqh@~}FF%#u__Cdf9c$pkumUBWMWEV_h!C(8QpsR)OyOe zopxxFym;|RW6J0_WOpWk@^3a)t)s;9@%*`mW9)I}3%GO~p%(i={jA|J=>R?iBY6z-=dS+Sr*7_DM~LIVNuG|=PU=?Ib(MUPTXUktrnOz{;A>)+bgjFgu`x(o z&#;r5B*Er}Xhj>=V583H z^$2j1KSLC4=*XLsAq)yB#v(%BIB(u8?ZXv0S_2jfD6A5ws&z$0T;W)kE(thoF|rU5 z5%F4#x&U}Q*A+Kh>BuQG1mIm~#{8`#m23cx^%28?e~gTbTp2Ej2n!Qht3|2&*zo%5 zK=uRa-j>$Zg^{wt@`%yV%bQJewBh||`GSw?o`Z__Qv-$TmQvZ{Bb7b?2fx+0i^u{P zx(PfzhJTIiXDm%_ZJiHpqP4HD@7(PY<=PoU=a<#~V^st^L{5 zS}U*VVHEo#Quwqv*%`yDTVnnV)KC=eN9$W#w)vPE(ts)4*KI_%2HqWTQ4Dd?3h4lf ztjg77ksPem8UXl~l$$9c3rALmr#HkqRQ}0-kheIzj3?^u?zR9&l7vJKkg*Y{$9Dzqp@Y;#T42Tkc5{Y8=IDImKK5 z?84tX;IQY>yD+a^0IEKY1IBfO)v5*~;wG@0)e0gW$Nlj~ zz}qcLvroFJJ>NcjJWk6XJj%qg=4{CX7(hq|3e+59;}sz&N@|T-ymPUZq+bQ>NtGhk zV5t8Dw(kl6r1y9PU}NnnEjAe3LsIoIJd3TX+oThimX=5m5A0gsVI&F@2;`OJ#PAg_ z09DDfqf6Ig9*Lp;O*^hY0=OU^OSK=9UuzS-h5Ygl0CEc+-a&!z5reO_7$RZ*O-KR^ zFHm2I_+rS%|H~IiYlsOYe!c7(xL+v_nKp1tp@4bvkS2lD+KrEc9ZTu~K(t^F1d@Y- zK?H#eLMlti$Ai!zmgIb;U{=u)@cFNi{Oh_|Zb_{c&ntHT71S0gJej<+IwoR0-6G{j zLdU=W)yNZlY>2NSZgahgjE@d7;@giAAsf_=jQ=+uS_-04s*}=WgOobg&(~KaWoshh zmebZ_W#t}_69Lau0jLBvopM&~(zSyRCmh^d(zy{Rsi+>A`3K|HOxBtn$UjSY1V-NP zO53NEbE7p?&h+4oKPL~ni3kWl2J)@p@=kxp?{xMk+J67xQ62^qfisI*{3Y<_)ogYN z97%;nM5LysHa9f9A?5@?gOimhef!u0=4Be^Idnz`nyVS9-oKxJ+r(r6ATXH~X+IK# z1ui_v|C~A0(a=D!`|aN17QX_%543*-dcnaUt=^xU=1Ot!=HrRcqqh@ zTa8Sc8Zh9$g;W+iiSGJ!GGUiUOblF#Y2Nn;_AV*ia zz8kZ<&cIN(8{bNdAf>L`2_mRG09Zh6Fu4yfdc27H$$`@ftlvNO3M8k=#|v0zJ&-{e zmp2&%=u@E$Z`HJ{EN~MbuT@iCz{NF|@hW!0=EAspPQb0+q32^@conul15B>(kdM_j zkBwl2AjihXaz9aXa&iKg79L-|*&Sus0HeYA^(F}Lrm=oU_TIgt#mwBawe11jO;RzL z*%(QzFKSC%pU56B_N7k}(b?G8fSRhiO-4p$S#Ew~V`Fa*9=`R&1q16EJHS2w*?<39 z_-gJ!vFUv!rH{kxTlR71aXN|EW^W;&J_S=I7s>tzlnr2tUA8_;@B6|3Gg%gmLhyU? z=kEia&cY0^N+%P`R#Q#+Nh#|Dul!%X{#xzotf~1G1y`_^6s))va6oa{%FD|G(9mBc zf!KW7egug94FRN!{liAumGeyLtfx2WL%_1<$9Urgxsa1BfQrsr^Z5>|u<+1<^9-%r zBWgqS?8qDdz;uhdciV#LWZ~6GNd^txcuGo2^{;SKZ_1jI=vvKJR#xJW-}=O;si|3s zv_B3~R8uN^3Rd_b4=X zw>{xwOqE})OcO)6PY*eqEgezISVh4O`zbgf*bVQqiyP{sI@>JnBu}4ys9NgoH1`6& zT2!=uWC*sTf1hIL{aw*J)0BrJF})8VVVW+3Q|jPe9#oUN>ka|MHyUyFnjVS^X+33Cr+MPWFeKi;~kicnI4V6WB%>{rx3>>mF z!2Dlk1Zx;L)$J>Cy0=O+wmsiATQVbgYS4(S?#l1Del$o8*Chk6zM!yhP6yX;K1xi= z1q1@9^wsP^1U$S3_SM=_+>j+#Zl$ywG zycX%^VL5{fm^#6&M zY5o&q^1o$}5M%sF#CT*{O%1$b{f$gJ=b3(|N5E`@D%rOZ?&jtOhwp&~FY-aNjf>A; zyZ}a9#s}H~E}{C({!A*&|4N>kW)RxMG(2a!)zRas-O;Pexf`Gz;`N4)LEhdE>gG;c zW5hu86}igLtKTC~Un%6$qw+i-l&z+dfXnVv8=>yMb#W^BW>0FivBVN5*_pidmt^`Q zq2#sra-!&HYNltgzl7U>v_L>i%v3V9(Ruky8tnd@C>;_U9L}Z#{PAC_oOkUPdJKUT zy-n(5O~8j<52_^zk~AoL;j_TD3S_15+%9?ZvKinZv1bb2SZIAB_qqu>6L^^Xsy`Vvwf(5v3Ml$m^i<0oeNoBIJn`(D131KK8j^s%sNYH2ym z#W_exO9ue!JQy{r46okj_mV3^#Z#2@>&Fn5O(Spyf+JXe=2yn%&Ye4#MSR~^mkFwX zMv?exUWR3eKK9|v`c!i-CpW0t zL2U=-MbLRC%g6zz`(D&dLl9*VP~DW*puwP1H5&#Rhe*~iDxX2Z@7XR7azLTE@83Uj zT6aJB5~{k~*tWIQhH$>WKxjibv>!gl3d(sruL9)8>!{#h8kxmT)03lpphl$#&`{nv z@@VtI73KqdT$hO06val{A7;Z)Iz7p(Yql)+wzvd__&H!-DywJ72S!LiLq{SdAxRaW z)V5?*J>8p*e-2-G%IuSw3mlCt#FNnbbp~-1ylZOV0Rr8D*%4JF)^bON>T1b9H z;pC0EH3nQ_@=p`__dz}FN5bu6o&dM%ye=JkUr&$b@cF?n0F_K_-7S0u>??7V7l3m%mpTdT+ND(w~lCT79pW3u!w?SOb5yaV($|ZTWz>Z`{ol)k5UJv zY&QC=$7?;eZZb2Qg1HV(8qFF+W?^BOK|yr0>{F}JgBG@kb8N{!?Y1znwqRmkWTO`y zF=^N-kW=w|Sr{tLq{-!XMAtzOpEtCM0+|!eclq&L0~fTh{cK%Sb)9u%XGNc}u&B0R5QG3{ z53m(YL6IO-MF`nzr`EN?0=i(Giz7l)QBHhuoQ@~B3TWqoF zqX<;Kruh3c${-pb zW8RRNd;IYg$ZEX}PUlEhQo3^pNG8EC5nNO)oCp;+I{60~IQtOG50~v+dNR81;3CxL z>~%^W1}JS0`tIOp*_<6-KvNG*gNw|WWlaIKQny-1QS;!~fgOuRq}%haQWy~&9xlf7 zj#lH`M<>04`@q*}=zNjS4^$3@ZE-EQ`9sM+RpRUkz^kZnR~OF{b%*1_cBR?r2AL!; z{D!30CMi-uYab%iK;%pXh=2r^lT{rL2-J<5JJ_+^pgIm^a-b1uFvS}hJyVslr`t&GKB^+jVx!-K#7eZTVGmBhhqvwK_)vcs=7y2FfGC*>L`k;By;BF3YM0oFE7LumBtMLE zXCO2dD7&v{MH+5X>~C1Tlns={Fum}@CWlahE&UO5c69lY<8*s7F`F10c^dVZOX8eb zspSXH!M7pKIvoV1G%iIgvwi#Whm-D%xLW0hX=VcZ$gX3tz{5?`1b*}UZx)B1XSV?GAJ{Qy4Tx!Hr%TZQu}X6 zBdUzy@n%Hjc3Gk$egc#*WB^pNyZJ}pe;>7-vrzv+nMYG8QnvPtUi?u5I2}u`iPVSL z0m~mQqSSHrM-)n9#K$ddDdMf}y|O;{KYJlQS9@_!sDAzQ8!7}93(#JBLd_8`k~uDQ z(emomis(A8`bPPtcT{_O+yu24S=NRwhDb)#uDmA2=4@x;t9hU(Wq#ad$M%%`YZ9!F z9M|V4PmhDeYP3FEK9r9WUN&&AIqn8*W&I&|e1xiADGnMyIn(Ro3EpB6uLGZw`AF$H z=qPT(iN_FV{%L0fG-X^6t;?6S`GXsjJ3wlv?=NXpFCjw`0Be8@$Xx*gW8-d9>unuN z9K-o_nbckIIJlI;S!NyKs-LcG4QVQq-f?G>kgZjd=&dPQfeuFu;KgeioH&#SsW7dfwqjK@za zEauT?u0M7&(wSkVh3=Bx1?YF>k;wWTxR z5A1ckFxze+E(KXatXF1LDV(+s@kovT)W<>1lr}-el|I2;a$X*(fdng(y>#Go_T_f) zWv|-GJ>Y%>lpYx+WzEBn$ZU3wj*fsq1NJMBy@3|2;=01du7R>GHxUI+?Yz7^&>t-9 zdhm3p=rvtGk%3OZnO-e51I$_os4+tfdgZee|6Me>65Y`1%h3_of$_Dk5&LXTiz_;| z2Gdy$XaN5mkSwoUxdM040~yD}!~`%+p{bo2r73VtFBKYkAjms>*H()MX2>c7!?R}} zUONXwg0!^y=hzdThH$6J(r#OZmPt9;J8)E@0v!>(a<)x#0LAT9z=Y~QopV$nj zEGz?Z9s*#+wSrL2jg1u|**)pfSCeEy7(wqIGf5CbKbkOVn28@3rd-zFrOIFxsN=z8 z0rwo&<9;rV5fqnq<4cF7t)6^s;z@ZRqNk*6g_KlbWeSrt^ z2GCyL%g5cS%xb{`l0Ps5bG3o0!ZCXk4G8UBZ9r2dV$&X9kpvcxug={DiJ(%~P+rb7 z`N$oUf3x#>TXJ%;Pg5)iqjV@;xSs;k550JSD89*$wD2ZG)bHr>CjKw}njfS9(4QVX zdW4`-ZyOrYMU?-|x&k5Jq(`Et%b=pH{d$Rz<+$h~7;drap?!E?1=T6lU4R6uT@N*) z-uli>Pv_m-Hsnk?%@{)_YL7+}e*V4#Q*R$YLtt3FtDs=fo8ot%toL;R`x6X{oJJ^-g1lI8E+tF&DR9?Uv8AVt)umI-nQwH;Wh zkLWDfU;4T3;bgcD20#1bo z74|E@<~*&=E}UFi%2%+5D42V)G&x7nA#X*0)9U_0S?gfKgj}Rohzbh&_|yLA3Mzmf z21o-9jX?l7HOuny0%MoJ?6laZ$Zm8}x~w5(0{&VjU#}4ucE3jO(GlUVJ_UYEkY7Np z>jvs|paPbd_L~CvBFl%qNhDUte1y+Vx7b3B=uIdvpv)7!0lN)@0`9@kcz-i#ooV~0 zgv*S&*8B*vhV!3fz<=tq42-~10IGm*d5`KTgq)VaO9|+J6N8kPxK)7d!G|nBHGr~i zOLs?I`kJJqB=~ExY>+RVKo{^es*Y$Dj02ZNGPSa@ayYAI-6kkgXr143a=80*7*Dr|r zn&BGer1c(peXlv%+hNMovuGTihV)$qxdPB4h?WAJ=gWLTWsF~v{lCSYG#v6CV~o;c zP(4JXfLtPJfJ0I1l7j%;p&Z#@Vb1cY+8*A1(1(rx&IR+CsMXXie)d^^1b~q9tsfDX z!WiH=;M7a2-l6NNO!GYbFu=RjX>oIlGN9(;C{cv$^<1;_H5Pz<6qN5{RB0`QU_P)**hqRtw`Du#E01p3K>Mo zG}c>CsGgsl_XHRrjKa_mO_$A1-d3yG+1Zq&q`YYWvj9DA18h2=2}&V`$IsziIAAov zri|yqjN-jk7&g73B;7br7`1YcG zBIuMl%kW?ca$%}f=KrhL}Q9nET#cRYrqB@u%#K#0LmNip=&!dt*x!g zRmKIM0U~8(+9ANsET`hpH;ld*CMzpT;KvU%TxH$6tfUFS&p`iDPFflxCufK%jck?6 zzIC|zoA=fJMmIS)^0TtuAcW#RQaq2qbJxoRQJI9N(1r*7`LXaLoub;an;fWG52Ik< zVBz8h`1lM}y9&sD$<-a(MNw_6Si^n)gIWx`xG}@e&!2VA_3PZN`I^O&+QtGSPuzEm zh0ipELFE44b#d{P7W!e0gs zL1cl*(mjyUd`N%A6o3u_j(Kg*!T!MlS> zMxA`eyn%Ta@JL?(!OL$K&iXGUT6IL=3}FEF>Yj{@W`V)Q?ugLPH`h3507<;JHlb=H zb3V;;Gc$JJRbqgyWMT1T002f-MY#y;;obfLr*8lt=I7@F0N@u8aJpjQ{s4&d8C+*i z4r~HABwWBo%f!nYfjWl`xghhS)^p3B48q|0XpTsU2m)EL-YdPJ=%~Hq5}V6m)heq0 zGi~8hl^JlnneMfq)II@+yjU$pZ%}{CiT$v}#(A57B*6u?f4R8~xxqOd<^fJqI3jbf zJG0*p54Uiio~fKqKy(if@n4V{@tmHU1Cjs_4UJw)AT{U%^D7{MKq`H{f;2~g0g~by z%6rmk7DJzoBlztOm91C&5>G~!d9ESkShl)VS|}$cr+`33UY?>Rh6e*8?bcxQZU&sX z$($alNu2Pd%2PVYn`z2H6TIz+G$ z`~#yzx`MMoVVy5$xXBtuNxFSWBFFaBDiI_Xg4h7AwW(jYjTW;&yfF~5!2B9U?je&$ zde#Pt$hB|CCN?MOUQ}Fa7OcLhSKEdz(v>|%X%AfcsORNF6A-dviN5G3LJV78Ak4pS z;Gn~`0OgkvZNyPKS%s&w-WWSQIL(qT=L9B!5p(e#S<~vYXBeqKqJ34*CLPz;u(J8oWC?-%&kRdS;Eiii z+h+rYj60&^Qm`Hv2)Pu0Z^YQ$>5QE&pi)Lp(jWp?HC_}iCO2RBl;Rx2BQ%_L2+V+} z$eyB9+W6RdB&fZs86@9^q=f}8#^)YT#X++DJq8|K8k?Il0iKp zXs{9OT3^~97cixZBwGEFJq+ALpu0_S=KwTN19|7}B{(*GJrne+gD(cd=U!v<%UGZ% zu@eNg_jpt;T6)uW_&O~1nE+wMAXnsYnbUd@9QKHBy>ha8dCNlS><-Vb&qpdVR1pW( zsRHjB%0@;#bu=g`fNXI7zO2CdQBX+)(MpFBu92{E(~< zH9vJdEPk&|mQgj=>a1mFZdgo2xjQzc_n_%Zrf%-0cUSP&FYJ3^njhaQUB2)sPzy9b{K`iqMR-s9*Idy1Cwl5N0kZUbTtGy`L|Wa7MfTqlx9^Z%6g z=J8N|;orDcZK#AqXd`<_vQ8U9$P(FwC}NVVgK4)@Np{M+m_c_=0eqYyhZi((gCXbOTp`2@Wc!HnZxL*nZ?-op` zn1V;*(pe~pwD`qJI*fky;_xl00<{aUjTL*Ha}z>=YHG!}%##nx1*P+&mWX-j(`BxS z1mU$y-Vd9<=vC|}mlLUn7+Q;b58YSx zTq@AbsZG!sdyS>c?HvN1Dj}6MY8B=sTXzG zCq1Uy&t%WZuwn^39sxC7H(UH9K>ucjZEs;txnFvTUwo^IvSoD5P`I~(?%3?)pe}Dp z^Ox>2+hx3>37W6g?0#hflhP#rs1;|VZ1PiZW|6#$9@H&D>b$}Ys^;x{K6|aO)(;Jz zOw%nf{{*dnVu?Ya@gX)MJH>_^vX?`rDCsx$YA<{eSe?@qo(GE-6cCX3Vnu?R$=I;Z z=+J1T6=!Ut7#2M^o1X1He}E}2QV|`}W2dB<9dNfJ3cUa1wo1Qp2LnlzS_^oLV6yhU z99gW(XWGF=Eb3fWS)x^%f#Ky2#1LH7)%g<2qR5dH5*-sTGTz1;EM+Tum`2gD6wn{L zl0|}qr+oBCpL1q|D;n$c8L=blqje$ibIrM4?hto{#AT$ea1$h6bfx9HuhLvDHo=%J zCqoiQQ`;6A-}!vs>f>M*Xy06#E@lOb3iYgigjsgYVaJSH7fp%X$3Bba-dz8=aJWox zFTZ4*#_sjzOZ8=Qi~OXjML#9){XvJ+k%Eh>aJlT28A}BP1;F=##!z6N%1BEFX(y#T zA6PuH=yP+d)uiqZdc(|e{pxfD+bf>_s2WrWbsd+BvKiKAMn5U;MLI2rSDtn4hW>BX zYpiV04?1acWGwRWqF`V8m(shQggYkMyRg#`oh3Q}>jyu^_6`d>l&(?M_Fv)Oy>sx} zlgRuvgmHm$^H2KjDOA-^i~Ri^AfiliOf;ZSALK> z+@`At+Fe?R1Lpw#@*8J%2+tIPgA0F&^3CmAsb=G!3b%9n(kyzfjqnS9w<%x{zX+Ip z>;mPiaCWq#=|`zlZ!COiy$z#@m&m{lS8+R+IU$OlV=svMN*zOTG{P5>PD!Ljh6hBb zD+r|?uQFJpTTNV9uv@EDJ^P_}$Ig33mxqa?uRwz$IK1M-TiuiNEg+PzKVm4%(SA`m z`WSANgsv{|M-npEjaNrQSmnj^ovdBeJ7gy<=RhHp<$1UK$quSLX>V*$XyiE)s(lD2 zXmi}%?d*~LiFVJf+-3RK!aiqlHr(CmS8v0+S61}FFsH&?s1_v3&3u`yy>WQZ`B>v& zm@3KCI3p=7gzpcC(US6FGTxZ0RI89~ zVVCObpQwB(JU2KK?x1cMS;$sy=Q69VTXy#I@sXT>pmWR0^g)M$0)tS5#`U{%i9?~q zz1`}@X5XyrONj^K?Aa+$_-rhHTF0(vN$v+9$XV;2>I>;p%}yjMiqVb33Uev@mKi z#`G*5D??d=T99OkX=v-L2-BvNM}a^u&<_xlPu&+BV6pM#ttBy|av4hL+`~&Lv*l&R z4euR0rUqV;sdAlywr2FnQ z%ib$O2X^hglDRa`8DnJ+Fqt}|j4}TA$A7w>S%Q6Tf*M$|U6w^9JKOTf!E#|E-XQ*r-0?k)6DLhdY z0d1bk4QtpaYdBKI*>YbyG$}K3PR4PJ(?i2K7G{fVsGk%Ei$X2*0rMD2wN=*`4evwG z`WsVAW6mCHyy~%MOXshGtZ%ivsj&?AsnKp(wC26hF|i_s__Ger&5mcZ+guoL!2_#G z!IaFeoUeybC|7C}t{n~jLc7mf;Ofo?uMd}-akanDc&v0J?eNFFhuFGkLaD=DArpAI&ql#C$hB_9<#v-9D9LuJ7t6~pKP8t3B&RvFADZ_WUd8Gm#u}SlQMeW@t8+GE9;gSFR5}b zb192lmnHTyj%Gbtg`_MlXvbe$$ztQOxF$z`Zb#(E!46;3>^16GrZT zO<1NU1}|!U5n{I`-v&AIg4wWRA`BvVS)*-c&0vs=jrk! z@L1T}*9={qbasHuV}7(Sx5s6)=&i{NaGX+y9&J9L_&|5|go#n-2N~jQVR!&!brf@K zBOWPrO7@hW-*sjN&FbqH|$}tow*0e_M&MQCCGve)w>+h0j&r4!E zVC?ef>bKC^huLa3)oX@^-d66oaq$$V*ZXHWm#>vXS^MDnxKm6&U928ng@;G|+5mbz zP=c|$;zYH<4}XTa`%h}F0&y~B2C0o^ah_Y3Mc3%XA1DhxkSS6y`R>JWt(gcO?6T{= zy)hNv);-_j5TNbx^g+w_k{M~Y)`j>A-k-xDsOmJ%FaKl8bU<&omhGmLsxCTU?$^M3#85ravAveCUVd;*qrCwUaS=glfVTWzDnK)qk4o zTfQ1Mt6p;sXonY;o#u$@_JT1b3{Ymceaa!HLfQ2U**zU-z#{$HhE8$C|Gvqw@!k0i z#wWGleFi0HuiRjqvp>K8!Rs@5_=qzaD?G#R&-nSZHesWXER*{E3QP6@sC_gvH-enF z4?I1TTX^{tdDO7KsLX6|@WoKlf>J}`eP37EH$?O5@L#h%7hoYe$T_z6%QJaCoAX&0CeN<#3d6jF#)g+hmE&1*?}G z>7S#Mluu{Kyp+ny^rN#h$C9*;myLB@P>p;3RwWSFgl__NsFHMIJ`ckOcLcBNP|MUc zXeaT9J{&Vh{pREki?#F>S+{*dABqV?Cx$LUb&#J z;mQXtsv6TCZh7U-uDp{frcaor+xJiG-@M?NH}|kj`KIj<(rq!0ejD?)vhtMQF7F51 zCguO_=YQGUO_k?T2BX+Z`#~kkD%sOZO#8piXQ;IMqmOZ^M;!wl+EPG0z#|P>3r=87;P95o z)0o80x-^rF6Bq5?if~-?Y))%UUjSuVG;xQ4zBlIxc6G$s_C*$@Y%I=AVRCWBm5B?=;hkM;a?JTp zXT%(WMc;p@tY#LL&DRzT@Cnd+ny}c)uy!P*_I|JxG}6}J3TBzk86ffu|Nd>zb)_r( z?4OOY;(nP}Mtx>VX1-FP~*X^2$e?S8HlIF zQ{sczMC6+#K3Q#jcoF$~GUr8XN8HCWQuo^^Snf%gk82 z#+s%J+=~KP!^~rHbHR%4A5S=uZIdNa_Zpy~cXs6)i1$0)i$r@q3JMF0xC=||IGzp{ ze5!)C?1MbR`~TLsJ9)oc(6#y@ksJ{^6U3{5Xv(7M)0q?4{ML3~9~+N}9z*Ms>ANAO zQ#ARs4ps9-R#l8*+6w67VfWP1zGqRoN30+Pic>%H{f;y{o9rh}Dmq-J>EztDo1y6s ze)*hNA1k3X#rN>Zg4uVWD;0aiSd*8O`c@Iqa_fl3=DLNs35F?`Z&9pK5`~ZD2j7pL zy92!w9&Brir+8DNo^CdCv{lS-gGDS8jiLH08RWlrD%S9l>!_BPjd1%Y8Z8lQPkymc zCl&(Yp7RgS*P;Y5Vg5b=spN#7;|B8!OTvidlii(BN;j2KT)xJQnl-Mt;$EVMz^gzC zD3c~xm#VBUfOp<{nQc$`=g#!c$?`FJB`m7)%igs{?YF?ZwvD&+_f_{rpNP(1>dUVh z?&>zj9mVo z!D-=H-3VA^|3T~q^25F@DX=@b!u__|lic;pK;Psb=LM%LtN4*MYMIw58+S(|t-2q( zzH&ZrpH}inwE*@8>}IX(`+Btx?Ua1ap1Oxcl|^fI73tVU5?_DH?OX+`2^CygLj;AAB}(bT=!E; zWs$1;)161FO9FN8rSjTpI+%IhD7~e&DY5i4*Y^GP(`n-mvspm^q4q#Ix~rppcuTA| zgNQ3{BXIL=@JP*rC)BfALf4vKhGYJUAh`7I#xz*Ofv8DHS6&^qJnh#;wxxaTSw>_d%c44KYNi@$JjaPMz9)f)MphvWQe z7J9vMSCW87tlg%6;{#^&t$={KrDzKXvO?42J|hLM%2<}x4Rx@Td+ffY2YgXoYX}?K zwhiG3tnu~`f5oYj#ZV|UqF@>a5y;`NTrl^2rPKr4ejFeZ><--00~@j1_#F75bH{UD zsw@AN4jjUO6xW6Oz#1NL2?76QNV_{p0E7WMvyam3>vyCa$r;$1&x7o%rgf+N{Laks z?RYle8b6TU`r^hf)3o=m$Gxc5LT$aVJdAFq7Bg@g&vp0H><&tHXZ#gSpZH@04)xW| zSO_>7@qNE%cvwd6wB^=Pw-~?t_5s8TiUW6c(tyVAt@kSQ2uUfx2VWKHd*bOQ*Ujvp zYkh&x?ONa`bp=@F7nOT>k(y>hW}>uKO)h2%6`gcdaRqj2iZL8CG~*ZSk~0od9m+Z% zk@F%+SheovPacd}|eXCGKxFo_lP_i4SJjymhda1u#A-ETquB-f==PV1qVM$U9ds#?>nOI0UbL0*h& zs#i_#6!5LMsyjog4Gyitkw=Sp8oH&c4}HoHwRZ4xVAMRS(8!)oLT5f~NB>mQP0wWN zk$QXLqI)0E`e%z)2Iy`>ZL*u|l5ICY5Sng@4K|NFIQ{gcmcxsHIjS2n_X~~D@0p_y z?h2Dv)Q32m!5%oo%DFKRjI=c@P{NhN4i0UmK+nrGNEs!XFW(!T3x6q^skrPuqtR&# z{8~HYLXXt>!;LH6VZS%fE+NAS>^Ye9`(6RblvOIbzwT=Qsvz zp0G^b?LB4?FFTdWNG8^9)>Nbx4;-Fb*J|VWwaU-}DQUg&Es(arv$$O1t_8|!i%H11-mg0BePDobH*7fA{ z%jtXho~7kk-`ZQ0m&x>q!GivYp9AM=?HRdsk*N)g8h*_Hjj%Awhi|(phUw}oN`L<3 zLRz?bBl{)CFyA%?0=&!0tE%gAietZ%Xui62V`W4i#f@!8m`k0+wz7N=_|UEf6t1^W zx%laHTzS@ssf}#tX=vw4R&Z*{f%^u9I@Lf#CwEibSZnXpWL;w4s`=bLBwTU6W}y!hA-ZC zqyZNDyU960VZbhy)nOZJ8IeZS63J?3y`7)E_F}QLu=-I|-G6a4NtN@_PhBt_(LJ%b z3${j7XFhNzH_85f-;ku@+AX_DxfV7t<3<c{a9nt=u;UB~rM@0Z3hr&;{2je^L-q7xh#<*2-PAs)JIHuXfQNDYsu) zi>O@LBW9Bhu_i_2(_dj`sb)Lxrz=YuXGmg_IOiE$6BJnVRWdl}(ayu)>pPE|$p3OR zasXGeJ@M7y)VI|XI^$2qtqYC>WUGm7 zTbw_MlwTadU$O2Mzw&?g^S@$DFcSb8&rxk_bR{ARYZlmU^eNj^`eCk}G2jYK?XN0l ze+VlKYxo{678BMo>v;Ww^uzjGPC+)~%kC@F7426{4gen>4VWUF6SI2VP0{L8XD#ug z<}<8Xr8$KFRrn6Xpk=i})uU0?#VDoOwV(-;RlKtN7PjkT1#fLvSubxy-3l*$&$V|fX%|6Hh?p4a)Hm|B(>_68Y}$)-w4@dSpWKe_*}uy zMXl|kI$s)xMu*EQ4w{>po8io9`=uU_pmioAmpS@NQsQddO?;=-8dS9x*?+c%wW;3< z2hsgfL3fo)fmOkp23C+}_1~BojO;?**nrs(GD&exy}kC9^f9?lmD>&O(7~Z$U#-*z zeXp7SG@KOc;JI@cZd$#I&pMPtppiW)6{<pSEq&~?NbK}QD`$P;{owC^42h_vQM zxAw+Xda0hgG}rX5-o)5=`A#&d?F+ulIa3O04KPc49bXBglyVQ#J}M{X+#qY-z-g;4 zAR?Z#q?swALrEF`*wI)_OY`p9Z-(NxV1B-DAM!F_*%vsxXiNHS;N~a7oyptHBeH%g z?UTDXIl#K2(9RxEwkzE~zRcx^JS6>GXukw6lytZ~+A(j?$ckaaZ$daG@!Jr6XL>Hp z-+aoSn8)*a2OXbO`u8`GM;9C(1LGbI$4q>M+b9>%b;t!ThT_Mj!h?T`$(uxch{?mv z(a%>GXHOp0Ji5^S#P7e5`4bK=l(>2Fs2G)J!1RDb>l*Ro&G z58)nE_v6$4A#|quxP^t)$`st0jpveMcblGp z6|1@UdH1|Uv1nkYI{AU}ft}SFMwQ@lVj-6XK6Z4LgSh23*{ui#?1F|Jp;~<1DZ2|c z7@2+N$_*;0(Pvhld1vSpmqE^6Y}HY#7i?;GW;?Rh*PA^QaNwNH(~ndt<~*PnZ6@W2 zvp8l4DDt*R2p3^;oLY+5taOt&>9UPir?EJw)dfY zaJm0PXbN&A)2#{ za|>Ja`|E+q`wXn9#i`h~>+)ZN`Y%t9e~BBDt@rP&+{Jys!%IW{CM__byEhuCi0{^K z{rPa@M-Y9a=YyYps;PTul~I_Lp5P9qo#2+(f8Me!7K%&IyF&qu^Hu%`)Zv*krg7(& zKkCM0^}5)_qiio8-sFIPaoSuF`5@P^c9!(|G3QxdZ{TpLR5MNU$4!R$^l9LG09#B$ zlgH`vpa1x89=QTa|IGWZ75u;8q<<}zk;B;olr46ArEv#f9k*$ePWFG$-rL?NOY-Pz z_%$I(u+JN#z`ie?(YUeupa0kicPNO$#;NbM=u__NTsu$@%#9xfHvb?q3%~?EK7O_A zQIa?xRyq@j-Cr3MHwb)r+`zR7?PT2Zl!}tcqi64*oe18chnVAZu+@{`bU=p<1yqW& z*l6ztfGND#eRAPW>!PY5lRl{J-^cRYXQvdH0~q$&&7UO{$MnNXrhRAsjs!a-?C|}g>e(PQAHbz16susyFAtaK8_LgIUY99~A2t8tRt*&`Bv;Pc%y=WSO zU=5yBhB2VYM< z&LQUPf}Sj#v*KTDg#E^YPCTRBX>Rlr4{voCr!@*TsoqpNF7D8_1VJRZIxs>?=CHeI zJYDX)tA=f6I2;>`-ks0l`90fVG}`2`>G!~T>Cvh1_@P`8y)T6W{Sh!cS#x=ym4R7+ z?*eywwCKayv*Jaww^igW@iZDOZX-gs{E*cGItKm6{Gz#Hny_RwGTDMDuyeyQ0L7@KrV)5xxyt1?^t>8<7kJNDagVT)16^RQza2!D zq{Pw6#T%OmmFfU2dx#kxl{O!Ki}S5rDLaaU#_QCG6t%`;tciS_O@0DcbrPL%If z#Cuv^0i_PZbD^OI&O={o|AKzn{ORr+vt%z@-N^NZUXf*g5%?`aY}Sjy6OTww)0O8t z#2q^@Y!-|(<9~^86r0bG+v&}O3$6+pcp$rkY!!;O01&XMM6L~PYeLEo_zVIb5G=hj zh>8@sP!WabE1S-GqN524pl|uPMwPVwG|@5JWoSuyfzItV4zQ{JgWpu%^0p77i4{vrJ!(5=uWwu2 zESsi)8}_nCHtml+P9hmZhTT4*OjcuM7s}Mt@ashYw?z^_iJ>VTLT79KU<(#j-F-a( zcHUa3!#`G{-|)K=r6cpv%M8hG*j)m^Y|s_hOX4Xt4+qB#X+A=VTZwYwY$Klz@wjii-m3RB_NNJxAmr+x0DEXyvcM5VFMnQ!HP7 zQUERBu!kzalL;Y?lytRhkTES2GAc};}{ z6{aDkkRR1Go{>+;TI~MeB?&e9&TfDPR(Q21{Cu+r@Di^!B3oC29les!*2=MME0ahGKu;kGq3L)jIcXD>%`F+6{da|++PySbKun;5cm$j9ZtY=XJ%Kz z8;$1MEF7xNzUHFmn))567LUGAKekrTa%EFls7bkqs*n;w8R72akI^u|ohS0*onBm~ zIaMl(;=Z++4=Ntr$?f|D>N+w}2Xa!A7=^6_6g4HPYR~Auj~wu7|9V<|8-xJRpdtr2 zdW6->W(ql1n1B|uoPtjwkNN{#cq#}f_wed(6zKaCx_|zCW$jQw>GRwbFb8Q)KFJ7? zRLQK7K3?T{x;+Q7fwR2w+gZjufv&!Zifi}MiEQ&fFl5tz_bZvSIO?1#&$gKki+ZNF z5xMMFwlw^?92Q|dUn=6-sI>b3Gc7j_x30~J30~!3qB(k;63V`X=41gCo1rJA_(w+0 z9&b_*$hT!8)xH*{QqzJ>g+T;r{&_R+cJ2QR_<;=Ywu}EqmTh|z{+X1UQ2ozb-T&Rs zxZ9g?(BDwwKXZevWPz*`>FRrnp4P7lt|bKV^utb%VI+yQ#ED%$0k$$RIrYgjFz%~e zNJ!*jGXv+G-XIL^q27pRdsDfE1beN1!skiCj%^nm{tsE(7`ScpXE-nhP`~Mf+TxJ81yX0D_un&@F2}pvaLL_66Dqvl+pnt1U5d^1wpExw!s=V< znu#wiYn$+s`W6POItCTcaSlH4?k~8SQ`6G8->b?sQQChw8)6~yaUZ$vv{i=gY^%y4A>vgbMx z>QyjiW7jUMLw7>rX6!QD?LWw79a3cDh6d@nkfd1map&QOuekHX7K)S?nKr)K4JE@) zR=LT&tYXkCBdkeD{VuTh6GF}WjgEF-%Rp*J0&n#8{RQjMlxet~hvxEE5M@}~>`AN+ zkmW;f)Yl`aj!cA#JZhvB(j1Pvj@8&wiW+4MYqQ=rTnz^}$S*L@a6wLy_wRv80V)zC zwp3?~ia>#khr&XtOZ+vgGF{9DTzv`TzGMObP)Tgu^)J*fN~L3)=k)v9t(-ac_#K?dEJDl(J2J?TOuxtNbnpUX zw`TA`hWxV(r1QUXxW=~k$qdAe)zyRa0$qTmmC8FHwWd>bHxbbe&Cq$-US^oNWNuWw zG~B*l1~9x#b^s(=(l;%Lb$96X8Ni^^Ecv+6za8L()T~p zy&!Z2_+M|6tB~_ZT2|LZS6hG540O|!;C^Y?({TXE4BvD({%#_}O$p-%+Dby1(1@an z%rOJek0RSqobgCdaW=};?<*=q1Z7iU#K;lzY42niR&V_zUaEix@@VqQJLf<{^4t@A zlP!-b<%y1mW`J`F?V~4V)@IX*`sTg&oCBtxH(a%|pE(0@{b2>!i?_W<5Z+7(3`Xh( z20WksOzK+1mgqzqivtom4b3+w3wV;)lPAnEem7$CkOzCrU`&o1cfgDbSYpuJ-=C_7 zZ-D zD+4(THwHX%27zyI)E0`Rl)F24;3&!Ilpa);WngCTRxtVby;;?_Lk`BacBn;pY%hEI zm5B{JpMXH6G+yHzGCS|YXSf=7dK+n_vtn1WCT2v9Ml9TRau!cRwlzb8_(AB6m z*~~BucH5afNQX^wnt}{d<8dTr(8B@-v*l?&mzgEv!65aYZ82x*7x$xB~%Zcwlui^|K31J-)jV_gdg`%dc7EkubeP?K5Gc1gItTg{V z4S{k+AnMo`Lp@A95Pczaq4Ac1AS|ml2*{i-;DO$T#Q?@l8GQ^ATwvu0n4_xo^OrX6 zy`=0qcmHhaf@M~-2zB!_3{-_<$sp_00ABh5#sdGp&x#~W16zSfKQEyB(13rcLr4by zldB|D>jQ3{6a%aT24f>VvD&~m?4|hnU*$AZYVdp9i;484bgLO^!bClG_23*oT05j??LF))VB`jY6Ovt;uhwSQbAM!yUjs~(^H3n{%OWX5MHktNib^$4*7M9UI6 zH_(=$k2!zrS4=)q^D8Dt$zzuK^8#&oYzZ$4x{T%T6)9&nC}9q6dd6^Rs!D8z>w{ai zVKqfX>XoqSPMVcpHKObC)7}ryXs#!uSvk+UKK)lQLjony+$tzQ#ee?mi@4J+ONiWd z>+qLicaB{c0|i=u-2>2xPMAHbO3v$RV5TCktagvXO?AgnVCx&0^iiMVE+a;oi}Xgl zxH1jGZS2-slfWTGkj3?6_fcDQ&-RHsB)geTsv=%!U?}cZ>xsEjAL??8{e6c-=7MSJ zDgQMu zH^BSm`pys+B=&_&V9iU|BQVdxiAI#<|t{D@miH*(9eraO^)ORF1 z6hGe*Pi%KomAEB!d#(>8pxQ!rUU>iz1mJy?|H;wme%Y-4l+Luz%yVRUy1|*?e`(UJ z=|prQS}}4A@xirZ)V0K4S}J4Q6)kGaP221VVy~JZGeMcs3umN(&t6KZm9Ski4Mx4V zvt17QfI-oDN7gAv5o*;_EaKcS?zT`jW!MZlX0M9m<}7kl&{BR*39Zd0=omWukt(Sf zqB$J_3XvRwj#RfdK2ocJ%w@7x?`1An6kT=1`r7#YQRDUvZ`F@Iy#Bmp z|H@@GW?HUr;Iu-+u9iw(%9gY%{|rShxt48S9Q&Ua2VF1ve9pUi*i{-)%3JAvs#oz_ z_3Sok(kCkmWn|&_6?bkYb9Qi6*ACG%6ZKIhrRz7SB%REgU5`ORi#`ZP!=*Y4cMh(8 zOcO|D>Fn8QPO}6J(y)UxN(JsR%?%-riXE2$XX;gLPpuuT{#^dLdiJgSY6$Mq_T#7B z*|D(CStF_eoSox-G@o`+d7Zn3dGjJN5r4bz6eLgrwKV*ET{+?>k2tDW4Wu=m9s-Ls zcy!MEa@UnjD1tRkHZV^fSVtJ{Eq)d)Gc;>a{})BJ4@$%bxTqY}bvgR1<$? zJwauTR?k^z!^-FfpWXH}_jraU1Px!n4|O5}o@jWE6b5WpTYsx2iU;uHnbDHHP-QLa z=MqjYB8XK-f9$w<3JA~O(OHqGvXbtPe;Z~1x018Mzl!1WEdN`9C^aETN_R;#n-0%! z=e$Gc;GpcdaSAX2{a5td`(~H|f-Nsqj)ezJDb875x4g! zL`Mc3jvNyULhXNc{su^znlejZZ3+qDA&Stb{$AJ82$@SyrNGV%r^pzka-?U1EP}?0;viQMj8!o zYQ3$1UC(ku-SuF?=z8UjSE0nFhf_&R^eul?TJD$hV*{14H0AaDxPMh=KD1({eKvb^ zn-}_B%?>InshsXF9(L>JvkiLg3kayq#`?Xxdm4s9Xk#+mT+J7u&f}P!SGrQYcs)d= z{zx}I@k22+31m%{@bek34QEf5`8N{5X&KsnZScjMVmrH7*Ps(<_XqE$3%~)4mhAoZ zwT04;##qIcAUe8%(=s?4QMsbH?@n?N)z{oapBQ>3U$C^toi$~ebtEKDb8Yt*kt5G>qJ%XP1zhT z)x#ACr(=belQQ^HrxD7%C?}~~mO5LmD7UbmJn`H0QlR_b#slWE`*jz^g|OWzb6JuQ z((@wgFN@>#;?*X1UY5qOc4Te{gJP24H4RlA(!jGd!lxr=+5s;TNguWHeZslzma^NM zBE*P+b6Rv*@YMtGC;7e zYSb&4tiCu#QDH1Tmr8u@OimC*P9I1j%40Qx@iDS(6O#t2{-G%nrQ_lZ_vkasJ+5PR zO-Sb$H5Lwf{cXU%m+4aF2R4tqXKtr@3w-vPOxw81&*`*b?3Ue6^y#yUmhzxLoAeR6 zM*0P=Fnxufu&kV*j+p|Z?|B5>GEVW&Tym#GU@n2gBMp^!S-wE^Vw(cjeR$T0-{Y(H z&3=x4ucfI8ju5lRc(}Ei;43L?V81TT_mDC?izy;BVo#Z4s$1p0De zT(4Juv$_Dk_jghEe^Ec6*Wh0*CI4kLs9x$njLHA_^RKpqzse&1socQZ9f_%wHX>D| zL<=yriWf|Vvn+<#O5`n;W8lp^9x|kPY%e$?$4v7H+LILes4FS^@a+qVEqaI(9~|b* z7tt#jvv>Pit&Oo41TK}1pVYeGxbTD5`jhY;z-obq`+O3xQ`3<{LgY@hz}c5$E4A!y zcJgEzyWkBK2y*-gg6tA!?DXnH_Fj56jRMyaR0MoSkXe0kNHLQ{zs%Y!EH+HctAE{P zp!o|v9xMxNmy^TbEdzmDg3=|6WS&*U<63!qTV}R<|$QfNp zzpfC_qB}1>2agv-uXPe8i5)0aO~=Wvf>62y-CFh*}Dq= zgBS!UVNOp%Fc4ZF^_%RETW5>4AQId*L6oOmVFozHlD_8n&iH(ozf${BV!I=f*1`aL z*Q{iR$`;7X<_CS{gq9NqO#mC8VlOXy@2y(Iq60)pMNYT(K>d%ps{6r;A_YU84?sq$9}0?CSYn%vc%YfL@Ho&fx+_Rwna}4Kq2gsLJ-0D>i2Y*4bBIn*Zr8~G;IA9sIsAu)+%*02Uv3fr0ql}*^c-*RZ-vt3g;4x|xFMAjvTI)Gk=CHZR-Kesh(P1wWIh0lG+Sv2h z+JYu)U`&EG%GB**Nk$Y}(f&_n{&@Jp!TzKdUw)@!e!E=|tIGf%0IcZ(l2y(9ac#tB z6ZiF?(Ju6;?3!h2O7dRX{#C7P@-B}{Io#T@+p{I^_h}p>w;EQbS(TBi>IeBUtQKa> zXKt5;uSu3IWdEA*2C`lKSV#jb_1rmh2=Tq`9w9hz?Sc&V1#;8S*M>5Sgdbk?qQ-|FjH++MR`L8rJ&b3-hPI8F4;Jo45`{w&s7Mw zUm@17H&3sy@Lcv6LYtWiLrW3TMN&`j9O?FxQq z7;6*zT`=3^1?#R8lO?e)yPGLL3v>!?$Vc&35}eqt&=o-hE6%^)L*Il2 zPI1>)VDJDe>>~_2My_kdx+X;gmxK+Mm8rJsUmB*fM%Nci-K?LQu*wbiI+^^U^zRD;ol!^Of#?h_D!>&u!1q>aT z4dP?EwzqMv>7WS|6XOncjj1F?nm8DnNioZb24p}ugP zfseecLyRQ>ykTj-(0mS6d@=xTC(mNBgx;cg2DLJr7!)=K0-{Ea7)Hj{_MYNBX2iLED1@FB( zuugI0q9D+m zrVbrLBd+pd3rrcgUSn<1Yek}$tv;ZRU4cazB0JfnTQKL)(!;1=yk|}QFilU;ru&rZ zkRe?IYHyCiDUL8rt+x{vnKEMB$an3?XYZ59+#bBmJ3!X1?i`Ow%$yU4vy4>}QAq{K zi&%$;Z>-r>iYu1<7OY zeieRb2WQ3N$?_`>zh}WSfV)iXfdE=+I42BR8On({46#zpYt9aI)Qdg-^I|#rkvAW+ z#it^$@5@0s>-xTxh9)vniOFweOT$G2O>ZSby z7~f>v!1fJ`us=HkHpqpY_E}A(`DGeKKzhtxrl)!5_ZOhvEN)48JSZY#@izzxIe!D5!_`Es>i)}~%O{{cc|bz&C3~I)o}xnA zYo3P`KbT0`ZTHCHR_r&NV`B`LuM<9XgH9JDaSwpOgXgH%vP0hB(*E{bfSW=4M{ttM zIuFdO%*%=yThPSmZUJ$19wGXlruN%Pro}>Xi->zR@pE9PXa9;Hf&o>JFxv58 zt7})H-)3cszf4L`XAJqd#v8|D$A2zx*E9A-9?!H*0G$N!l&Xdo3lp9lydCvARXdhlC6A%7{p!+9# zS$OIv1A`2HEc*eH0vFxt0-79d{G~HIKLqTC2zER7@l&_>A8l{RNT4I-%76Ea!56HE z?+~iDt!UEMr57<>PN|7nR{gTJPPGjL!8XL6XJ51!wAL)1ZucdCX33Nb>`ek{8pq_R ze>9Bm)eM0Xw8P! zKX@GF%YM4r+TbK6OK=_| z%0P2##3KfLhth9mydZ*eAU)0uggoK*iP9%BkmH2ZR(g70X$=?3_8-MYdz{t+E!-ENa<71Egj@Rc9eGrz_J2lvWf zzy5ObWx-^%Ek62w|20_%naF_M=aSf4H#F(OM^4{mQtCo%P04H*nH95 zA1Exx;?jOEF#l25HD*HdoQn(__!#k9EerBzPAV4!&U!O}lNRU4(Cc0>u^xH&NTfb|3S9#yDr9Dm*ad#g^&5h#TB`< ziTdeW=Ia@;ZZSrl&f&2jUTC9@j9HEbYku_KH(uUaQu)`(HA7q5d5kIMw4c`2-?d$Q ze+$+i@8&3wyH_-{FR}#bTLQ{PzQjF-~7vY-vjFJD!0VoJfDm_bMn>&DYM7){@*Xom)M^EF{UT4V=5ap+0u52ER`KNqR zk$=FHa3@L*=ok1-@(APCmvut~jTOIqgbRhlJ5c1&W)A-8M1Hd>6bHK utU!RQ#fF{K-d?WrlMyWc<9aPpc2Q8cJ%=Dx Date: Thu, 4 Nov 2021 20:13:34 +0800 Subject: [PATCH 615/756] Add some parts of PPP --- docs/team/lezongmun.md | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/docs/team/lezongmun.md b/docs/team/lezongmun.md index dd70386a31..68f522e388 100644 --- a/docs/team/lezongmun.md +++ b/docs/team/lezongmun.md @@ -1,6 +1,41 @@ -# Mun Le Zong - Project Portfolio Page +# Mun Le Zong's Project Portfolio Page ## Overview +**ConTech** is a Command Line Interface (CLI) application for managing computing-related contacts. +The project started on 3 September 2021, where our team brainstormed and came up with our target users and app +direction. We proceeded to create user stories related to our desired product and narrowed them down for each +iteration so that we were able to comfortably deliver our features. + +### Summary of Contributions + +### Code contributed +The code written by me (`lezongmun`) can be found [here](https://nus-cs2113-ay2122s1.github.io/tp-dashboard/?search=lezongmun&sort=groupTitle&sortWithin=title&timeframe=commit&mergegroup=&groupSelect=groupByRepos&breakdown=true&checkedFileTypes=docs~functional-code~test-code~other&since=2021-09-25&tabOpen=true&tabAuthor=lezongmun&tabRepo=AY2122S1-CS2113T-T09-1%2Ftp%5Bmaster%5D&authorshipIsMergeGroup=false&authorshipFileTypes=docs~functional-code~test-code&authorshipIsBinaryFileTypeChecked=false&tabType=authorship). +
+ +### Enhancements implemented +1. `rm` feature + - Feature to allow users to delete selected contacts or all contacts at once from the ConTech Book. +2. `me` feature + - Feature to allow users to view their saved personal contact details. +3. Personal Contact System + - Creation of personal contact for first time use + - Saving of personal contact details using `ContactsEncoder.java` + - Loading of saved personal contact details in `Storage.java` using `ContactsDecoder.java` for subsequent runs +4. Parsers + - `AddPersonalContactParser.java`: Parser that is responsible for prompting users to input their personal contact + details and parsing them into `Contact` details for their personal contact + - `IndexParser`: Parser that is responsible for obtaining the `Contact` index from a user input command string. Used + for commands involving `Contact` indexes like `rm`, `view` and `edit` commands. + +### Contributions to UG +- Added documentation for features `me` and `rm` +- Tweaked documentation (formatting, usages, examples) for features with `all` and `me` as inputs + +### Contributions to DG +- Added implementation details and class diagram for `Storage` system +- Added implementation details and sequence diagrams for `rm` feature (delete selected contacts, delete all contacts and + delete contact fields) + +### Team-based tasks -### Summary of Contributions \ No newline at end of file From 2774f8e8dcf8ecb47a0ac568f8a23861bd5d2b45 Mon Sep 17 00:00:00 2001 From: lezong Date: Thu, 4 Nov 2021 20:18:36 +0800 Subject: [PATCH 616/756] Minor edits to AboutUs --- docs/AboutUs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index d7616a4fe8..6205fdbbfa 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -4,7 +4,7 @@ Display | Name | Github Profile | Portfolio --------|:----:|:--------------:|:---------: ![](https://via.placeholder.com/100.png?text=Photo) | Marcus Ong | [Github](https://github.com/marcusbory) | [Portfolio](docs/team/marcusbory.md) ![](https://via.placeholder.com/100.png?text=Photo) | Andre | [Github](https://github.com/ng-andre) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Mun Le Zong | [Github](https://github.com/lezongmun) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Mun Le Zong | [Github](https://github.com/lezongmun) | [Portfolio](docs/team/lezongmun.md) ![](https://via.placeholder.com/100.png?text=Photo) | Mayank Panjiyara | [Github](https://github.com/mayankp291) | [Portfolio](docs/team/johndoe.md) ![Ashraf](https://via.placeholder.com/100.png?text=Photo) | Ashraf| [Github](https://github.com/ashrafjfr) | [Portfolio](docs/team/johndoe.md) From 91f5de91a5f707849f6f9aceb48d8a161b6b9ebc Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Thu, 4 Nov 2021 21:11:34 +0800 Subject: [PATCH 617/756] Update error messages --- src/main/java/seedu/ui/ExceptionTextUi.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index 8ed227e116..2e915edc4d 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -188,17 +188,17 @@ public static void missingIndexMessage() { public static void missingIndexViewMessage(int ListSize) { String message; if (ListSize == 0) { - message = "There seems to be missing index in your request.\n" + message = "There seems to be missing or invalid index in your request.\n" + "Please enter command in the following way:\n" + " view \n" + "Enter as \"me\" to view personal contact"; } else if (ListSize == 1) { - message = "There seems to be missing index in your request.\n" + message = "There seems to be missing or invalid index in your request.\n" + "Please enter command in the following way:\n" + " view \n" + "Enter as 0 or \"me\" (personal contact)"; } else { - message = "There seems to be missing index in your request.\n" + message = "There seems to be missing or invalid index in your request.\n" + "Please enter command in the following way:\n" + " view \n" + "Enter between 0 and " + (ListSize - 1) + " or \"me\" (personal contact)"; @@ -210,19 +210,19 @@ public static void missingIndexViewMessage(int ListSize) { public static void missingIndexDeleteMessage(int ListSize) { String message; if (ListSize == 0) { - message = "There seems to be missing index in your request.\n" + message = "There seems to be missing or invalid index in your request.\n" + "Please enter command in the following way:\n" - + " rm \n" + + " rm {REMOVE_DETAIL_FLAGS}\n" + "Enter as \"me\" to view personal contact"; } else if (ListSize == 1) { - message = "There seems to be missing index in your request.\n" + message = "There seems to be missing or invalid index in your request.\n" + "Please enter command in the following way:\n" - + " view \n" + + " rm {REMOVE_DETAIL_FLAGS}\n" + "Enter as 0 or \"me\" (personal contact)"; } else { - message = "There seems to be missing index in your request.\n" + message = "There seems to be missing or invalid index in your request.\n" + "Please enter command in the following way:\n" - + " view \n" + + " rm {REMOVE_DETAIL_FLAGS}\n" + "Enter between 0 and " + (ListSize - 1) + " or \"me\" (personal contact)"; } printDoubleLineMessage(message); From 01f2a32ccdf1b82b5018ee627a0c9fcef70c6a7a Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Thu, 4 Nov 2021 21:11:53 +0800 Subject: [PATCH 618/756] Add new failed commands --- src/main/java/seedu/command/FailedCommand.java | 3 +++ src/main/java/seedu/parser/MainParser.java | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/command/FailedCommand.java b/src/main/java/seedu/command/FailedCommand.java index 386d2b204f..85dc769605 100644 --- a/src/main/java/seedu/command/FailedCommand.java +++ b/src/main/java/seedu/command/FailedCommand.java @@ -37,6 +37,8 @@ public void execute() { case MISSING_DETAIL: // Fallthrough case MISSING_NAME: // Fallthrough case MISSING_INDEX: // Fallthrough + case MISSING_INDEX_VIEW: // Fallthrough + case MISSING_INDEX_DELETE: // Fallthrough case INVALID_INDEX_EDIT: missingUserInputExecute(); break; @@ -101,6 +103,7 @@ private void missingUserInputExecute() { break; case MISSING_INDEX_DELETE: ExceptionTextUi.missingIndexDeleteMessage(contactList.getListSize()); + break; case INVALID_INDEX_EDIT: ExceptionTextUi.missingIndexEditMessage(); break; diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index fe93680496..74a84ae3a2 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -257,7 +257,7 @@ private Command parseDeleteContact(String userInput) { } catch (IndexOutOfBoundsException e) { return new FailedCommand(FailedCommandType.NUM_OUT_OF_BOUND); } catch (MissingIndexException | NumberFormatException e) { - return new FailedCommand(FailedCommandType.MISSING_INDEX); + return new FailedCommand(FailedCommandType.MISSING_INDEX_DELETE); } catch (InvalidFlagException e) { return new FailedCommand(FailedCommandType.INVALID_FLAG); } catch (InvalidDeleteDetailException e) { From 24254d9065bac35d7f12072da6b1c2b41df427fd Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Thu, 4 Nov 2021 21:21:58 +0800 Subject: [PATCH 619/756] Update code to adhere to checkstyle --- src/main/java/seedu/ui/ExceptionTextUi.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index 2e915edc4d..288d645f46 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -185,14 +185,14 @@ public static void missingIndexMessage() { } //@@author mayankp291 - public static void missingIndexViewMessage(int ListSize) { + public static void missingIndexViewMessage(int listSize) { String message; - if (ListSize == 0) { + if (listSize == 0) { message = "There seems to be missing or invalid index in your request.\n" + "Please enter command in the following way:\n" + " view \n" + "Enter as \"me\" to view personal contact"; - } else if (ListSize == 1) { + } else if (listSize == 1) { message = "There seems to be missing or invalid index in your request.\n" + "Please enter command in the following way:\n" + " view \n" @@ -201,20 +201,20 @@ public static void missingIndexViewMessage(int ListSize) { message = "There seems to be missing or invalid index in your request.\n" + "Please enter command in the following way:\n" + " view \n" - + "Enter between 0 and " + (ListSize - 1) + " or \"me\" (personal contact)"; + + "Enter between 0 and " + (listSize - 1) + " or \"me\" (personal contact)"; } printDoubleLineMessage(message); } //@@author mayankp291 - public static void missingIndexDeleteMessage(int ListSize) { + public static void missingIndexDeleteMessage(int listSize) { String message; - if (ListSize == 0) { + if (listSize == 0) { message = "There seems to be missing or invalid index in your request.\n" + "Please enter command in the following way:\n" + " rm {REMOVE_DETAIL_FLAGS}\n" + "Enter as \"me\" to view personal contact"; - } else if (ListSize == 1) { + } else if (listSize == 1) { message = "There seems to be missing or invalid index in your request.\n" + "Please enter command in the following way:\n" + " rm {REMOVE_DETAIL_FLAGS}\n" @@ -223,7 +223,7 @@ public static void missingIndexDeleteMessage(int ListSize) { message = "There seems to be missing or invalid index in your request.\n" + "Please enter command in the following way:\n" + " rm {REMOVE_DETAIL_FLAGS}\n" - + "Enter between 0 and " + (ListSize - 1) + " or \"me\" (personal contact)"; + + "Enter between 0 and " + (listSize - 1) + ", \"me\" (personal contact) or \"all\""; } printDoubleLineMessage(message); } From efbf82724d7b54c99739f2e7c06387c73f79133a Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Thu, 4 Nov 2021 21:26:04 +0800 Subject: [PATCH 620/756] Update tests --- src/test/java/seedu/parser/MainParserTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/java/seedu/parser/MainParserTest.java b/src/test/java/seedu/parser/MainParserTest.java index dadc03d4fe..d2b2b27f45 100644 --- a/src/test/java/seedu/parser/MainParserTest.java +++ b/src/test/java/seedu/parser/MainParserTest.java @@ -81,7 +81,7 @@ public void parseDeleteCommand_validIndexWithSpaces_expectDeleteContactIndexMatc @Test public void parseDeleteCommand_missingIndex_expectFailedCommandType() { testUserInput = "rm"; - FailedCommandType expectedFailedCommandType = FailedCommandType.MISSING_INDEX; + FailedCommandType expectedFailedCommandType = FailedCommandType.MISSING_INDEX_DELETE; final FailedCommand actualFailedCommand = getParsedCommand(testUserInput, FailedCommand.class); assertEquals(expectedFailedCommandType, actualFailedCommand.getType()); } @@ -89,7 +89,7 @@ public void parseDeleteCommand_missingIndex_expectFailedCommandType() { @Test public void parseDeleteCommand_invalidNumber_expectFailedCommandType() { testUserInput = "rm abc"; - FailedCommandType expectedFailedCommandType = FailedCommandType.MISSING_INDEX; + FailedCommandType expectedFailedCommandType = FailedCommandType.MISSING_INDEX_DELETE; final FailedCommand actualFailedCommand = getParsedCommand(testUserInput, FailedCommand.class); assertEquals(expectedFailedCommandType, actualFailedCommand.getType()); } @@ -267,7 +267,7 @@ public void parseViewCommand_validIndexWithSpaces_expectViewContactIndexMatch() @Test public void parseViewCommand_missingIndex_expectFailedCommandType() { testUserInput = "view"; - FailedCommandType expectedFailedCommandType = FailedCommandType.MISSING_INDEX; + FailedCommandType expectedFailedCommandType = FailedCommandType.MISSING_INDEX_VIEW; final FailedCommand actualFailedCommand = getParsedCommand(testUserInput, FailedCommand.class); assertEquals(expectedFailedCommandType, actualFailedCommand.getType()); } @@ -276,7 +276,7 @@ public void parseViewCommand_missingIndex_expectFailedCommandType() { @Test public void parseViewCommand_invalidInput_expectFailedCommandType() { testUserInput = "view abc"; - FailedCommandType expectedFailedCommandType = FailedCommandType.MISSING_INDEX; + FailedCommandType expectedFailedCommandType = FailedCommandType.MISSING_INDEX_VIEW; final FailedCommand actualFailedCommand = getParsedCommand(testUserInput, FailedCommand.class); assertEquals(expectedFailedCommandType, actualFailedCommand.getType()); } From 81813e8a578d948f9796f375e707a28a46f2af9a Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Thu, 4 Nov 2021 21:27:27 +0800 Subject: [PATCH 621/756] Update IO tests --- text-ui-test/ACTUAL.TXT | 12 ++++++------ text-ui-test/EXPECTED-UNIX.TXT | 12 ++++++------ text-ui-test/EXPECTED.TXT | 12 ++++++------ 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index e4d727ecc6..2f64ad844c 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -133,8 +133,8 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing or invalid index in your request. Please enter command in the following way: - {REMOVE_DETAIL_FLAGS} -Where is rm or view + view +Enter as 0 or "me" (personal contact) ____________________________________________________________ ____________________________________________________________ @@ -234,8 +234,8 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing or invalid index in your request. Please enter command in the following way: - {REMOVE_DETAIL_FLAGS} -Where is rm or view + rm {REMOVE_DETAIL_FLAGS} +Enter between 0 and 4, "me" (personal contact) or "all" ____________________________________________________________ ____________________________________________________________ @@ -378,8 +378,8 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing or invalid index in your request. Please enter command in the following way: - {REMOVE_DETAIL_FLAGS} -Where is rm or view + view +Enter between 0 and 3 or "me" (personal contact) ____________________________________________________________ ____________________________________________________________ diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index e4d727ecc6..2f64ad844c 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -133,8 +133,8 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing or invalid index in your request. Please enter command in the following way: - {REMOVE_DETAIL_FLAGS} -Where is rm or view + view +Enter as 0 or "me" (personal contact) ____________________________________________________________ ____________________________________________________________ @@ -234,8 +234,8 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing or invalid index in your request. Please enter command in the following way: - {REMOVE_DETAIL_FLAGS} -Where is rm or view + rm {REMOVE_DETAIL_FLAGS} +Enter between 0 and 4, "me" (personal contact) or "all" ____________________________________________________________ ____________________________________________________________ @@ -378,8 +378,8 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing or invalid index in your request. Please enter command in the following way: - {REMOVE_DETAIL_FLAGS} -Where is rm or view + view +Enter between 0 and 3 or "me" (personal contact) ____________________________________________________________ ____________________________________________________________ diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index e4d727ecc6..2f64ad844c 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -133,8 +133,8 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing or invalid index in your request. Please enter command in the following way: - {REMOVE_DETAIL_FLAGS} -Where is rm or view + view +Enter as 0 or "me" (personal contact) ____________________________________________________________ ____________________________________________________________ @@ -234,8 +234,8 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing or invalid index in your request. Please enter command in the following way: - {REMOVE_DETAIL_FLAGS} -Where is rm or view + rm {REMOVE_DETAIL_FLAGS} +Enter between 0 and 4, "me" (personal contact) or "all" ____________________________________________________________ ____________________________________________________________ @@ -378,8 +378,8 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing or invalid index in your request. Please enter command in the following way: - {REMOVE_DETAIL_FLAGS} -Where is rm or view + view +Enter between 0 and 3 or "me" (personal contact) ____________________________________________________________ ____________________________________________________________ From d81979235f7403a1ef4e2005c52032e0da84c4ed Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Thu, 4 Nov 2021 21:29:22 +0800 Subject: [PATCH 622/756] Add personal profile file --- docs/team/mayankp291.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/team/mayankp291.md diff --git a/docs/team/mayankp291.md b/docs/team/mayankp291.md new file mode 100644 index 0000000000..e69de29bb2 From 89bb68cb6c71b4bfea4aa653740c447e917ddf39 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Thu, 4 Nov 2021 21:49:24 +0800 Subject: [PATCH 623/756] Draft PPP --- docs/team/mayankp291.md | 53 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/docs/team/mayankp291.md b/docs/team/mayankp291.md index e69de29bb2..564fc465cc 100644 --- a/docs/team/mayankp291.md +++ b/docs/team/mayankp291.md @@ -0,0 +1,53 @@ +# mayankp291's Product Portfolio Page (PPP) + +## Overview + +**ConTech** is a Command Line Interface (CLI) application for managing computing-related contacts. + +The project started on 3 September 2021, where our team brainstormed and came up with our target users and app +direction. We proceeded to create user stories related to our desired product and narrowed them down for each iteration +so that we were able to comfortably deliver our features. + +## Summary of contributions + +### Code contributed + +The code written by me (`mayankp291`) can be +found [here](https://nus-cs2113-ay2122s1.github.io/tp-dashboard/?search=mayank&sort=groupTitle&sortWithin=title&timeframe=commit&mergegroup=&groupSelect=groupByRepos&breakdown=true&checkedFileTypes=docs~functional-code~test-code~other&since=2021-09-25&tabOpen=true&tabType=authorship&tabAuthor=mayankp291&tabRepo=AY2122S1-CS2113T-T09-1%2Ftp%5Bmaster%5D&authorshipIsMergeGroup=false&authorshipFileTypes=docs~functional-code~test-code&authorshipIsBinaryFileTypeChecked=false) +. +
+ +### Enhancements implemented + +1. `list` feature + - Added the feature to list all contacts with their index and name. +2. Parsers + - `RegexParser.java`: Add Input Validation for contact fields added to ConTech. Covers fields - Name, GitHub, Email, + Twitter and Telegram. The usernames are checked against requirements from the respectable companies. +3. Exception handling + - Add exceptions to cover more test cases and provide clear error messages. +4. Sorting of contacts + - Store contacts sorted in ascending order in the `ContactList` structure. + - Sort after every contact is added, edited, or imported. +5. System testing and writing tests + - Written tests for various functions and increase test coverage. + - Tested every component and made sure the program worked as expected + +### Contributions to UG + +The link to the User Guide (UG) can be found [here](https://ay2122s1-cs2113t-t09-1.github.io/tp/UserGuide.html). + +### Contributions to DG + +The link to the Developer Guide (DG) can be found [here](https://ay2122s1-cs2113t-t09-1.github.io/tp/DeveloperGuide. +html). + +### Team-based tasks + +- Attended and contributed to weekly brainstorming session during ideation phases (V1.0, V2.0, V2.1) +- Maintained issue tracker (ensured that PRs were tagged to according Milestones and labels) +- Updated gradle and testing scripts + +### Community + +Reported 13 Bugs during PE Dry Run and suggested ways to solve them. From bb0e15b02d0ad51f7f1c78b14aecacb5130554db Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Thu, 4 Nov 2021 21:58:49 +0800 Subject: [PATCH 624/756] Update regex check for name --- src/main/java/seedu/parser/RegexParser.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/seedu/parser/RegexParser.java b/src/main/java/seedu/parser/RegexParser.java index 373c09601e..6cd76c91a6 100644 --- a/src/main/java/seedu/parser/RegexParser.java +++ b/src/main/java/seedu/parser/RegexParser.java @@ -57,7 +57,6 @@ public void checkRegex(String flag, String detailToParse) protected void checkEmailRegex(String detailToParse) throws InvalidEmailException { //allow lowercase email ids - String emailRegex1 = "^([\\w-\\.]+){1,64}@([\\w&&[^_]]+){2,255}.[a-z]{2,}$"; String emailRegex = "^(([^<>()\\[\\]\\\\.,;:\\s@\"]+(\\.[^<>()\\[\\]\\\\.,;:\\s@\"]+)*)|" + "(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|" + "(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$"; @@ -108,7 +107,7 @@ protected void checkGithubUsernameRegex(String detailToParse) throws InvalidGith protected void checkNameRegex(String detailToParse) throws InvalidNameException { //only letters and spaces allowed - String nameRegex = "^([a-zA-Z]+\\s)*[a-zA-Z]+$"; + String nameRegex = "^([a-zA-Z.']+\\s)*[a-zA-Z.']+$"; if (!detailToParse.matches(nameRegex)) { LOGGER.log(Level.FINE, "Regex check for name failed"); throw new InvalidNameException(); From c6195c7a895d15c9ac255e2974e6247508ae6384 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Thu, 4 Nov 2021 22:09:48 +0800 Subject: [PATCH 625/756] Add link to PPP --- docs/AboutUs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 6205fdbbfa..9ff7066479 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -5,6 +5,6 @@ Display | Name | Github Profile | Portfolio ![](https://via.placeholder.com/100.png?text=Photo) | Marcus Ong | [Github](https://github.com/marcusbory) | [Portfolio](docs/team/marcusbory.md) ![](https://via.placeholder.com/100.png?text=Photo) | Andre | [Github](https://github.com/ng-andre) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Mun Le Zong | [Github](https://github.com/lezongmun) | [Portfolio](docs/team/lezongmun.md) -![](https://via.placeholder.com/100.png?text=Photo) | Mayank Panjiyara | [Github](https://github.com/mayankp291) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Mayank Panjiyara | [Github](https://github.com/mayankp291) | [Portfolio](docs/team/mayankp291.md) ![Ashraf](https://via.placeholder.com/100.png?text=Photo) | Ashraf| [Github](https://github.com/ashrafjfr) | [Portfolio](docs/team/johndoe.md) From 28e0cf0dc72bd4e3811f79bd801cd43d53223661 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Thu, 4 Nov 2021 22:19:25 +0800 Subject: [PATCH 626/756] Add more symbols for name validation --- src/main/java/seedu/parser/RegexParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/RegexParser.java b/src/main/java/seedu/parser/RegexParser.java index 6cd76c91a6..2c4c849f60 100644 --- a/src/main/java/seedu/parser/RegexParser.java +++ b/src/main/java/seedu/parser/RegexParser.java @@ -107,7 +107,7 @@ protected void checkGithubUsernameRegex(String detailToParse) throws InvalidGith protected void checkNameRegex(String detailToParse) throws InvalidNameException { //only letters and spaces allowed - String nameRegex = "^([a-zA-Z.']+\\s)*[a-zA-Z.']+$"; + String nameRegex = "^([a-zA-Z.'/-]+\\s)*[a-zA-Z.']+$"; if (!detailToParse.matches(nameRegex)) { LOGGER.log(Level.FINE, "Regex check for name failed"); throw new InvalidNameException(); From 7416f26ce0eab3dc8cdfc1c02febd1e53f1c16b3 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Thu, 4 Nov 2021 22:31:18 +0800 Subject: [PATCH 627/756] Update regex --- src/main/java/seedu/parser/RegexParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/RegexParser.java b/src/main/java/seedu/parser/RegexParser.java index 2c4c849f60..c9751cab05 100644 --- a/src/main/java/seedu/parser/RegexParser.java +++ b/src/main/java/seedu/parser/RegexParser.java @@ -107,7 +107,7 @@ protected void checkGithubUsernameRegex(String detailToParse) throws InvalidGith protected void checkNameRegex(String detailToParse) throws InvalidNameException { //only letters and spaces allowed - String nameRegex = "^([a-zA-Z.'/-]+\\s)*[a-zA-Z.']+$"; + String nameRegex = "^([a-zA-Z.'/-]+\\s)*[a-zA-Z.'/-]+$"; if (!detailToParse.matches(nameRegex)) { LOGGER.log(Level.FINE, "Regex check for name failed"); throw new InvalidNameException(); From 2a6ae7c1b7b15623a58d2ed51680dbda44c274c0 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Thu, 4 Nov 2021 22:37:56 +0800 Subject: [PATCH 628/756] Update AboutUs.md filepath --- docs/AboutUs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 6205fdbbfa..7dfd4f46ce 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -2,9 +2,9 @@ Display | Name | Github Profile | Portfolio --------|:----:|:--------------:|:---------: -![](https://via.placeholder.com/100.png?text=Photo) | Marcus Ong | [Github](https://github.com/marcusbory) | [Portfolio](docs/team/marcusbory.md) +![](https://via.placeholder.com/100.png?text=Photo) | Marcus Ong | [Github](https://github.com/marcusbory) | [Portfolio](team/marcusbory.md) ![](https://via.placeholder.com/100.png?text=Photo) | Andre | [Github](https://github.com/ng-andre) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Mun Le Zong | [Github](https://github.com/lezongmun) | [Portfolio](docs/team/lezongmun.md) +![](https://via.placeholder.com/100.png?text=Photo) | Mun Le Zong | [Github](https://github.com/lezongmun) | [Portfolio](team/lezongmun.md) ![](https://via.placeholder.com/100.png?text=Photo) | Mayank Panjiyara | [Github](https://github.com/mayankp291) | [Portfolio](docs/team/johndoe.md) ![Ashraf](https://via.placeholder.com/100.png?text=Photo) | Ashraf| [Github](https://github.com/ashrafjfr) | [Portfolio](docs/team/johndoe.md) From bf9db8f036334c25a9aa89fdf73c9daaed914ab8 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Thu, 4 Nov 2021 22:42:15 +0800 Subject: [PATCH 629/756] Remove "-" symbol for nameregex --- src/main/java/seedu/parser/RegexParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/RegexParser.java b/src/main/java/seedu/parser/RegexParser.java index c9751cab05..51ecb2494d 100644 --- a/src/main/java/seedu/parser/RegexParser.java +++ b/src/main/java/seedu/parser/RegexParser.java @@ -107,7 +107,7 @@ protected void checkGithubUsernameRegex(String detailToParse) throws InvalidGith protected void checkNameRegex(String detailToParse) throws InvalidNameException { //only letters and spaces allowed - String nameRegex = "^([a-zA-Z.'/-]+\\s)*[a-zA-Z.'/-]+$"; + String nameRegex = "^([a-zA-Z.'/]+\\s)*[a-zA-Z.'/]+$"; if (!detailToParse.matches(nameRegex)) { LOGGER.log(Level.FINE, "Regex check for name failed"); throw new InvalidNameException(); From e4f55231b47c06f85bf49c9d20997d6235c9d5bc Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Thu, 4 Nov 2021 22:48:19 +0800 Subject: [PATCH 630/756] Update AboutUS --- docs/AboutUs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index d7616a4fe8..2c0ac1da91 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -3,7 +3,7 @@ Display | Name | Github Profile | Portfolio --------|:----:|:--------------:|:---------: ![](https://via.placeholder.com/100.png?text=Photo) | Marcus Ong | [Github](https://github.com/marcusbory) | [Portfolio](docs/team/marcusbory.md) -![](https://via.placeholder.com/100.png?text=Photo) | Andre | [Github](https://github.com/ng-andre) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Andre | [Github](https://github.com/ng-andre) | [Portfolio](docs/team/ng-andre.md) ![](https://via.placeholder.com/100.png?text=Photo) | Mun Le Zong | [Github](https://github.com/lezongmun) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Mayank Panjiyara | [Github](https://github.com/mayankp291) | [Portfolio](docs/team/johndoe.md) ![Ashraf](https://via.placeholder.com/100.png?text=Photo) | Ashraf| [Github](https://github.com/ashrafjfr) | [Portfolio](docs/team/johndoe.md) From 0749b4e960a1d225a3d320851cb6009098c82be1 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Thu, 4 Nov 2021 22:48:25 +0800 Subject: [PATCH 631/756] Add ng-andre PPP --- docs/team/ng-andre.md | 52 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 docs/team/ng-andre.md diff --git a/docs/team/ng-andre.md b/docs/team/ng-andre.md new file mode 100644 index 0000000000..45aacd81cc --- /dev/null +++ b/docs/team/ng-andre.md @@ -0,0 +1,52 @@ +# Ng Andre - Project Portfolio Page + +## Overview +**ConTech** is a Command Line Interface (CLI) application for managing computing-related contacts. + +The project started on 3 September 2021, where our team brainstormed and came up with our target users and app +direction. We proceeded to create user stories related to our desired product and narrowed them down for each +iteration so that we were able to comfortably deliver our features. + + +## Summary of Contributions + +### Code Contributed +The code written by me (`ng-andre`) can be found [here](https://nus-cs2113-ay2122s1.github.io/tp-dashboard/?search=ng-andre&sort=groupTitle&sortWithin=title&since=2021-09-25&timeframe=commit&mergegroup=&groupSelect=groupByRepos&breakdown=falsehttps://nus-cs2113-ay2122s1.github.io/tp-dashboard/?search=ng-andre&sort=groupTitle&sortWithin=title&since=2021-09-25&timeframe=commit&mergegroup=&groupSelect=groupByRepos&breakdown=false). + + +### Enhancements Implemented + +1. `Edit` feature + - Command to allow the user to edit a contact's details + - Implementation allows flexible user input with minimal restrictions +2. `Search` feature + - Command to allow the user to search for a contact + - Implementation allows flexible user input with optional flags for searching +3. Flags for `delete` feature + - Update command to allow users to specify a field to be deleted for a contact + - Implementation allows optional user input for flags to specify deleted fields +4. Parsers + - `EditContactParser.java`: Parses user input, specified index and specified flags, and creates a syntactically valid `EditContactCommand` to be executed + - `SearchContactParser.java`: Parses user input for search query and optional flag, and creates a syntactically valid `SearchContactCommand` to be executed + - `IndexParser.java`: Parses the index specified by the user input for all commands and returns the corresponding `int` value + + +### Contributions to the UG +- Added documentation for `edit` function +- Added documentation for `search` function +- Updated documentation formatting and overall readability + +### Contributions to the DG +- Added documentation for `edit` function +- Added documentation for `search` function +- Added UML diagrams for all the above-mentioned features + +### Contributions to team-based tasks +- Handled release management and published v1.0 and v2.0 releases +- Updated User Guide (UG) and Developer Guide (DG) documentation that were not specific to any feature: + - Reviewed and updated overall User Guide and fixed inconsistencies between UG and error messages in application + +### Review/mentoring contributions +- Reviewed PRs and ensured overall code quality/formatting was up to standard + +### Contributions beyond the project team From b4d8c932a031a0bef8a78d4420784b283f8d1f1d Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Thu, 4 Nov 2021 22:58:04 +0800 Subject: [PATCH 632/756] Changed link of portfolio for ashrafjfr --- docs/AboutUs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 6205fdbbfa..d3f986c926 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -6,5 +6,5 @@ Display | Name | Github Profile | Portfolio ![](https://via.placeholder.com/100.png?text=Photo) | Andre | [Github](https://github.com/ng-andre) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Mun Le Zong | [Github](https://github.com/lezongmun) | [Portfolio](docs/team/lezongmun.md) ![](https://via.placeholder.com/100.png?text=Photo) | Mayank Panjiyara | [Github](https://github.com/mayankp291) | [Portfolio](docs/team/johndoe.md) -![Ashraf](https://via.placeholder.com/100.png?text=Photo) | Ashraf| [Github](https://github.com/ashrafjfr) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Ashraf| [Github](https://github.com/ashrafjfr) | [Portfolio](docs/team/ashrafjfr.md) From 9c09929c36ae8928bd107306b4b5e287ae80fe23 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Thu, 4 Nov 2021 22:58:23 +0800 Subject: [PATCH 633/756] Add PPP for ashrafjfr --- docs/team/ashrafjfr.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 docs/team/ashrafjfr.md diff --git a/docs/team/ashrafjfr.md b/docs/team/ashrafjfr.md new file mode 100644 index 0000000000..72314df94f --- /dev/null +++ b/docs/team/ashrafjfr.md @@ -0,0 +1,39 @@ +# ashrafjfr's Project Portfolio Page + +## Overview +**ConTech** is a Command Line Interface (CLI) application for managing computing-related contacts. + +The project started on 3 September 2021, where our team brainstormed and came up with our target users and app +direction. We proceeded to create user stories related to our desired product and narrowed them down for each +iteration so that we were able to comfortably deliver our features. + +### Summary of Contributions + +### Code contributed +The code written by me (`ashrafjfr`) can be found [here](https://nus-cs2113-ay2122s1.github.io/tp-dashboard/?search=ashrafjfr&sort=groupTitle&sortWithin=title&since=2021-09-25&timeframe=commit&mergegroup=&groupSelect=groupByRepos&breakdown=false&tabOpen=true&tabType=authorship&tabAuthor=ashrafjfr&tabRepo=AY2122S1-CS2113T-T09-1%2Ftp%5Bmaster%5D&authorshipIsMergeGroup=false&authorshipFileTypes=docs~functional-code~test-code&authorshipIsBinaryFileTypeChecked=false). +
+ +### Enhancements implemented +1. `view` feature + - Feature to allow users to view a selected contact based on its index from the ConTech Book. + - Also implemented `ViewMessageFormatterUI.java` in order to return a formatted string of what the application will + print for each field. +2. `help` feature + - Feature to allow users to find out all available commands in the application. +3. Duplicate Checker + - Implemented the duplicate checker for `add` and `edit` features and asks for users confirmation if there is + already a similar field in the ConTech Book. The duplicate checker methods are within the `AddContactCommand.java` + for the `add` feature and `EditContactCommand` for the `edit` feature. + + +### Contributions to UG +- Implemented the structure with reference from + [AddressBook Level 3 User Guide](https://se-education.org/addressbook-level3/UserGuide.html) +- Added the `Table of Contents` with links to each feature +- Added documentation for features `view` and `help` + +### Contributions to DG +- Added implementation details and sequence diagram for `view` feature +- Added table of user stories for `User Stories` section. + + From d726e5f5c2899418459988f171c529d22723428a Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sat, 6 Nov 2021 02:19:02 +0800 Subject: [PATCH 634/756] Update Table of Contents with new details --- docs/DeveloperGuide.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 562faf4214..24d9729681 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -2,6 +2,7 @@ ### Table of Content - [Acknowledgements](#acknowledgements) +- [Common Notations In DG](#notations) - [Design](#design) - [System Architecture](#sys-arch) - [TextUi](#text-ui) @@ -17,6 +18,7 @@ - [Deleting a contact](#Delete) - [Searching a contact](#Search) - [Listing all contacts](#List) + - [Importing contacts](#Import) - [Product Scope](#scope) - [Target user profile](#target) - [Value proposition](#value) From a44110ccafea9e9f9ea7ad8bce0b1377269f2089 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sat, 6 Nov 2021 02:20:34 +0800 Subject: [PATCH 635/756] Change acknowledgements to include hyperlink --- docs/DeveloperGuide.md | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 24d9729681..55a887718d 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -29,19 +29,12 @@ ##
Acknowledgements -- Inspiration for App Idea and OOP Structure: AddressBook (Level 2)
- https://github.com/se-edu/addressbook-level2 -- Inspiration for User Guide and Developer Guide: AddressBook (Level 3)
- https://se-education.org/addressbook-level3/DeveloperGuide.html
- https://se-education.org/addressbook-level3/UserGuide.html -- Converting text for ConTech:
- https://patorjk.com/software/taag/#p=display&f=Graffiti&t=Type%20Something%20 -- GitHub Markdown Emoji Syntax for User Guide:
- https://github.com/ikatyang/emoji-cheat-sheet/blob/master/README.md -- PlantUML Tutorial:
- https://se-education.org/guides/tutorials/plantUml.html - -{list here sources of all reused/adapted ideas, code, documentation, and third-party libraries -- include links to the original source as well} +- Inspiration for App Idea and OOP Structure: [AddressBook (Level 2)](https://github.com/se-edu/addressbook-level2)
+- Inspiration for User Guide and Developer Guide: AddressBook (Level 3) [[DG]](https://se-education.org/addressbook-level3/DeveloperGuide.html)
+ [[UG]](https://se-education.org/addressbook-level3/UserGuide.html) +- [Converting text for ConTech](https://patorjk.com/software/taag/#p=display&f=Graffiti&t=Type%20Something%20)
+- [GitHub Markdown Emoji Syntax](https://github.com/ikatyang/emoji-cheat-sheet/blob/master/README.md) for User Guide:
+- [PlantUML Tutorial](https://se-education.org/guides/tutorials/plantUml.html)
## Design From de98b731bfe362b7c60bff522e92d2b191fdb8b9 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sat, 6 Nov 2021 02:20:59 +0800 Subject: [PATCH 636/756] Add common notations for DG --- docs/DeveloperGuide.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 55a887718d..2c970d1396 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -36,6 +36,21 @@ - [GitHub Markdown Emoji Syntax](https://github.com/ikatyang/emoji-cheat-sheet/blob/master/README.md) for User Guide:
- [PlantUML Tutorial](https://se-education.org/guides/tutorials/plantUml.html)
+## Common Notations in DG +The common notations listed below will be used throughout the Developer Guide. +- Words in `UPPER_CASE` are meant to be parameters that can be supplied to the commands. + - e.g. When adding a contact, in the command `add -n NAME -g GITHUB`, `NAME` and `GITHUB` are parameters which + can be specified, such as `add -n Le Zong -g lezongmun`. + - e.g. When viewing a contact's details, in the command `view INDEX`, `INDEX` is a number (integer) representing + the contact's index in the **ConTech** book which can be specified, such as `view 2`. +- Items in curly braces `{}` are optional. +- Items in angle braces `<>` are mandatory. + - e.g. When specified in the format `<-n> {-g }`, it means that: + - The `-n` flag and `NAME` detail are mandatory fields, without which the command would not execute. + - The `-g` flag is optional, however, if used, a `GITHUB` detail would have to be specified. +- Items specified with a pipe `|` denote an either-or field. + - e.g. For `{-n | -g | -l | -te | -tw | -e}`, only **up to** one `flag` is allowed, but there are **six** choices. + ## Design ### System Architecture From cc3a245f12299107c8cbe71299ff2b318a098226 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sat, 6 Nov 2021 02:21:12 +0800 Subject: [PATCH 637/756] Update Storage component description --- docs/DeveloperGuide.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 2c970d1396..5c556f2d95 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -96,10 +96,17 @@ will be referred to later on. ![Storage Class Diagram](images/StorageClassDiagram.png) -The `Storage` component is responsible for saving both contacts data and personal contact data locally inside the file -paths, `data/contacts.txt` and `data/me.txt`. `Storage` is also responsible for loading these data back into their -corresponding `ContactList` and `Contact` objects. It is thus dependent on the classes, `ContactList` and -`Contact`. +The `Storage` component consists of the `Storage`, `ContactsDecoder`, and `ContactsEncoder`. This component is +responsible for interacting with the user's local storage files. The user's contacts data and personal contact data +are stored locally inside the file paths, `data/contacts.txt` and `data/me.txt`. + +Firstly, the `Storage` class checks if the user has existing data, or if they are first time users. Next, it will +make use of the `ContactsDecoder` class to decode the storage file and load the contacts into the `ContactList` as +`Contacts`. After every command execution, to ensure data integrity, the `Contacts` in the `ContactList` will be +saved using the `ContactsEncoder` class. + +As the `Storage` component is also responsible for loading these data into their corresponding `ContactList` and +`Contact` objects, it is dependent on the classes, `ContactList` and `Contact`. ## Implementation From a96558b871807b77f29f5f6bb01dea96554d5cca Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sat, 6 Nov 2021 02:22:48 +0800 Subject: [PATCH 638/756] Change command formats --- docs/DeveloperGuide.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 5c556f2d95..c36d93dc42 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -125,8 +125,8 @@ The currently supported contact details are provided in the table below: ### Adding a contact: `add` This feature is processed using `AddContactCommand`. This feature allows a user to add a contact to their contact list. -The user is able to add a contact by entering a command in the form of `add [DETAILS WITH FLAGS]`, where -the details with flags are specified in the form `- `. +The user is able to add a contact by entering a command in the form of `add <-n> {-g } {-l } +{-te } {-tw } {-e }`. The user's input is parsed in `MainParser` and `AddContactParser`, the latter which inherits `ContactParser`. `ContactParser` inherits `RegexParser` (for regex checks regarding each detail) and implements the `ContactDetails` @@ -144,7 +144,7 @@ executed in `Duke`. The sequence diagram below illustrates the process of execut ### Viewing a contact: `view` This feature is processed using `ViewContactCommand`. Whenever a user wants to view a specific contact from the -contact list, user can input `view [INDEX]` with the index of the desired contact displayed from the `list` feature. +contact list, user can input `view INDEX` with the index of the desired contact displayed from the `list` feature. `ViewContactCommand` is then created in the `MainParser` and executed in `Duke`. The sequence diagram below illustrates the `execute()` function in `ViewContactCommand`. @@ -152,11 +152,11 @@ The sequence diagram below illustrates the `execute()` function in `ViewContactC ### Editing a contact: `edit` This feature is processed using `EditContactParser` under `MainParser`. In order to edit a contact in the contact list, -a user must enter a command in the form `edit [CONTACT INDEX] [DETAILS WITH FLAGS]`, where the details with flags are -specified in the form `- ` with up to 6 details i.e. `-g github-username -tw twitter_handle`. The user -input will be parsed by `EditContactParser` methods `getIndexToStore` and `parseContactDetails` to obtain a String -array with the details to be edited. An `EditContactCommand` with the specified parameters will then be created and -executed in `Duke`. The sequence diagram below shows how the whole process is carried out. +a user must enter a command in the form `edit {-n } {-g } {-l } {-te } +{-tw } {-e }`. The user input will be parsed by `EditContactParser` methods `getIndexToStore` and +`parseContactDetails` to obtain a String array with the details to be edited. An `EditContactCommand` +with the specified parameters will then be created and executed in `Duke`. The sequence diagram below +shows how the whole process is carried out. ![Edit Sequence Diagram](images/EditContactCommandSequenceDiagram.png) @@ -176,7 +176,7 @@ If user cancels deletion, a message is printed to show that the deletion has bee ![Delete All Sequence Diagram](images/DeleteAllContacts.png) -To delete a selected contact, a user must enter a command in the form `rm [INDEX]`. The sequence diagram below +To delete a selected contact, a user must enter a command in the form `rm `. The sequence diagram below shows how the removal of a contact works. Before any deletion, details of the contact with the specified`INDEX` will be displayed to the user, along with a prompt to confirm deletion. If the user confirms deletion, deletion of the selected contact will be executed, along with a message to show that deletion has been executed. @@ -184,8 +184,8 @@ If user cancels deletion, a message is printed to show that the deletion has bee ![Delete Selected Sequence Diagram](images/DeleteSelectedContact.png) -To delete specific details of a selected contact, a user must enter a command in the form `rm [CONTACT INDEX] -[FLAGS]`. The sequence diagram below shows how the removal of a contact's fields works. Before any +To delete specific details of a selected contact, a user must enter a command in the form `rm {-g} {-l} {-te} +{-tw} {-e}`. The sequence diagram below shows how the removal of a contact's fields works. Before any deletion, details of the contact fields specified will be displayed to the user, along with a prompt to confirm deletion. If the user confirms deletion, deletion of the selected contact will be executed, along with a message to show that deletion has been executed. If user cancels, deletion, a message is printed to show that the deletion has been @@ -195,7 +195,7 @@ cancelled. ### Searching a contact: `search` This feature is processed using `SearchContactParser` under `MainParser`. In order to edit a contact in the contact list, -a user must enter a command in the form `search [FLAG] [SEARCH QUERY]`. If no flag is specified, the search will be done +a user must enter a command in the form `search {-n | -g | -l | -te | -tw | -e} `. If no flag is specified, the search will be done on contact names buy default. From the user input, the search query and the search flag are obtained from the `parseSearchQuery` and the `getDetailFlag` methods respectively. A `SearchContactCommand` with the specified parameters will be created and executed in `Duke`. The sequence diagram below shows how the whole process is carried out. From c55beb638d5474d47f9d9bdf3b31e1d763555fa3 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sat, 6 Nov 2021 02:23:35 +0800 Subject: [PATCH 639/756] Add contact parser class diagram --- docs/DeveloperGuide.md | 7 ++++-- docs/diagrams/AddContactParserClass.puml | 24 +++++++++++++++++++ docs/images/AddContactParserClassDiagram.png | Bin 0 -> 9997 bytes 3 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 docs/diagrams/AddContactParserClass.puml create mode 100644 docs/images/AddContactParserClassDiagram.png diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index c36d93dc42..9a25d1ee36 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -130,9 +130,12 @@ The user is able to add a contact by entering a command in the form of `add <-n> The user's input is parsed in `MainParser` and `AddContactParser`, the latter which inherits `ContactParser`. `ContactParser` inherits `RegexParser` (for regex checks regarding each detail) and implements the `ContactDetails` -interface (which uniquely allows the parsers to easily identify each detail based on their indexes). +interface (which uniquely allows the parsers to easily identify each detail based on their indexes). The class +diagram for this is displayed below. -As the contacts are identified by their names, the name field is made compulsory at the `MainParser` level. +![Add Contact Parser Class Diagram](images/AddContactParserClassDiagram.png) + +As the contacts are identified by their names, the name field is made **compulsory** at the `MainParser` level. The diagram below shows the process of parsing the user's input. ![Add Contact Parsing](images/AddContactParsingSequenceDiagram.png) diff --git a/docs/diagrams/AddContactParserClass.puml b/docs/diagrams/AddContactParserClass.puml new file mode 100644 index 0000000000..e309d3c08d --- /dev/null +++ b/docs/diagrams/AddContactParserClass.puml @@ -0,0 +1,24 @@ +@startuml +skinparam classAttributeIconSize 0 +!include style.puml + +class MainParser { +} + +class AddContactParser { +} + +class "<>\nContactParser" { +} + +class "<>\nRegexParser" { +} + +interface "<>\nContactDetails" { +} + +"<>\nContactParser" -up-|> "<>\nRegexParser" +"<>\nContactParser" .up.|> "<>\nContactDetails" +AddContactParser -up-|> "<>\nContactParser" +MainParser -up-> AddContactParser +@enduml \ No newline at end of file diff --git a/docs/images/AddContactParserClassDiagram.png b/docs/images/AddContactParserClassDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..082cbc58bf290affaa4020dfd8d2418c9b815b36 GIT binary patch literal 9997 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 literal 0 HcmV?d00001 From 9f3a8bb8388b4d8b243fb881696a543d9ed9656f Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sat, 6 Nov 2021 02:24:08 +0800 Subject: [PATCH 640/756] Update format for UG --- docs/UserGuide.md | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 15cc1214c8..cd12aa0c5e 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -69,16 +69,13 @@ This section aims to get you started with using **ConTech**. If you have reached this step without any issues, congratulations! You have successfully set up **ConTech**. -

-:information_source: You are advised to go through the following two sections. - -Before moving on to the features of **ConTech**, we have prepared some documentation regarding some common +>:information_source: You are advised to go through the following two sections. +>Before moving on to the features of **ConTech**, we have prepared some documentation regarding some common **[notations](#notations)** that will be used throughout this guide. You are strongly recommended to familiarise yourself with the notations used. You may also refer to the **[features](#features)** below for details of each feature and its respective command. -
### Contact flags: `-flag` @@ -190,13 +187,9 @@ Command formats: * Additional input after the `me` in the command will be treated as erroneous input and discarded. -
- -:information_source: You can easily run the [`ls`](#list) command to view your contact indexes before running any -command -requiring indexes. +>:information_source: You can easily run the [`ls`](#list) command to view your contact indexes before running any +command requiring indexes. -
Expected outcome of usage: @@ -458,12 +451,10 @@ ____________________________________________________________ ### Viewing help: `help` Displays a help message explaining what commands are available and each input format. -
-:information_source: After learning of all the crucial features and commands of **ConTech**, you are ready to begin +>:information_source: After learning of all the crucial features and commands of **ConTech**, you are ready to begin using the app. A condensed version of this user guide can be accessed by typing `help`. -
Command format: `help` From c13b2520e0df6d987fbf1268c9fc40de765e6eab Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sat, 6 Nov 2021 02:25:39 +0800 Subject: [PATCH 641/756] Update non-functional requirements --- docs/DeveloperGuide.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 9a25d1ee36..b37cbd8dfb 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -243,8 +243,10 @@ additional devices or platforms. ## Non-Functional Requirements -- Should work on any [*mainstream Operating Systems*](#os) as long as Java `11` or higher has been installed on it -{Give non-functional requirements} +- App should work on any [*mainstream Operating Systems*](#os) as long as Java `11` or higher has been installed on it +- App should be easily usable by a novice who does not have much CLI experience +- Format of details of contacts should follow requirements stated by Github, LinkedIn, Telegram, Twitter, and general Emails +- Importing hundreds of contacts should be instantaneous ## Glossary From ad83d6ac0f4755a4a4bfdce393f4533d053ac163 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sat, 6 Nov 2021 02:25:53 +0800 Subject: [PATCH 642/756] Delete johndoe.md --- docs/team/johndoe.md | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 docs/team/johndoe.md diff --git a/docs/team/johndoe.md b/docs/team/johndoe.md deleted file mode 100644 index ab75b391b8..0000000000 --- a/docs/team/johndoe.md +++ /dev/null @@ -1,6 +0,0 @@ -# John Doe - Project Portfolio Page - -## Overview - - -### Summary of Contributions From 5e0cb000f09df4ba9545fccaa61628f41572ddde Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sat, 6 Nov 2021 02:27:04 +0800 Subject: [PATCH 643/756] Update marcusbory.md URL --- docs/team/marcusbory.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/team/marcusbory.md b/docs/team/marcusbory.md index 6f6d3db24c..d61a78f00b 100644 --- a/docs/team/marcusbory.md +++ b/docs/team/marcusbory.md @@ -34,8 +34,7 @@ The code written by me (`marcusbory`) can be found [here](https://nus-cs2113-ay2 The link to the User Guide (UG) can be found [here](https://ay2122s1-cs2113t-t09-1.github.io/tp/UserGuide.html). ### Contributions to DG -The link to the Developer Guide (DG) can be found [here](https://ay2122s1-cs2113t-t09-1.github.io/tp/DeveloperGuide. -html). +The link to the Developer Guide (DG) can be found [here](https://ay2122s1-cs2113t-t09-1.github.io/tp/DeveloperGuide.html). ### Team-based tasks - Hosted and conducted weekly brainstorming session during ideation phases (V1.0, V2.0, V2.1) From db1ff0a876df78d50d1acfc7ae54d4b711b055ba Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sat, 6 Nov 2021 02:29:24 +0800 Subject: [PATCH 644/756] Update diagrams based on DG Review --- docs/diagrams/AddContactCommand.puml | 3 ++- docs/diagrams/DeleteAllContacts.puml | 2 +- .../ListContactsCommandSequenceDiagram.puml | 1 + docs/diagrams/StorageClassDiagram.puml | 1 + docs/diagrams/SystemArchitectureDiagram.puml | 6 +++--- docs/diagrams/SystemArchitectureSequence.puml | 5 ++++- .../AddContactCommandSequenceDiagram.png | Bin 20675 -> 21033 bytes docs/images/DeleteAllContacts.png | Bin 30265 -> 30117 bytes .../ListContactsCommandSequenceDiagram.png | Bin 24464 -> 24439 bytes docs/images/StorageClassDiagram.png | Bin 10045 -> 9816 bytes docs/images/SystemArchitectureDiagram.png | Bin 15734 -> 15595 bytes docs/images/SystemArchitectureSequence.png | Bin 20923 -> 21972 bytes 12 files changed, 12 insertions(+), 6 deletions(-) diff --git a/docs/diagrams/AddContactCommand.puml b/docs/diagrams/AddContactCommand.puml index 82a03e015e..b32c1bb705 100644 --- a/docs/diagrams/AddContactCommand.puml +++ b/docs/diagrams/AddContactCommand.puml @@ -12,7 +12,7 @@ activate "addedContact:Contact" deactivate "addedContact:Contact" alt#gold #lightgreen hasDuplicates(addedContact:Contact, contactList:ContactList) - ":AddContactCommand" -> ":TextUi":ignoreContact("add") + ":AddContactCommand" -> ":TextUi":ignoreContact(type:String) activate ":TextUi" ":TextUi" --> ":AddContactCommand" deactivate ":TextUi" @@ -28,5 +28,6 @@ else #lightblue else ":TextUi" --> ":AddContactCommand" deactivate ":TextUi" end +deactivate ":AddContactCommand" @enduml diff --git a/docs/diagrams/DeleteAllContacts.puml b/docs/diagrams/DeleteAllContacts.puml index bf5340fd0b..a0906d15c5 100644 --- a/docs/diagrams/DeleteAllContacts.puml +++ b/docs/diagrams/DeleteAllContacts.puml @@ -2,7 +2,7 @@ hide footbox mainframe sd delete all contacts -":DeleteContactCommand" -> ":DeleteContactCommand" : deleteAllContacts() +-->":DeleteContactCommand":deleteAllContacts() activate ":DeleteContactCommand" 'confirm delete message diff --git a/docs/diagrams/ListContactsCommandSequenceDiagram.puml b/docs/diagrams/ListContactsCommandSequenceDiagram.puml index a0fd73fca2..41ac60896d 100644 --- a/docs/diagrams/ListContactsCommandSequenceDiagram.puml +++ b/docs/diagrams/ListContactsCommandSequenceDiagram.puml @@ -32,6 +32,7 @@ else #lightblue else deactivate ":ContactList" ":ListContactsCommand" -> ":TextUi" : printContactWithIndex(index:int) activate ":TextUi" + ":TextUi" --> ":ListContactsCommand" deactivate ":TextUi" end diff --git a/docs/diagrams/StorageClassDiagram.puml b/docs/diagrams/StorageClassDiagram.puml index 93da57fe51..70bcc5975f 100644 --- a/docs/diagrams/StorageClassDiagram.puml +++ b/docs/diagrams/StorageClassDiagram.puml @@ -1,4 +1,5 @@ @startuml +skinparam classAttributeIconSize 0 'https://plantuml.com/class-diagram diff --git a/docs/diagrams/SystemArchitectureDiagram.puml b/docs/diagrams/SystemArchitectureDiagram.puml index c00894649e..75bf90772b 100644 --- a/docs/diagrams/SystemArchitectureDiagram.puml +++ b/docs/diagrams/SystemArchitectureDiagram.puml @@ -8,7 +8,7 @@ Package "ConTech"<>{ Class Storage Class Command Class ContactList - Class Main #grey + Class Main } Class "<$user>" as User @@ -19,8 +19,8 @@ MainParser -down-> Command Command -down-> ContactList : Pass\nCommand ContactList -right-> Storage Storage .left.> ContactList -Main -up[#grey]-> MainParser -Main -down[#grey]-> Storage +Main -up-> MainParser +Main -down-> Storage Storage .right.> LocalStorage User ..> TextUi diff --git a/docs/diagrams/SystemArchitectureSequence.puml b/docs/diagrams/SystemArchitectureSequence.puml index 274fcbafbd..c5cb15650e 100644 --- a/docs/diagrams/SystemArchitectureSequence.puml +++ b/docs/diagrams/SystemArchitectureSequence.puml @@ -29,9 +29,12 @@ deactivate cmd activate ui ui --> main deactivate ui -main-> store : updateStorage +main-> store : updateStorage(ContactList) activate store store --> main deactivate store +main --> user +deactivate main + @enduml \ No newline at end of file diff --git a/docs/images/AddContactCommandSequenceDiagram.png b/docs/images/AddContactCommandSequenceDiagram.png index dfef50b80b15f76d09100317f255e08f09fcb6e0..3fc04b50f908edf9dce5087c6e267df2f70ccb2a 100644 GIT binary patch literal 21033 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

#fB3rM5qT&z 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 E0JG&kcmMzZ diff --git a/docs/images/DeleteAllContacts.png b/docs/images/DeleteAllContacts.png index f90702878a2e1cc6fd386ad8a1e60593ec6fdbd6..d4f7c1abcca25e1a9a6f0543fc3785444bc9b633 100644 GIT binary patch literal 30117 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 H-(UPcELkYv literal 30265 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 literal 24464 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⁣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 diff --git a/docs/images/StorageClassDiagram.png b/docs/images/StorageClassDiagram.png index 1573729beeb78d7a74d19d0d52c2f9ade9f017d2..852aa19e5ee60b19f25c93ff2cc432a41c21e9d5 100644 GIT binary patch literal 9816 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 diff --git a/docs/images/SystemArchitectureDiagram.png b/docs/images/SystemArchitectureDiagram.png index a7fdc8b62c3fee4dc245ce07c57d20ac9f763269..5988f8b7110d8a7a22abfb7c882bc17b6f3ea752 100644 GIT binary patch literal 15595 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 literal 15734 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 diff --git a/docs/images/SystemArchitectureSequence.png b/docs/images/SystemArchitectureSequence.png index 1800ef2dca9c9ef77ea5f33357f1fdbc177562d6..b0a649e5c5f80f61d0881af7905f6a1c4365707a 100644 GIT binary patch literal 21972 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 literal 20923 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 KN$z7^um1-)s|fA@ From c44147ba31d75004f594e1196267e5da01f24d39 Mon Sep 17 00:00:00 2001 From: lezong Date: Sat, 6 Nov 2021 02:43:45 +0800 Subject: [PATCH 645/756] Update information in Developer Guide --- docs/DeveloperGuide.md | 11 +++++++++++ docs/diagrams/DeleteAllContacts.puml | 2 +- docs/diagrams/DeleteContactFields.puml | 3 ++- docs/diagrams/DeleteSelectedContact.puml | 2 +- docs/images/DeleteAllContacts.png | Bin 30265 -> 30115 bytes .../DeleteContactFieldsSequenceDiagram.png | Bin 38195 -> 38550 bytes docs/images/DeleteSelectedContact.png | Bin 41733 -> 42647 bytes 7 files changed, 15 insertions(+), 3 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 562faf4214..fe547baa99 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -80,7 +80,16 @@ will be referred to later on. ![Main Parser Sequence Diagram](images/MainParserSequenceDiagram.png) ### Command + +The `Command` component represents a collection of classes with their names in the form of `XYZCommand`. The `XYZCommand` +classes are executed in `ConTech.java` by calling on their corresponding `execute()` function. + ### ContactList + +The `ContactList` component contains all the contacts stored in an arraylist. It deals with operations that interact with +the contacts in the `ContactList`, such as adding or editing contacts. The contacts stored in the `ContactList` are sorted +according to their names in alphabetical order. + ### Storage **API** :`Storage.java` @@ -92,6 +101,8 @@ corresponding `ContactList` and `Contact` objects. It is thus dependent on the c `Contact`. + + ## Implementation ### Supported Contact Details diff --git a/docs/diagrams/DeleteAllContacts.puml b/docs/diagrams/DeleteAllContacts.puml index bf5340fd0b..e34bae33b1 100644 --- a/docs/diagrams/DeleteAllContacts.puml +++ b/docs/diagrams/DeleteAllContacts.puml @@ -2,7 +2,7 @@ hide footbox mainframe sd delete all contacts -":DeleteContactCommand" -> ":DeleteContactCommand" : deleteAllContacts() +-> ":DeleteContactCommand" : deleteAllContacts() activate ":DeleteContactCommand" 'confirm delete message diff --git a/docs/diagrams/DeleteContactFields.puml b/docs/diagrams/DeleteContactFields.puml index 16a3629322..a4bfa9bfee 100644 --- a/docs/diagrams/DeleteContactFields.puml +++ b/docs/diagrams/DeleteContactFields.puml @@ -1,7 +1,7 @@ @startuml hide footbox mainframe sd delete selected contact fields -":DeleteContactCommand" -> ":DeleteContactCommand":deleteFields() +-> ":DeleteContactCommand":deleteFields() activate ":DeleteContactCommand" 'obtain contact to be deleted using index @@ -16,6 +16,7 @@ opt#gold #lightgreen no fields to delete activate ":TextUi" ":TextUi" --> ":DeleteContactCommand" deactivate ":TextUi" + <-- ":DeleteContactCommand" end 'confirm delete message diff --git a/docs/diagrams/DeleteSelectedContact.puml b/docs/diagrams/DeleteSelectedContact.puml index 176b692ef4..c0042f170b 100644 --- a/docs/diagrams/DeleteSelectedContact.puml +++ b/docs/diagrams/DeleteSelectedContact.puml @@ -1,7 +1,7 @@ @startuml hide footbox mainframe sd delete selected contact -":DeleteContactCommand" -> ":DeleteContactCommand":deleteSelectedContact() +-> ":DeleteContactCommand":deleteSelectedContact() activate ":DeleteContactCommand" 'obtain contact to be deleted using index diff --git a/docs/images/DeleteAllContacts.png b/docs/images/DeleteAllContacts.png index f90702878a2e1cc6fd386ad8a1e60593ec6fdbd6..a779d77c80cd849d5a21bc96e83fda9b47974caf 100644 GIT binary patch literal 30115 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 LD2nGkGW7jFS#AAz literal 30265 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

o1;#I*sN!>S zb@wdHeT-UFmK%E4po>)|cfLUzrJg;opa9Q3?B>D22NI=@QL`y@lmOXgC6CcwWK38y z;4!q?0P0;{nIxgE+hO9xG%@P=;e=n`2gWMy0&T)M4QowyJClYgtKBImAiIgNV5H(IS> zWBoxNGp@+u8n+$Zs=wFgJIdjntmjJ)!qUz7&P=bLzu3bwHL+)*3^B-o3U{OFVY3l; z9TPHeEGnQYSKifrMJau$- z_tHtA*i=t=i9(kxdYAb(Ito=^<3K?5SJ?h{ES>Sjk&E$q^t%1XjY>kp zF1HJR^_n$K9e9f=99w5sWVrISyaR!UvO+}<+vj?a2KcESCw1&3-jO25K(X=kUd6os zd+n_LhRHRsD~BI{;Gq!CtF}(C(t3AH@Cv68?Qt|00y^(-MS)1z1@q!{Nzt5%9HdiTl47}ZJ#25xOLe-uO&$gTMc5j7Xlqpv90RIGl#^`+j-MKew zlLJ&Q%0hJ~5Z{i@V^*@fTQT%3k_FsewpMJhbagd|C@qMHQrdVWVxV|&Pdv+LL0n1H#3(n15Xi@0 z?PP$MeYLd}UbB?SWq|mVeHBzT*p3I@AsPubRn5D3#1heD(B?mW@zDmvw|m+fY`@}% znmG$WAtV|Z4&Kg&40u(k8}iDnvTZ27WuFbiagetIt}WGeiZ-@23t4^#h4r3P|R1UunqW zq>h$uJhC3j0Aq?WcQtk(p@~j_*|jL2J3Sx8Ts3jpmyRUKNj8qnXZM_%__~&z&PqQz|o*JkF zbl1M&)v*3m?r*S&m_L^lv8KH7Liv&xFZv0z#4dMQi%mG_e;jHpeR!+y>IgLdRCsx{ z@;=FM7G;b~&tBu8W9S=;&P3)MYv`LJ5Wr$b-cUsclAW}LAph4V2>7a!O4Zs*`Hk>! z4Zo7r2B4)<!SEG;$zXyog81hpWvP zzqeL;5^@k`~Lj0(<{8U67xelg0m3xR+gBnQwG^2)MtJy0^ zox^EfHslRiH%_EOxQuk-$xp>D+AQO&OxP>{4|Bp?uFyY_;CDug$leKs;jtIfd-Lzw zXFty7pO(=iMOlj-TP^U+t?JMkIXG0s%5&iH+?QgC&R&)-`8s%>Aa)_a;CmfUdWxAf z;h_5~r^8o2b23SjNYqw0KF*6zN2?sU0dreisnelRAJ~%OFY0OzHi-ZNj=e6qIPc(n z{G#{d#Age}I|d*Ei7f!ZdZSBKe;-iE;@EK6Fg6{Ok#5Z=&nf^(gzl&D_{d)7O87Tq zY^;Qm)x%W<(K`qP0M!z}RwRuxX1J{T4!hbjpBr}ch-c_-30%f~-j4W8TIoJ&GIO?v z8|;dMj=)W@c8Hry>pA(HkGfqgX`CM|iT}FfH9EzGh)Ssi_G_{SkwA;P}Ug z#uw!vfVGRq=DPr3X|HA`8jq6$5hc|O!R7a~g$NL$eBOK}=i1sxfy>J3bYXS?;u@5^ z4py@}UnMqog&zJr;4#feoA=~SvqIl4r;=L6l_(s1LX<{oCThy3vif(5Jr0lW#)2To zXO|pyZ^@VOQvU!(G8to5qc_Vx?|7;~&a~WZTe{bQWi?&y4{1H6}QL8jpw}Es4*4XEm zpm4oPE?n@`b+NqlLbDKiu#j@ElIR4i*oFyxJb}cgrxix{G36Fi^dm$LHBSJ7+lA}? zxk*u)884|W zC~<(h!6$~Gu*<-Wi{EDAHM%o)%e3QF7Nmp7m~Ma+hlvf|fqB_T2&(G*;*l_26lSFr z>m2C*JgG=e!>?S1fgX`jF@62yEf}fa@+(O?X1=X-TQ-yH2v(|M#$4&9o60{Ekn|Zl z@>^x8@~%ubUe*2Ff0W!rlkWGl-(9=9=;{b!3OJeOi%8S&`j5msHaw`3X$>Y{IRVFw zq(SleQ^j#PYn%Q=j()h}n4#knAoL-loX8lr$8Gt6{JnEpIk=r(`I}P66LSNpCjlcN zv-%zdbc_FZAY~vc$?YV@FwyaNAu5s?2~v;b^5jhf;3TY`RW4shI=reR0^%Piy0IF= zE%CWgK_<=s2M66bS6NtDLkf}(^Z4AF*OvR!1_uVTp|i;Pl7OAWvm-drO>fnbAk8y*`MM@m6)QGXr#hJCEd zHDLAw2H_48f{&C7zucrvjSqj@Nq2OC;vjIg-RSSVK0 zfZ_)RD$4>N14j9$z~#Bn0g^?IMlvMcLq){$ zcLn3CzfL?wmS)$0-{l5psbRnl)Er;{&Ncc7o(Yvip3g5W9j=dsA4ifY7|E(Uz^2u! z&J@$le-dfdBfs}LSHp3kBZ6Tj66}P5!9mAr;GPAB(z7&@ZU+G=^4Qnukz=#Qdh<_B znpA+~nfe^v`$fMLQQt2O?aIFboDV<~pK!lC|M>A^*@SiHVt1TcQF-~%l=D`QpWhum z=r(+=RV`Ge3A`{t{hL|4yU$t`)~;h|U|=BN6d$=acp_V=s@1w2166~B%Yx|w?WL== zBk*YaO>ElHV8D7&;yJ4Mu0aKOzt2w(v%VsHyf7Egy}?>n=Yx;Hu-O=;<3_*rn2RfF z2L~6ozsC8{ZtaJ-CvbmAiHrOB`=<`|KWOp1z_TCeapnP%DoYjHxF4{PMK=dyUROK3n0@uce=N766Vpgb#bo3tEbFJOK1((9EepMwk$`5BrBi0V>#C5+ruNYkKY|RpmY>st(4WB zZ-6%fG%F^L)h&uO1=3T+`f$E9N%y3JmDMh$<7WYKCe}$V4;+(^{&5MEnj?`E#|$Hs z1+Nj(qIv(pv+Nf({U*T;x;ffFeFBDzfIJOkC$%tHwa4}J~BqtSWXRsn@mZ9NtcNObK~A@f^&_lL14H^&X94fk|}%&*e#tPcg$L~_Cy zKUfQ&(3hrhOY>(F=*N)_7)r;ozY^+Z6nRWX$tU_yx1AvCSUzYmb(qYnL7@gM7S%s6 zFx^(mQWdF&={VuhbE$|$n#?hYch5hF3VMTA4ye+x`@8g_{#LvZwJ(s*onRbHOo5k~ zfr_AW2wT$gOA`TIIm?OEMqZ_(E?n3B_61xLuPvV0+1X5qASIkxE5|%Q*7foG#RJdb z_FbFh59D}w&kuKi@A2|<`jQZ_1~^XlR-RL)rKWx}8>6}fOnqjcr{JeMj%&$vK>QW0 z7^3$^T~da?=YFmGfCe;YIs%6R=23xHCykV0mqYfQ!6ins*fZxZfs_TBh6*M=DUO6ga(TdZ9vlz&@UTB7 zy!V4keQF_bH4Ff*NFFzeSH=Pl0XsH3@BqPsve(zwfv@tRPU3@pBClA#fr+LwgUpGC zjo@ttxjJ>VpzE@=RIh>Y7Gaw}6y`Ujs)K*|mw@N5x1+;kq<|b9iv<62 za%`J?aaZZ9;Vq=|b!R)B{^bTqz-B1Yy$*aZa#Zz6n8C0W_o%bQhO!T$b0pujn1%C4}IB%`jC^{}@okm)F_-EamP zaDP3|ufqW%&$|&;{jjEwN;s`|skS~vfx`ql1y!5CQ$^cME%OfHaVu2GAHTdf6co`c z=>-N0U^yDfmVX{!YQRQIo28tmV%rxOh%vPUq^FaEjkwTI;JWN~pUrkm{^M8yY_Fma z0h9#^S$U&2U!=%o*5zyzOhheXyX2q3!8>ngXlSNDh=nm8tRjHo_qs_mAjiF0Hz38? z&2YTyDf}vgf-}-M~7;Hg>&d^z`^yfIMTp?ScaHFD+Ro|L>HWs;6_k{ciG@* znnBY#PX=l#G`PmTLpGmLA*`r05s(q!1Rim}n2s%+Zm*Ja*_f1oc;H>hhahq;*G|;%U@kWj3uyq(9|ogb%6UMXjGQvREAp=9;);o8M*`JB$;U zvHszM|0D6uy{TCj#$0jl0qvqapez3BVh2z%s&W&dx;d!HY`E=h{b9e#Wn1`xUEnqU z^6J2p3F=NpxHm0GqzyqLoqO{#E}1^Tck6{}FP z|2UHn&Bba3U5xgmABkUf%NxJoqg_1k)R9(kSsLCFD8zWTrfc`>To!nYIUtn5F^sOu z#d)Tjk6+TA9N_YK*XmAP{yZ`e3C@XxgW-KQEe+@m@ZEOconxu8@&Lrdwe?-dC<@5P zbrpfS&1Jn=Mdby`!vn`(0(nsmI7n93Ab{;*j+h@#4v0q{e4dxG0r}LW{y&Wv9Rju} zFv9QtpT@odEUK-0A4Nq`N&%IWl5PQM6-7e2qy}jvr5PzvLPAoy6i@_&0i+oi>F(|x zKpLd$zYpm3dcXU9zdt^Y4~}Qf*|GNC?^^49*RghEtPo+p8!zxHQUlltsF(rIi4b5j zf?L|bIRNRK-95Q-t)x}W5KxSu;OGgnF4)WjD*~}s8;5Gn;9HqZ(Ik2Rh;gJK-TiJ) zI@llqYpu&&>R5ONaiTyV;$k(OW_)b;6&oiIi{cMW=$Vy)A-ZNniWjEmyw0s|h>9uV5&x%WzHN zy}++7!#zW5_)uA)!n3G7p+j$0j8{N6LcTrRMeO;Jqq%`qFmVf|a}?zIggW7%?+jor zY_G&EG@7HEqHL26Cj8hz<+m`1dXTg4(+k~vpGuA`LzIKQnB8eR`bsx_!4kRS8W8a; zQ40&ZSU+I6*I+kZ;R%i&Ktl-30e&qlaFfQ=kZa5Lh%!dYTP*NHHtT-QCX1YvK~I^aqC8%Y6#xG(MFX=1!= z`!}(PE2vw9;X(W_#7cJ{9Jx*QU;pD@6(zu)ZZI709pJ8@EYknUXUMGilW7iuA}4~C z|N7j2`46Cx03>6Mt#0}UG>PDFkb$f&gZAjL&rt2i$IA?z?OlEN*ByNsLwT0WMd3u5CDp&f0+sdv~na82{0MM zMJD&#^WO@8Ya{R6`4>J36FaQ>$_Ej~?{64^PY0a3o!S%5ANI7@=c#MAQVkLSX#lWl z3|tYg(x)(@##0!gWB=i`144cvxgcaD;G6}jmzb2|e|Tg}s29Z7zP#E^UXie{uz39V z@!v}DeaBS~J@M~C+ISn*W zJ9|vr-l3|~$$D~kNF|(Irwn+qHE&7R(N*AYz|{woD+XCVmG+drjB+XhKm?EC)IYaA z3e*+5bVyURLCa~Qc%tD0$=KP8NT;0Z{>9m8k*__K8K&iS;*VcP2jh= z$<1v8=-(_7<{*|MQ*PK8-cA6QUtAFjlCw!pYWpT&_x+Y(!@JHDIltz?+-E?hsHCAG zg*7os+!mX+N|n8QiNg(qzP8a&E61<_6AqldB$SkH6IBxG&>e$)XRF%S z6dQ{KMefj7y5Op+#OtZ7q(Ii-TF0~-jVtO=VH_|^`FH<7&4F&W##*k?We9Qg`Lb?MqS(aXT= z1iVbkuFnK}vjvp^Qu(r*85$b{>95}o5KJv_8UubF@R`-+l^CVSXk7oGCe}G|h$I7E zZAVoT`!R?XL11FY|7rcd2>75uTGSydWS%# zC;1)3e*Eq;b<=*>0YxOki0J6)+0}EVIzCD-G_y*2Peie@u$Z;IF9)4!jphHUTj_OE zCYl9;uI=A`vKZ|&^V*aJ#rOOA9xF~k>`0&}gUiSA;E_-&0&iX9Xx|1MdgWV!JjVO) zH~uA#_hMoLh)G=bHf1Cv>RMXRsILFixq@8=a2aVW3qhCzV&i&yccK=CoyG6oy$du2 zpP55kl6BPOzlv2y(KQbwJ;W2Z{}V_e{|T8>3F!g|L{Gr&>gwwC>(_-CTB5Pu;ynWd z3$O-&AQu45F*^(lY)J7WZ`f(KRFe1;OWK`&t=w2cya{}Y%(cT+{cgvXeGN=pH{+fUu$(ZOT~U3W2i`mp5&t7xlFk@n#Y;=j-+ zNQna*e<`iI8)orbI&JH5_ip*L%o5M`4Pp!wgwk}5xn>-Z1?K9Du4;!FHnk4v>)ju* zl|~p(;UDw#?IMqnB?hwkL-!8g;d9XyPkFtIjT}_FbpVkPAzuGrBG;Lh7yz2oA;ga9 zeXv)|5So;xu^3$G^zmIr?v}DLiD8_F9=R{zaeVY1pRg)I+R0iGLv1wa8hpo4vY`6M zj~`7yIxgahg7Ri;7^&gShx%KnxymqI*UC_ix|Ob`4HBUr>F6S}so- zV&enizY0W${7G&^jpaWjjn{e$0Mg5JLNLfbJL!Vo-;4o9yvLdt-jV=cSddRjQ1w<(g$Zxe(`GOTDaH1+m zS61pf#t(9ij*g(dGB|l2X8~MSHZM%md4 z82bi*VK8GrT=>StKQIsly7l-2a-xV7NRziKR6z||0EZ(JK)jH`2CU5Ecp*=9Y!&AO zs4MLRGI7jmnV_nLHxg@7>~boo#RhJ+QwxH5H8nL{I*1JCYoOAo;V2sv3A`0}{v}ug zf|Nb(wma2eEZV9<)7v4PsHzrJ(gH}zXe+$%C|l(2|4kJ*q<1$h3s`@M1yHcbNJ{G7 zT^%C&hlo)O1U3OKZt(@Eyax4Tw~i+8^I#fLJP2!sz8lIhZ1lN8PvN$2MUl)1PJ0Q3 zPGCqBP7B$Rp*LMXw)9;#P^utzzo+l-aYS_$A#bl3j4F#Q4Wz{?Ic2lww25)#^idn| zg;Q1@chB7IH-r)zeq*xHomUgIIEI>rW1qZ=CA3F6H;@Qb= zIwU;L$G(Bn4|J3FS%(2gra%SM-`=dvh}5s0(m7m<5OLWBWsfGn_M14CgL#ifafzPO zfM6P%dF%262le{_*6ewod@GTvuZQsBvW}#Vwh&iENA0I5N40oOBp5GfvY@z#KSVQa zgOImFB@37u{Wkg)CCHri~=bdC21^^)>1}do~BMcq5LJIHsicB746p z^tpXBy(yBDau9T9n8M4P2x)hu7t4I_{0EZMtcYr`HDl|n4UQi640z$A^Ii~c>O51? z({20O!yJU(c%p|0>|Hu|(r-^dy0s4kbKu8RoGg5}1QgPA-3K|_Bk{VMpmz-TEy(aD zH?zIAXWkmPyXu|pqL#dM+bK@B-^!Ixd*G+lLp=W)N+|;m8iJM$C>sR|p_`MxJbq>m zvO(^Xj^pHTK@E#=tm^)~k`Gu{UQFl^++(UMH1?tG>_(1Ul4p$rj-wBYIL&)c ziYl;H!nC{2SY-do^cro$bh?QFob%V`e>S@`8f^z0EtjBBui9xA9M*PFp+6!f zW)Renn3wRtSG+TE%TVS+TcTF{{UYZu*fdb`CiOq|>gc|O&`Y-hPXtYXt65oPgAWyl zRQM3p!;|67ZI?cn`ekn5tscc2exTD39O=q7FUU8yv@oT-h=FfY^{gS@LtdUuPM%Gt z{Ueg`I%D=NM8(C!J^g03zKPo&gs`jzmdXuyd@Io~BHT5m zH@nrp*(_e2Jrx#lS6fTf$+Ir%?YEQ+@a#Kp%Q+AL38bZ^30P0P$w~&n2!2pwteaa~ zF?JWdkvClK{cXV|lREyADuWm?lg@Q_IFH5wFXBS|1wH0QQH`>tLA%YKbk8DO^fhq5 zZv>S{G#ZVq#g(PuJ{?a zHdFTgaLzJ5SlE3<>gGJz@Rhk4yB9|_*&AbAG7uE2Rdqu@S=SszDZoZ8;= z^`2_!;MhWk#OjUkG_73rEyp-;UAtI70`()yi~!@ugV;|ClIPD(ubr7*Bhqe24~4T9Qdw+8 z7rMpzIL$n7o6a?{=eMk*(6RHdkuiP8JL!3SQ^2bN%nf}Cy`SS^foWrFL?iOKZ^Ts> z$<(M+qxFH$3N$wJJiS`_oQTbFbcSC9wfgD|c9f(AzLwZd@APScH^aexT3d_7z88ta z&D4wN7;B=}=Z}mJyigV#dYnG~Vyvy%xZ$j)UzW{UA1Iw^n7+_3&0PFWjeebJd&9l3 zXmT8y8?5G3=-B5XHO+3Mw8nzAR?$mX9UkYU_<5HX)X{nxS;i0YLI z#A0+LFTR>v^v*9H;GS?@6|UMYgYS za&9C4^T3t)u{)2b)!r3>wVMb@@oa5t=^ics+iXQKZ)dyLtAtLL?e*Q+QYf#Vu07|Q zLZnH|IGOc-v?q7WysFUeh`cH&7>`JYHPJpZO!St4v}-|fGpl(BDJ?0b5YL+FVc{q6 zjwJD~{#9L7$ia0f5jM`4UU0ft;tBtd2m0ZI-3?GHWFPo3Z+Z?VcTcjg+NS(uA@kG?J5qrdTL zvW26?2pA&h!9g*r2#aenok!obvDuF*?6$d-V8d@2z)gB)^2ljGfY&6msz_Dbu!P*?iUjmM}`zODmZ9tg>*feAE%kaH@HAWUX+Q(aK@Ogq)OIZB~mJ#cf~( z6H;Hig-{@bYKoaqf%!2(H^iCRcFBUkKL!T=g-A7Hy=g6G&f^{PLpf3aUu;Ih2UHtq zZl8|Ad+=T>{=HUNqBLCJ4A!lzXQKBd)|3uSgmLR(gyo>ZU#7-agYI4{O_u-p#od(i z?;5XwQ_hx=9j(F-w%YeR#ac(d*MBvV2@Bi>>~ynox&$)}*P z9;esS$ReRPAiR`+0t>@D=>c|Ay0umjoX9hep2keu%HC7>*?4wm;Ph~O#Jli!-Atz2 z1LK>xx;_TX_Dx9>W+CvsJL{j%hZ=nn7G*84w4fCp=0xy{P`OUTb5OEckH)5uM9)t? z!_h6!i|-#H37-|0%zR#0#qfr%rIb|-xv|*-Mop6g(LkWNt|3}dCj9KvRA@*OIw~oF zq!gXbb8%Fo4{5VbKt!`JJanOi=wVaR&=xgeKoVJ~k%qlF|MCVr_=jz+kaI=m1z<5t zBke9W@g@u@YsFr51ruch^7r|qtUW8~!r}fA6EasVOG~*u9{jO)g0XvO)|~E?{=T(K z@7(pTeBW}U0lAFfN!}>oQ6v2 zk&i^)zk33 zeHSs3!``^&Jq5NihwDRz;E1^<8PQX?Oqlliy~3XOy6ibiF)7}CyVnF?cAZsb1O@zf zY|Fl`r-^O+DCq7BaQp4O}Ef)*BL+u?fD$N2s zF;04!F7Ga})FCG)4Ab?CZZ6;o6nP|j^zh}y?{qw(>35P^{*dm~Fpg*8mgTDIvd%t4 z-n)D|%%zzivuDI4)vHv@@Qurl+;f1rv(+VHBo_ZEvyJr1#PTmS5GUmo*+oD6p)4w)&Ke$T3Y?EnuTEy(&E#C2${>zaPX1!s2$*<*%iZY_NQRaA}t15xXr_ zttTaTXTkU_nL$A$avnG9=+**zbs{oE^mT~BV2TX4yV zq3W}y_y{#_AR|^voqo;g9qUKM>>^#ShVdlU8y_CcD~RyppZ({Gd}xd2DV5w^!;A2H zvKm#r))CXqC9T!+AZx8NtlvE6t$|0z2LakowAiAwdy(}fVTMDOuPpI?g@1~DKHVS2 zm4C*l=jd5!lku%)e2Vsta-jyRb2cMZt2y1-TI7C$_P_{!&~!G($kt0R?&UnfEf`%7 zjXa(*36FF;OPua+9?B1DLfgc%Ikj!s$<2$s3{#NF-}9>pADj9DNMSb@3#2 zau)n@x|)=2uH1jc)+_pZkKzQYG7g@hiO4Lx=lA5`$k{C}GeVhtNwAt;!;-70!0UTk zu72kO6pVK7d@HAY?c;vb#J#pVZxRBwat+L6!w<`B+w@-p+cqv}35RoPxssHN3|$u7 zw9-PF*|9{d2rph7^lJeS$wmjqRkeKfSt0fMbDM=i*V@zt(}3rBOJIC%FD1d>(M{g= zDMC&D>WCqWb)^n3EiK)(Ume*x8>4U2v9E~SNc2bFd~-%Senq+dl3uI?CmIjnR#GiE4LwU>#e1?(2?_A0dvnI0QN!q zZb=#UuIz{?yc|JX=WHa49Vav)E^?yj|3MXNd$U8=HwXh9Y=a(mcO9c*DMcf!Zf zeO3nnO6nSKTfIoE`nrpAy}pkX1}Y#va8-d`U^bR{-}7hMDZGDXdZy8{`c_B)R)~H_ z>HVdPytU!gjS*mr_{8&wo9`6B#NbqkAc1(EySB$DC3{lM(SLO^!&8k-xsTc}}zmv+f%>tJ7Y z+GHSmuFtqeb-$>>Y)-@8lz%3|hNZGOdvcdNg$pmC&{$7TD)A`~tQgUg&9fjlT^I=K z#ovs}!3x-;z~+?tqD01hWlI*hC~Cp|_wJ&TcRo7KCv9`#fVUwf%IO)_!hwhp5;!EE{ltojkaaf7V^4cVd3+zb;WUi4!;GP~=9~>GIw>9m{96yj7 zVP6MBhsLRsek9Yh7{jdBh;GV;Gfz6awRASu&t3zYTrl~oQC<#O(ZacX;x#zqI)mR} zP~mbMFv#97`d_UxTT_9(XK8hG5Xmu@8BYuUn#<}agBCR}%?y3hK8FS?%F;}#1wli+ zdy6GQLDz#5kZ#th>0kCs)|y8{pNN93&|0Imx`e%tOf#Hb$G4ztxiW(C=rlyQN( zh$_E+=gfG5a2vr%cgyKLlq~INwnj{De`qpIx5zM}OfX-@!+0;E345$;C)56wW@&J3 zZE{mJ0~iAqT7?HRle5f}*n}wnt%96mwRoz#d`b5=z=-cFdtve(cK5x-Rw+4_8G9V@ zruY{&;6ERK`4d@m#|JqqCkm5GRuKk1)iEL)E6PsB=ly;kR?KpU*vp?gU5*Ikor` z!!~!))5Z@wo2nP>lP=ppNBwzYSP?)QOiAc&S#=1tsSyfo486Le=YA_`Z~p3%DGcdS ztvuOc`nXp&fddV|3C)782LMrFzxxOaZn1N-Zat6`cEBYu+G#qzmiuqlV!X^c6KCoi zcqeWNt(iewQ5?|k-oGButhsBkBFD>g8UU#Z3h`t7^PGNL7=iPm-!f05t=$ehPOP>P zdTUe{)fy`6W77OLB$Ic5H>j!r^#L2SS=xdwpAEAQsh zt`yB@1->N$knp_IwdPT-ug)EH!p$$#cxH+A8?RdpWBQ!E4Nc^V)Z^ZAoxWXIWUsu3 zu>U6A<|PtUZb{*Sutx+(ltkI9C`G-KpNTB1Zxak=O~L{WY6_mDp}{1y^WG+!ycb0nhZb z(cW4V*b92>4p+fNpjC40Y8SL!me5YHQ#bO@Y;)1D|K*&4QF}9hBw4wdk8vaa4^I&~ zanzmy&YGUzKMz!QV8t2j)BlF(g%l@&qj}#oF3V*z3L;&_4r)|2rl`xe5VEg! z{&j96u35B7OG!7Fgz-2pK6jeQavaE|tx(|9 zfi0OAO*H2?U?jBtv)3S6F>l;kK;K-5hvzxTP@7zoXIK!P-kK2}rQ-Iun*|ZI_xXFW zVQ)A9n#PjF?5(9dW~yQ%G_Wg1^sGCVmW(90qFFcDCc9eF?mdPnkKW8n}d+K#^rj32jRW>4>hx&IZ>`){u|%`)`XaM z(YAg)6&xepU~1nVVYnl<7TOtFa%m|C9cb#GENwdEfZbg#G<44+iL94jcgtfN{P_!% z^G~fFxgy~+XzMG$6J~L=ao_VIOR;{`A|g@(obAg>S2|;o14p<9BmmS>CJV(O;kj03 zU%2P>LT*mjw!5t{Db~Kh>YcPHZMDOYeA4DybliS9&KQo{@RKv?B0AkW0WFDcGlGJM z-AX1J#&ZFE9ErMvUWqraY@KOU3YQU7H3GYKKllEP#rOwL2tj_aEr+yy zz;lgSJM0+ix=C_2)y3wF(6J5Vrc@F?D9nf|XE)i6sBUV-V)i zqx8E;T%R!{u%j9ro5egkXQ&u}trBI`8lVXlcs7MD{$kR-4|Qu42Z)C|Q(z%AV}LaW zaN>`fbB&@}Y_F<~i5pGrRU28xUGM)5vIpC8Tp7;|m|u82l)WAo2ejcZ*Rmn5ac$|P z?>kTA2;L-MUd6psLRFhe78``UBUc=fFoajY}`a&HiY___YNjSTix z91-GXqrb=b6L}2Vu3Z+_xeCUBVNO+9y@i17ImfF?HE4s+4RtzOgWe^;LaJiu(v0W8 z{v`0~#Nh*>ppVO}MCCbK5%s3|5+tzNM;@S+&znjDt+i6hp;;cf%~fhuY$yQ$Q1PXu z5F3{O7p4<~&u4zx>mWW_zemr$-My8NRQjo!r((|cN&Rwoq2*^+dzbM<1FSt+{s7-B z9%ZaroQ*Yt@s%VeYZwbS(VTrtKZ1-y-AET(Or-GgsgKBz$_>l<>}a6LF>NV)e} zo*@Sb)@mooCv}0Ba{m!5fvj7G<-2J5QL$z3Ms%Ar?CZr^q834ZIogNH{!eYBNonRr zND}aM)+BwTz2#l2T{QZ?7q)N3++?O?MyE2dfl>lbT7 zYBQN41;w?q6xJ;xN-r*^&>@w_`|fSws9o$K^or39LdjnhQOVd-B`A>+bs@4NU3Tk_AH`fjDC z<@oeY-CzN`GYA1<%(iSDZd~4*-*~ek&Vu1_7VLDo%>X{kdU7C~Z1()#Go3(mT;hd@ za~MGo;0BpPYfv2jj#Yfr=1X0%bZcJ+oNL7eE~pca!e|JN;}l;YcOK(17+4SCR9)Dq zJBA<(TPb>Jrno@=NV{M}J51rn!kfK(F*MV4c17K-viL7*&p9spoIKVsd2 z$+1U~NidwR+Ts{B$;00i5*6fd8p(!BkK!EiKjlzr3}i!r6c*^pc_+n65YTKm9^tVq zq|vYms@ueU-MOm^os>?}c6`xT@;MC1MOjX}vZK>CAwb-5Y;)|F+)h0O;-S_D zepInDNnT06BC01JuQffqG!CvO(}p6nV4BJ$aWLK+Rl+I8qyU1gC5rFjb%9arw{_R1 zFUo+!@3fj@Jl5xFXt;_)2Wmtu9bc@9l`j*5#CYRHzlBav29El^Lp&A+CKw|};nahv zw}vIY%Og67hwo*#4pKcKa9zFn0$jljouezs`BRJZ@v!~2GNWpDX*c)htumPDBv!3N z73b9~Vg!8ZSJZ$OOp=$OnW>qvga`(9ZBpC)pfHP$v}X?4BzV1zF|OFE4}f zRdNT;mh{@WrhcGp*IAM(TjQ0)3phuTV-jx zo_p377pu0up-#WVKE4aQ7M)RtJz^a8rl}(IV)ga1siY7PFI^Bb;r~4dMR1;7%Uz_i z(_C)p;@;Wsws^D~RVd&Sak}#3250>k{+ON;KsaOLQ+Iw)V^=-(dFFhXwlSq*lPu#xPc~fEFAiK7Pj(J)0>ZQqGHRMp&5}K@qOCxRX|0#?^7k` z#L_fx{@RUpq8#s$Et&MAM~}z`9UZj-^y4G98}zMg`O!WIDHb6weOR7j)yEq~=~_M*(>KXR*8KPu^?|<;a9gH76d(H^ZbTc2cBY%}onKkq|M26F&BL<^pwS$b zc1{p`t&g9X9!$G|fkDtCdH=4mfCGE(Ogd$e?ABRPV=jca-1TdmAl*PX)8>!;_jECn zF>F!#QW$Ej=llIk+J%q>bT^qkRUv2ottwQ5tT)69ilr=(TJz$ zgwipPIJa_JmKjqRTJl6|2}EAZKA4KKC>RNU7cx++pJLZac_nJC5|LZqoE{MrG@RR? zL|Ra9J}l^BZ&X>M{x(J^XH&A)J%BW%@wrZ5-zu)vGeETk{93*j4d1UrO$AfR?Hk=o zy7%MC>cWPm$K7{3hg&1;ufm)Hzlf~7I*)zs5?7!#2%6rdhWSptN)Tdp&0p+NH}J60 z-dre8AQPnHnp5w$&YxrM^^-K{5NWd#tLe+S$ZL;GOEUq~X>mDqVVWA~HBxuX#TC}0 z2X1IrxsS%Bzu2;gx@y$^2Iu2P*ywysA$wcxE1W09X_Vh| z#2pG`25D`+r*vlIUKE_EJ-d7;LPyWpdQ*SzPAyJ9z14yd?UAeGuU5XC_!H%Tky$!e z!e4FTi8;eHy0=8>_hjM=;X}=(*qe}r+ zz#U%_om;59-K)7w!o;Tw`{2KbNzP}GP?a5XJo|HVbAV`f>(}fPKKvsu2D&@ozn{kP z6-uOC{KG?3X+citETUCZ(WAiqmZ$h*-7p!z%D-8_nk&E=^p6qzdCvZ?q}rdJ`_s2z zKWF%RS_Jav!KeRB82xLq&wB#Rv*hh|qgUR!)Z?t2i2m}z?Y3ZY%fpuV+^n52J`1L$ z1VzydE7`_+Y1Mu~54w5HI(}Y}G$7JWPb%R(n9(1i|iiwFv+tLHiFJxeJ zzx-#k;zKYztR5bdAS)$nwS`zh^BhF8ICV4y=#<8QMF`Ag^I-GqTlTUZut*sjd;3a? zuGljNL_YK>ed>0AQzGX^&0QkvHdHJ|zg3zpJK)fw<1kft=gg++OOrc)ObHmjwsxe5 zLp`ddS2}B}0ME9nRE1-^Tym=w#-NiavQm+!T|DsD?H#9@;Gx734NX<_s<;Wf%*9a% zf%MbtwhQ)O31&td{XU13;=LUG)5xJ6y#=`>av&La3NtiBNkcnA({-DOM%{j_IzZb} z3RvGKg;4KCUJ^-#%~ZN+8O=P-qs&pO?Gc9-;!D@w4csVoIuZn%mJ! z7Fj-B!Ms8*q^egnd6o4l`&&R_d0+GL*teR0NuZBbJ-oFtaV;O9JcB z-G!3fB?*JZ+_$&OBaAwCnqrpg`wShE(5xPOm&?DVj97N$m4L zM@y6jl-zG^G)VZgJWHA_1|C7J+lx-v)3pK=3JSw2eY6nold9R7SNYaI>bxm=wyd=F zaXd>c%gn!Z7~@9LJ3Nwd%}To|^H#23WTR211UQf{cEKEzWOI}}o4dXl1=^T$35dA zpG9NoDltuq#lXT^T(3imkr7{x+-#vy?ZoY#a;r4c65GX*qZZyGcsR%v<5V>PqiQtk z>!Z7_2V$|n>jt~`FyA{@neZ%>`2K<>WwNoMrT~UAX0g!vhkxd}f!Vn^4~~3u(rHTV z8z`=vuJutQO^y)VN&uTf$5t&3IZmuUx%a5+DCWG|CZHC9UB5PyPu(kWMtx<9Te6<9 z0wvDXmaTGalpOV<_hY3J{YXol#cihpB^6^=9gPi}ajvTt{m*XUT;mjXMdxkD6NEQM z>HlS|{Wc4)=%^`#jf3fy3%9}aM3(5z1H*rsza1c1tAYcnHgPOfMEeQbjmq!MTQUf4 zhYzNUO3r&N$rSQQ`b(!b@&BCU3+lD@? z?aTtv?<32&!DbP?hLe5>b+4)@T4aQ6rY@F1{w9fSK^BUQ{7l7H`@->??HSL~dAU_B zgLaHZcgJc(4nhT2Z+{Sr5%d?-)fxQ1t`M7ZH>1WkgyRAaVWsm=KgU?HOpo_%!%B(Xle7WmOu}vCrSV;H?a`Wrnng^ zdxY8v64HJpha*}9VwT+U8e=u|e%eS9H*`OCjt&WiXh=xFE48*(Cd zb=JI5X8hg)Z#_fxBDf>n;MN!6?TMZ%mV>oD)+Rgc(|pD6AU|JM&IE!b*8wbX#ov$b z^)K55sjb_s4`s|niqlRVd)BzJCMWcuOo8AdPu7-o1trtK%zF{bDKok{sjZ>~i-O8mml<_vcT^l$q0ec?h?zU(LT){#QT1 zxT*MfcI3l&5t602Eu+++5VhVUN~Q|@Wcy-9v`B9XW%Jt`cgI(fy1MSqg&N0y)uu7w zKP591_6ZQmKQ57VI1Rs7R}EIMcCv=KJQQ__@nYymt>_KGSA2R{&Ep`u^~=ls+&pi%eNhv5 zO!77$+guxVlF5yh_HQfZt zi~yZiQHi3MS|>6ZFpX2e3td%JR2J_GI(Qv4%?|e663V3 zae~Ghk0Pcb;KDX&|Hvg!j85-tiAiZibnkU;BcZiA8X#mY2)KWq>MX6SQV$_E>&erf zslmocJ)HC ze)_^lsBywl@5n?}@L_K;2qixc0cFv$UVM^XYeZsyWkFxg+ySpqqd#s0sOGc{YO=Yl z)zfFt5ZseERm!o+X^QPhd_pD9Wk#&Ltq{h>V~m~pNwD7MLg+bFu>0X8fS0j$Y9O-E zc0gGb!)JL2G;2msJI+%no6 z$MZNg4{+^&Q~9rb7N?K|Vg{BL4M1!EO~b#WOcO{8G!ewctbl+IG2T_)vaq9h&ZPw> z#EYNreqz-FJ@hY1|1sr0i1#N$pUT_={@}R%13#(x9=QZ)AhG}*ct-PYJvzQvg7hbM z|9{@79hmy@NO+_vwa2LaWqBv#<#u6)aeoFnhJkUdek6!e({&0Y2zBPii= zywYvCaZ#XLwmIB~`?0^RL&k%b1^Qn-+`4f*)c0Ja9A(FaJdgH4{T_C$!Y9YK;Z(dm z3KmD)os;LtU1(*DO<75R%p7R1sw2b=V4gEXuYpZ(G5&cQ!j=u4quq$(OOD40U-9nW hCiA~`{m0R%Ocm#3H^GuyVA*0wK9IeidGE=q{|7D*y4C;y diff --git a/docs/images/DeleteSelectedContact.png b/docs/images/DeleteSelectedContact.png index ffc429b5e5f3bd2bc3344492655b49aae195b184..bfff69b3b54a9ab8d3bacdfcfbb1f0edf85cafc3 100644 GIT binary patch literal 42647 zcmcG0bzD_j+wBGfltw_LMGzzem2Lq6k&=*Zq*EHC6lnzn0ck;`8|m)umhP19*!#{6 zo^w3D=X~$?yT5z)KWdnPaexbAV@F>1X1TI zBKXUvR}tReA39qRWm`QghyJ!ftVuAs{~;W{T~2@`+R`x*j7d;>4sq zHn5pli<9zuy|(o&oA!jmo%~fNf|28Au0CJ9bFW-?i#-&&i#L8%X8Tr7a^DL|Jfg+Y zPctOzmfNk9t?X7gmAARoAK98fue7y4s%S7^LnI$B#aU`6X zerNrz>8tC^B+28=Cr5I8H-_e{>ugOc(af^;R_VKhT(kUewh|3Ig0d3IG9S2_`;0&N zF)5jHZT+kDfwm!vtXId$6YW0TN7b$_btSn82WbMGQS7!M?-9}mUM_d^d|2yS-=Zf? z|6Z$Xm&LU$?RJMc!zwN%192gcgiqt(xcpdF@#<2PHaCgN01<0(hC`#E_0?;W4Mt&7 zOzvT3a?7t*nfJe8}-F3g`T=eof@)1 zLcswJY%EFkPT+CdB1$kz$h}Rx_4TO=H5Xs>`i&`c{^gpf9}lV|gq;t?HpPfjU<+?a zzY2|(&p;N9tPfZ4$Q)$KdSBw(HPzK&x*o^bCXj4z&;{MTsWtv)Oh7v}pci7T@#)j7 z$jU=&xe}@s4-LOk4+^jRKK+A5+`;FtSIQnXY!RXv7-9NKhr(FrhGn+xpQIg#dzNfs z!|z+2tSm==yDusnS9>13|B~K+;QFIXJo+0^s6n!aHW8R_qX_V|u~L;~LdkX|3G8a! zkOY3Hg_#ziHbEdB5b?)?3XYoVvFPg0pMQt-UMan+o#?Bb_%Q0za799LpniCpkz^># zCaYeA-&3;QrZyACfV<_s5tYWkya$TFw$V3V|)vf2c!JMi(aoKBIv{0gbSFLA&8 z>Vo`F-vllXdJKQwJGFbMg>;0ajB)X&z^1HN&r?(wN&tK{Luz_U3T>=l(^J|HE)H`N z=i5ZHo1ctLL5p4;Zn&SXX*D)BuA<#{sX@Mh1pkT07fPODgU+b&adl@TtLd88p|mpT z3?sc;Kc=d+B27%p*rN@J=QbmE--J-W3UUNGKPlzlYesHmhOKll?W=L2)%`4optz zzTwfk0SC1dD8Z_yA?@MkFjOgw+3m;$%muNFPI+`bSc2METc4euBOxLAU=Zc&HDiTW z*#G#h7sNM|Andceyet4a?v6r{m0R*6)b#cB{VXgaaL)Q%Pu$5X>cP3MCK+-RRnCy{ z-Obn%>xDK;x83OA;9xb2QvL2YzD&Oll;XD2sWQ@MTlLtxi=6@f{%B}u#4H9K!&>g0 zJGR~g42lg+P3)GFF*Ki|quWDfwU-m2>xKef$dM2coe$PaU(ShE2I6B5E-zd*m}-k< z0otk+^1jOL+*wgkQC*!>f=MNRzL8L?!gl34+s0UNPO{)YMuGGGs>7sHN<~FQNeL$v zm1i5HWyPDMK;Olded4ko=f_L&w1f2Y^orT);zKIEPy3$9pyGChRv#}$udJ*@m^#h9 z=OB045)4mac}LE7GLonF{P}YdcC*jMJG=}y=ck8SMP@{Hs)~x?;o+i|l**a~RGpMB z=YJVis@u0yi>$tRzeYmcp+JZ2=eQ5D`a0WrV-Q(G&zv-+eh5w|rViy$C30C;dRx2- z3JN0J#h?=I>lb{yJ74L%KkFW}vbWM7%j006&s`s(<<^?9jb{>9T6VAt1+ywI-$2Y6 z(@%!~n3|gUaU}A^BvMOnOKS*HNT3tO3lOBD2wl zE=OA`1qONVmW`M-%94yJ_E*1IOq3-i&Q9&SH8^^ioO7cMPz{?d7ab~Qsh)#L;-B<^ za%JUKqSH=K&$A6^>jnpy8({>7J+`pT%0o?c_3`q}s&doe?3`+76h+_q6PqWw(2KrL zzBWGW9x1k@=*A}JJsL=p&y0zW&r#9Jk*;<-uL952efSi2jv#%1&FFTZdQQR^+V=J~ zA+x3e^?MBQi-(VW^Zui=MQm7kj6cg(gf9QXhav70%k9k7^FFLRa@f~~DBw4$F};|A z%-L$i8{Z2}OG``7P?Iy1ax`$#KW3V%s($}b zJk_;h!SL4Go1EX}6OnEu_wA_5zDH;}(=jk)BqrWwVJUFfoMbe9@x+rXC*-H~u{++9!*VYK+C$e)I< zcn}Uw4>#SXYY@U&IjN=K6GEESWv7+4zP^6!n=y-i+sC=)pn{6HQ$o}Nz2-p8N@rwL z)KEkUmo0>xFQXquaDI+f`~4;8>rKcSHhk=+U2D#fFtyJw)^f%568Fzne*R4D^(m^I z$380jS6jLmrS8)_Z{NPH`Pn-LH_`Fx+m~}3Vs+aJU^e*Y2<^Xpvnx?`p4po^q{LC` z)>2@?f>aQixrW@&C*hQSloRt24~ekOb4#%Io#ZIK70m9IAImuk6^9M$O&uxk;U{agi32UX$%rs3#ybJ`Byi}u2fkB?EYNI$F1&bNl@>+81_B6<+M&XQqyw~2yvy@!Ezp`pfW z>z2zi);W20ZPP^~Zd7Aw7O3Npqn7tW&pH@Phca6`JHM8{nKbWLGyh+os@N^{ zg~Zc>-MKh6K3+>%IaQqj;)wgd>1r9_zb_g>a~anxn#WHK;z32NS~M`Co@BV1pI1j#0$ldB2K;^U2>PhRnsp zF#5ibZ#hM5*VngIA{IpQU4XF+{`{oM_ea^mQ+Us)?P{+*CY_F($X{kG>MCsnL!a4R z=e1}N-o*H8a8V*8-rq%pLho5y-$>6$Q%eig{bok=Svq}gyi`VB4*EqtrRDSI@N*Et z-Okrmxl!u1gI1rhn$=LUsV-|^U9|FDZC1`xSW_>0!M+NfXn{eekg%}Z>6o8k*I7=P zD%IQViJFfdCIf@>lp8gxi@aa>74%1w#tnFVQMmkWqD>5>Mz_>k5GJMzQZ!@E;;=3; zwHEZOeHVL-R}Thm2KA6x*Q)fcqPhJ+bZzZxiz!IUaM=emd_t!6_5LMVi3tAl^TRP_ zEvBQRIR{!QvB7L7DLZN}wnq#8XL z;rq(;%IZtn;WzP6QTL-6wRIy4ixUk8OnF-|S((sdQJGws&vkTS`QmfbwzGuN#jP?3liHtW# zlhU8XcZMp_PsgP#dCT*Z@B=d;`D!~A&6K;q{*U7LuMWXru5G^BtbC+jKtOE=aF+eF zhqa@?S#A))q@&(JotJxwEnWQV{;(n6(RBAwq*xHSs25X*_@s z_7dtc+0HDJQrNX)s~3!(f_mRP|C`((CLeiUjyoR|tcjI*+cBBgs3+(2O*A>5IkYQV znKaMl&yIs+UCSr|=*V`$&0s8tuSAsMD*Bm8j#podH;kuT3hbt9j@sHLz_d+TS|-$b z;ir-NS@=brvWoTalsn9^t^eA}9ZYY=#zNCq!{A;_*`Y5Wt3|pur!e24w+L4v8wd7e zJzm}Q9e(mMwJl0Kjb}FUL>;|2;Qh|_wnp{Y!|14B5ee~QY>`d>h}D-SG;BUgzF@`A zDa&ZOU9VK@&Jym4DgQLAPU)QG@|g9(I}k~j=+XQ?b0l|0vFYi5S8M!`O5)6$lvDLx z{rMPSSoQhP{y0H1P0lTEPB1ckO|G*IVwsYg>ulZf`lGQZ9wNo;gujK@F{rwLAOXhVZZl zAB27JbV=?jm7!Y|i)g*33%|^!2PNvP%-3bSeTuVXe*g@sQ9XZOQ&5hUntHh{tlN=I z1VqFd*tIaU*~mu43aUIY|5zTS-YWYkSG{uk_lrKu)O*S5naM`W+rbU)KNdC%8uMBi z6jm^lE%R-CloU4%7D7T~@NJfKdjDet%$Z*legAgtD=mWn!56UJKYTE!aH3wR^NOvY zsw}Una3RboFz&zJwzolc2ttR;X&;G4V%ANND(4V)rahMuIE1A9sF!Al_7mt$LB#Sk zT(!B^;Ah0dP9MW_NXH=WHIyZcPcX3GSfMFr>3C3$LoN`wKTi;CI_Ydd_GWRs@!v+H z4<+fC@c|fy6s>CV<{((mr-Y^1?}g~fT&%2bndMa@_SRqMH+rx|tbj3UZnRU)n+-xn z&Ok>OnD$`9i` z{EE|!8C&Lf{&SATv;m#1?3AOk-F*tTqoJ*tbAwK6SCYq;U^(#qoCF(6mT#^7TFTX{ z)N8af%RY9y(5pT}O;mxuw9xO3*m=M>Ge z5)X15)=KTJM%gIM4>CN?2@CS2@djw44tqnZVcJ?&i~68|KruONZ+}>gI%`}pcp!n} zgJmU~Qb$i++4(_jCa-o)=d6J2w!kg@7m=c(MGG)ZSRGhlo=&LD2a!_KV7igb7! zvUSCb^{%_e^`&&n;A=2w`t$Yi3>;3$++&^+ark_sR!OMk;&Og6OebUM_3F^x^<36W z8AfRw&K9bxVp-!H`n4^miaXR>aC658>qk~<(`Ay_PqujUUF+3ey-Jqum2_gX`4V@}Bf2N?j;wFL5k&aG=X^@h?@16=^Z)n}HXWamUtQZ*;bdcNS6aGKQ6``7l6H}4tzu$h#~eUYVigjU6N9N=8!_$m>T}Qa`_#hCyUpfpQ;{xHiDzL5*W8* zr?sFX=_OSBAF8Hlwsz#1m&&#&2-=3Z`^Me?-U=c*FC@j>EWsgvi|ua!K#Ip{j^{8V z;oIiRm|y$f%A4Oipd{Vq_Zodh@c&oikkpvO`lqN%ajS@I_y23*_xc{;mBiZ3%YsDw z<|rm9?dM-wD4KjReCmAe+a0v0%4e>ltJM`dL*Jcpa^j-Bw+bC$u?{Ou%AhbvmWtll z-34?+m?<)Z8Br~s`rSH8Al|R_A{D$|tY!km-&@w~2r>KP1ha`O6(5_gT|EP__S%{Wya*@o@DF=o%xy9^BS|Lu;medP>t zrMbCVT2;;ADmi!M`B5|+%1*wa7~N4XwH7Jmhiu82R8fG#@Kq zJ|D|a<7#w^DMK%@7@oYmJ^Hvn4^6*i?nA&Tyhkp&g_U$4c|IS%C8NnN3Xl}$F(pw5 z5KW~27YC|hs^uaPAs$VLYB;EJpAfB8(B_}dJ(ik=Uhp80ErS2{?KQjf838(=o@#D1 zyv9%VP!C6R8swD40|d%@JlGq8e>tMW^8f6Bdm|!bi#QkgKhOsAthDmc3zer;!(jPH6AGV zm>1UjMT}PRQ%{-Q+Q`U=etY<}!gspqrh$or%@ppu7ULy6n-!sGy5yI14`-1L3>O!- zO+mwLJ3xz3IrsCoZyzOLqXmZXj>FGI~d=K|WJwA_loJzs5<(sFVhg{xVBZenL_+G9k8{+O&ht@T7z ziIjc*ybCJzZK{%zrnspRG}T{rYtwA)&;? z#AUR+q%nl<7%m$yESVKXy|CQ0kZh%B4eP&{azGUE7N85kNWDJVQ+fKHGXBN=F&>MXdP9ypyXP|#)@Ks<&$?)f6oNg|Xo zBJZTXOr*hFgnmg(l#byP^a8}>E)C$#X{IE-SPZ*@^$o>6#rElO00Am2C@2W1SU~5u za^z@~E6Qn2l2rzjxEw!ZumKa&Ccn0}cF%3P+1}3g{d;|i*UZe!fVrLN0zErsH~+pRoNP5~g7P2Z*QdQvEfR3!gu zyWT@UK)4t-WMn5Nr&w+~UH#6Jv$s)VE1gI%H!L5Hv?1fKT%$)vM^s{gTi$!pw^&$0 z!&a!*GoJ2gbp{}BY5%#jIJ`d+eptfnfjS{4|reHKy^dpQx>8QOug4xH*3+M{2P7Zrr35kh9A8dJ0 zI$OJ<*d)#dEfp0(c~GyyMMLB5dZ4AKc!P+jHN;{9=8H?U*b!L(3MyeAtnG?11hL1D zd&W={nV6WuVbrQ`@ct=uB-M_?z8Uu~cEw6moozQ$EJ=~O?)7@2V#`^BHG1vZHAXst z)y+*U1qJG~t!Yo}E+9JuFjw80a-VJR8`gaF-aS;apsJ#Lr9Z`TG~X*EGBOfOLId$) zy`C5|9UUD&4h&~&yjtn|3g$tG)Ktk!DxQxqF&)*10(Pqk;RCiX-Qm4#gU!jxuV24n z^X=i}OxxEWp<J00R#K(>16{34BcFvqD2c?v7Tw zyF>L<;0M<+;&RPEah z82-f%r=x4mUs0+RTU34tHy^EMuS1YXPIH@vGKF_>ZZNc(^H? z%K?dW^Q2=JeGilHDZc~5pKhquM*h#q`R&wj5_g6yZ&Khjw4CznV6%8JBZyu|9SED+ zbR#yuMkL+u=SWM|w+}bh)G+iF`FR{)biH>tlPP|6WC+_?U=RS^!$dzI{d+P$MH@d^ zDk6y>;C%>F+QpwbjbPR~mW4o!lyjG?{+7?CXm71mZ+Is}c6$3#954hkYjH;bf$zhI z4-pY5yr4ap@A2H97~=jCBSA;c2hJ*Cxer#cPYFuwV9XU;bs={oiY%wH;b(vkDdKo_ zggn$WuNF4UJT3tLlgBX9A+|ce8Swu&@>#)Zkbgh0?)jg$x;$mw(?x8D?r#mJC;@E+ z^7bRW+fyH0(0<82Kv!X!Zzlu^y601i19d#&-vG#K^y3|`Q&b2m%??>>ipSre#k5eB z%M5@h@BRL*A^+HReZ?EC07F&>!kdy;0a64EKpO)3PY;dtN+V}(D zJ$-cLG7Zjd+}D(!p9>No=dg%*XiC06@UG_*%iv=-`feJ1wC*yijA(-pyEp+b-@dUz^Zx_{ylRpDic_wK8n(8!A|lA6jP$z|%AJm4 zO{UfW=K5fgBzHK!MXglgn3d%Fg3G;gc?)CR(6I(j7GEiE03oOdv4|V}1dJjdmIjOKp-F^A}R$#S*6g{)&`PsU0ofGOq|P1otH_`I};s(GKWpKt!Y8G>xt>< z{sd2-KBbY4xk*eM_34x2#yA&9V+@L!%R^bw)z$767EJBFwBv=QN&pu;dGbU-0YA$i zobleh%B8qhZ#+FMOBcfVULB;W;j*UD#=C@|0oi}=?08p2PF9NXuD2jQAz=^^i#N*I zHXwlP3Og>QPbiQq9K>ye}r9&(5@L4Ch4U(PB` zpVV7g;5$eyuc@h_6!u;p$@3($9;^7yUhKEH<=FRQ9mtrE17bK>1Am+94cHqL_vhP{ zy3c88X@RB;ZxS}|7DS7lj*bopuVny;w1qJ&bwt*O%nAXs!K}1wEs)XEB0#FtfAK;x zn*IHqv>)$?SnihU)T87R^R}w(uaB~TIGdRGMs?egtY^eXMXS`>%UiHZbYd0QDL{(m zwqL&)X1pRF`Eb>wB9rT#4}}{i8(U#TMGTrXav&*JUyhal@e7bmR8j`*st>+!O*i2; z^hK^xZYq$*kw@*CT%UOC7{cv*`lHy`7yt*5CFla5=C+zAaw*Iej1^nP8)`v6Y(C*f z{-p{5#W|9<%kgR{47f1*`sC9no!@6R5LdlZqB3TSUU)$iF#KNM%Yt`}xMvDCI zhpmS|+s&me2!%;t6ksqdqv+Im zEFu!i`7-gl2jZ2;0wBABxwb0_QkaSg5rZjK$php(+hpe!p23)ph@DPseipZRx$M_R z8X6v#y=(|IVwcqp9eccs(PZfG6Anc*{cB&`!RNrqNniht7X3Z7qD&Qz!Yfy<{j-(I3wUc)g%b|J}3wRcfcNHqsyDy%HlZEaZ#{BF+*MX{NN zAK5fzW@dumQ(!GAiE;X@ATyH@*a+^hRr-D+eW2R_)&(%TxGeWj#%%(N0tgg2_0wX& zbwWbC1P5W1>En5N%>bb(X3_wT&h|Pt0YPel`s>y2G7ZM5tgdl>zP`6)n%bg}ELa5_ z@(uFiSO$eB(>@Id+h|H9M*H3tH&iaQ)&~oLHONHQXY8@;ki=61C19J#*5HBmaY~<2 z#)>>blYhh{@w&n!Ce@E(TtM4#5o*{KBaY(5_{7@!p%#4*|H(2aFIttEwW@e2DPP|? zKR*Z6lrkv0a{&Yg=)cl-r4P)*R(G@Uk`H8wyIahxAm)d`yXja5eg(!8q)q<49^r~Q zu=tA2MuqBIIy!(Wr8sf0!f992{oF2mzGA11p<4h}p`4}K{A7FQCmyWig&xgWBOevd z01)?TZ&@~+l+$Y3Fy8fNuhZ|vrIGJQH_oj5@gV2s=7zJ>9DaOfJ3vwiXMM;Fa>d|& z9N9ffY^VY*NE2&7$NDpfz9%NY!wU@yYlOL0{|Az@zQl1Al%C1n?F-WtSXqnp4Pv{ap`pOvjuJ(;1zye~uF z9WNkb;T`BtyF@!cio#a9mR+7|y7P!PEe!&b;G}Tf1OA&khTUAO=HP5QO z{kIB3ndt4o^3t$7*;B=!+eWHqfLN$!Iqcp(nmTkP&3EubZU2aRyS25o4L_H|69p5{ zpu>?e2MgcG)U06WjZSt@Z#n=@nou_=O13)Ai!GT!&gIO2@;Z4J}p)7~-mp%{CJ$4hkD$U2(q1Ntgb#`u^#Z5BDQxEz%-cB*WQXsU@ z;I7-hVI9ykB#6h$WlV@U4Sux6)A0v0e%R$x8HX|m{|sYBkw{)Yx7(R>ZY&0V_(as>q{t3dl3dE|+{}o@Mrp#o@vyE$>Tq z1DqH}3}F@yl=^KPTcdujP=29|2zM6H53wPsv~Tt)^1IwerbPMe7emi=k&DZNA1;s_ ztvB!?{YCx!fxHG#^Py|!KE2Yn-9~b1elUIf3vVtCa&B{YNnQQ*9v1QCaL-G3>hVDJ zzRVy1sWnVj0D}bq&3?Va1gSx5t7c|Df}J$}?a!Z$Yya#2lK{?>A9?%hK)|mEKQ+lu z{l;g=-y6R_3P0Fe^Z)PQzc%OB4*%LSoqZdns^EDs5R1M_u299TF86-HqmeY4D6=y& zThG^Tf2%6`V319$ugzN+v4%#u5*-k5sotlkq#5z$J6_ZR#JIQ#k}LHx&jA|3!-IPW z0|=RcTdPDSo*$IQIcmdv$z_Ynh50kVkX&rVO(C$#(g8+pUR}y|p&VRFMbzX1bj-bb z@0ZZg&`>am8?=ZU0NYfl$WD44a!|Xf(US0=&s34uAs`^2`5h4+G4Tl;PI)N+U*X4( z_&08_JMGM)6Efu{%^P)I&lJfKDwGzRD0dKW+`7fUlAfNfoB%=?NP!9h0Nny}7o#|) zQl@fmmKukxuWy*gNzEuQr<8N;{+d8OOP zG>_b(kAU_E!}k+y4HqnJ)ME?8L`A7;YDyzl1tK+3CP7d@SuO@@Mbjho91_J!La$XbkV-<&lq@7=j zmYEz6uRdg83*@4T%)7qomCj*HJof93fNLmgE>wFyX8i;*g34e|$^3{3{TbvBP6=rC z9v~LP@j0k{GZM`Hh!z$W=0aHrXdHv*gV%9zYC=$gR-gB*-{t3r0w_^IIl9r&A*q-g zs$T6Diw4-5?t%YcYh*f)iyb(1|E-&Ujkv|Hd<`@8(}yWcx?4tt(#V~G!2Wp$+Q81h zV0yGQlSvBt#&5*Tz!326-3#$z#a9i!xHgL&qae?M9OhUhpCU~_Kv01tyqTSMId9j6 zG(G;dxGrFT^7eQvAhW-+TzEuU|s>AqBv*; zfLH*zRs+Bdp!JXO(oo**ruQVH3G?$Wpm$Ew3=_$hs#%ISyD%$eKVq&~LvEQYal30?0_blkoFz!qeyd)A20M=R2cFX`@-9`s^ez zWDn7R*YTN5$A%C;AjN)*v^r;{rxPdD7AyN19gD(r#{wFg#}ef{I>0Kq-~3xv_;rQ; zTo&9>+)I%Hn8(izdalwJ968ol!q3F?8q+WWJnLTO_iFd*olim~j z?8?Te$_wPcqa_jw7cTcZVWZV93GW`Z-F>Crm04b&s<*#72%fZn{kn1?^9Q<#nAeDZ zaNC#cLPTKI-arAvrjv{7DNlj0d)bC}lmp^C)TXX^x&V+8^&x;kan|dkJtuAJk@wGp zLC;TRVmK4brUzR%41Z57o%mIUS}_h*OO@T3*cJE62bcGu^;>{S>B*g6SjcjkUipFe zk#fp?edIwt6z+#a(ZoC@ysnM&Yop$kyN9PS((!~>8T3mDw41SWGHkI|TfAH*kI^96gr*h?& zS`GfYizB!GKhQ6~mB2qA`32iE`)>^a?bXBvm;eDF67ZSc|D%O}9O$Lq5CA3gty|L| zyY#$zWcXmD>N)4!p08xWZo<5MAk6Wki?NF9lb5j$OT9KsF2t?Fbma1rV zsv3q$;c|;KbEexJ%CbPvnmqfH#JNpJsO2{B(P%bp-Kvs$#Km#Hwt%TYapw-DZbh=% ze9CNn`ED1F@rPkPu$%&G;RStE!#PX4riw}$uQtZZmlh+rl$@N(P?SeipMZ=0V_F$L z0YPI!L#Afs2_O}K+OpA~(!I0L9u_t}Q$#4$pvW2kT=oDs?Q{SU$oX*NUc82$^;%Xj zIj7a54CzAiQ>zvo`SbVP)QPug_z0e-o7+`1i*|H}E7SwA5m;SbSA^~oi*Ljv=c z?);wa73Ng9x3}kZev-EX?B2IcMggZ>WIhH2pa#pMR6^SBk6~c|sd#yLNyYIV*Lk5^ z1o?aRW`>5^*^j1yI$H@j2VRcrg#K*F0J0Pti&JLJhkavQT+A z8Co1d`dm^=BSAHV>QtRs@tJlgDC{hhCrXg;(EWFn*3@5i7QQ^3a44``0eRQUyECN1 z4^ceDf99U*H{Wn>OC!3SPNKhp8Zd~~0GPmc7#|ZODX|2oAO@xEq!dmG>3IHF6U{PP zIw~r?@866W#nFwM-VuGo7f2wCFRa))7_*G$vhfb1aGXYP_BYhm-`|`9wEr>KATVIo zH4_Q=J|J&s01p}pyI~ipJkXP_AS1t&NT~6o!vj27M^{&NYU*djGYRCV5dSRY$jMtk zrHe+3cRe7A70dj>F4TZsmy-8{P^87_7*qxJsk^SI%U3TBPKHFUB{6~rrqd;-^H?hf^mo&iw} z4-ao;$B%Yc(z-!bL`XWiRxg@a*o~iB$16+W^Vu<+zC|uW>iahlOc45rLS!o3|JJ|=)Cia&hCscyIIF;<2e5aww#j1@3)p~ zMI-C#gyMSPgiVr&wB9uHy+*%kIy0fa!EIg}7+@UJQ&VwR9>X~#kKCUe(t?blMEnJNVh@x})F`j`~_F=2e49s;V#7f`TflNHCnA;g=Qb?(N%e#>s)5(X#5; z8*R$%G^--4_RAnQ0V_}bW&G+l8~KFP&r85;stH!7tj6i6!28!%l*pd}zEkoBAz`uU za9}kk(olh+9Q$TmDeO|FTL7!^r%=}l2Z;;Q7a;M>IGyPxT|n#j`1tg+wlh+VCg7jG zpkk9Jy}oxrKncof?cS}lxl2zUqHvdy(QK;f91s`ACOi%s)TjAihnRiK(Z@zjK!zV| zOsJ`$vQy6D!l6a_*HWCU3r^``pV!~oCoqTf7DXKW~8};wtNv5d+ zDh~v7$4PjP^9u?9L553478@7W#bET5zG#-M`ut!F)CcENu=99$p8;uPEdXLAj#rm#z69|n)`DJq%$TsF#|pY}94f=#x^^?^>~uC~vNMbE z<@tSp+M=$&V=|nw(W?JJNZ!(mMb4-uQDXthJ_h+3vP%{!;-RSrOZ@s+&*H(GQ?0vQ z8M}v?2!LIHBXNMY-+~ASbl$HO6=!KFaX{CQBhQwYs&YNn@E^Ko!y4KBq&33K_r%mNHw+mO!e zZ~V+92V^8U&l5seGYRQorDJcFo*a4kW>Nszu@WB>{g3zz$72A(kjq}Zg7`Z3Za$(| zk2|2epyxv_`?4Z;4~@2{aGEb|7;r4o5@AWh4;Sig1BMHov(&ixKk8B7zMoa` z&Z$%E)3lR%H{_9E1jrD;oa)m$K-vt~J%jBBU=l&J$>0hnIXe(^@p37VAel&D_-pD> zAlei$N5W+&S4i@kkB-{%i2tx(5ju`QKv4*guk(C=vp1t46Im+lUyW=Z{!yQtpR}Ig zVAEdBtO&OU?E-N#M~vUKm?WQ>DgtW&@6SsCUD#;^e~D~7a?e(JEDyfBixVu;ILfIH z739ZzcSs%vOQ5b^`)SF7^K#Dx%;+WBpvNci9QHB6qh?l$J?3DSp$E$2Dk>+wos|rZ z7d0P#JBNURz0nEPLDEInwHi58|7fl>!Izsn`?G5yzy>VG_ti~Voc%EkWY zu3bv+|5*D?os`2seYTzNEStt+!1cS(zMz9NKR*xP&N$emvrmB`#&1gH0kcS2m&btx+0zeXJKoa{A(8*V5?G*Q-1>XB+coI7y#iORGAFod%KhChmjHGgJW)@L%4$uf6OGxtvb|RS5OS)soH5c zyaLs!jiC%cR!f0A8`I2w{{H@e7PnvSd0lDyst)Xb_p3hXY-=Otcj07c2I4&S_x857 z+f-C=Vp0N4w2eyi-6!Bv1hyD#GHz-C&uvN(V4;gfgInkN~>? zcQDgll(#n0(9-UH-MOS|w*b!mgRs4%YZbfN+o^I~=38*Bj}<~=PQ)l&8?YLin{zJr zu&*ywhv4}$6#TC5^4P6@gTrfIl&0zzaO0evTA{oW;k%FZb#=@4q<&Jmp|hDzeMiA4 zSfodzhVgk133!i$MIoH{$AR6+8ub zF-yE$40Yu)Z@zJ9xvO4btc_SOxpHBsy+m?g2!M!s9)3@)t-U?oc@?nR)Y~{lI41`` z%2UF@7~Bm)n68AIwd$I`a{ex?t{uc9x~MZ{TovVQ-YDN} z5dJJU0&LY}g=S+#Qcf6<&7anyyrmD{>^f202VflW<6-%fXZFVe$iIqyGm&s)0LkR2~9(gb8xs%+NU%4gjt?J}qcvKfb8BOLzg3p?fu(mWCj1 zn;0>q3jQm~DGHYDQ31f2)69a+3i-mK(6OGW`>ab%JpAsf_YOv@$Ce@Kmu zVsPLIk$Piv4#d`xxUKSj_X#RRtJ5>NWXP5|oOM5jUIlcfktD#3+yPrJ=>SGOq!8`C zwGEJ`MZDH85VeMyzlxX**n%&x(*z#e{$_MBq7h#&q*J4P0Bh&3&m0eWw0u2~ib?%B zk|TU@!y7zkP35ypW&<8Qcm2k-pN+43UHbvj4^55!9cGx!Ts532QF#rUW=Riu3d3oIaC3e*E~Z zeB4fe)|qbY8)RVOeQ^T9`Dp{5Oh+tF1er;VCdBH>C9tyiATcoC&1@;eRA@O1-*o|p z_~ttkESE}cHRIj8H(8B>t;TT_85dD_4S|MPSv*hT`I&BcXz3p~>^d_eeM_#*56=fG%w*{TC&> zW7~bVi!N?xI=F%6agJtX+^Y>Ps5wPo8R5$g-ZcK>znKQ}sKBc=Xfhq$5T+Y1vIjwV zN{ORm+vP}z0`{P^>~r;)YKCX`T~BO@N4`o#Jbd^NFeOa@ zCBb>r@mw9G{g%*G#LYKta6jI@5Yifu2!J~eV8^@co1i83_V&Q+06Of^=@cxE^lT~Ky$hSp8MnD3bT#xZl*G!s4c^E!Ev38-Rz<)CI$^Mvkuv1H z^q_Hf!@)-{+!nW=f*7f4T~pBt_$C!DPRJT715W<{hGrgoG%@28(A=#Cx*XNjUVf8FWe3^D3516+vU0H7F_)1D%mfOmUMIxUe^1p^N$NX%o2 zBIpN`9(TaLo!_tufoYH=3{Z0b_WrB>d@;nMqoaJzd%l5z(m;Z4h4XsB_-uSPdA#N+(3)U^swzugTV z_0oYVKRmXJb#c67SN;lEM_l(UERGMEQqawiD|4n{Yrup4`m!nmT`qNXLzw$p(hHf` zoo^y@uiiZbxFzoRMf@y|k?MD#?Sl(Jh|6l*mpLL)4%*`^A)8TwH)~#l*lM1#kTVTO(3dbyEXMP)V3rS~vA@nQMqh{ZZAb$S1;7HYu_Yx{RaH?@QBBP_P-gPO6ZVY# zp$p(olrUlYWz%C1qcIaA@W(8U?_|P3M{?tjT~nZb&s!gCPUV1_R|cM8OD6b+k7)1r zcT+J~H3&={O}8I2q;)_S(DgsciW2F6B&lW$8q83F12iCL3_>7)ylk~yf@(Rhj)sL& zs7+az*=NYE&%xG%KX92_G#kP|>((EMiZ+FmJ@Y=pRDu1)hQz~JMyoaG@gX!|7i&?< z&BS%ucVDnrzmPPL1GEsu$2Ai@ozja44Dt}~)}B2=Tks~3*>9@A^79|+BWYj1SW)n+ z+~0tzz!|UQXjtU~16_lHS{1?KnF~(kpP7#gdsxhDg(r{uHU@MOaDe|pkTAT2VVqUF z0k44XKbGxU#c+y`80R-I{}U|%$=jo;;djeAoWJ?Gqp^Y<5QV@42*wCfv-V#P9Mt~X zwGIT~;QW_;7qd1S?!Ad3Up#Ico`_U`#wL3o6a;^J+v)yVirF==Qv>q{SKG%N#6Px( z<%Q8mgfq$#Yu$6{IuB)KlZU_Y6ErH|CZF@Sz9W;FrRWX!J?-ja7SbD!$9*~1-b_|> z4f_NhloX0ZKsCxR))OrP9^JyhB>A?K8d^mZT&Dm)Gty3aJx$aVFXYB_vg>9+TA~#0%2Y% zn*Bq z(P-k~(PT*P5X(`dN^PPhyc~dgEGa*o!XHEHP(O(WXcgEZNqFN1{ki%*V5TBR71k)a zd)C3Jz)n7Q+=wzRz++N)dWgN3qN&NdGaD^pnI6Qh;LGi+4@!&B+*a(Bb(~+vdCL;o zV$N5Oy)k9(vY$5QO#Ab<~} zl;Spd4m%rsmYd>88zUKWF*1t-1F((4ghOmhG<1`}>_OkD_m1cDYc9caaioOb`B^iC zM=TZ3M0*1gd-QCBEb7a)Bl0|TEw7fmCZ?$hc3i70?rSxb-r2C+^G-?g96<-Pzf4bH zlJtoIsFJ}xM$DEBtY{;|L*{y(*gZP-UYI<+_upmgUQUpPI2@rjeE+8TxT`3~HcS0}Hn-DtE zJE4S5k~1NQxL@}<`+UE?>+%=oDYItHTI;^oJ@Z_?eEIWjpx+(Ngj<1O+25;mgW7(= z()J4#e8pmTS8zJr@a^ej4bb<6EZoAHPjO8N%NtO%-sd(~*K--ftf3zJ#x4a}Ca^*s zKLo_FM=Xu{gk0}-L<|{Df1V_JBi41vcu6c<{NDqSOE(H1WS~bEjjlb^(iX9+C6Cb6GprgDb{Rb>w~%Mf)3X=gfTYYr3Y;<*{R%fdu8l%}_%Nm4 zX2+6d)kv)lT@*Y_p`5*y+X~N|Y(x)RDk!{D^^3{Tb{dLz@w!i$em(qc&y!~^{AkKa4-!3hT~iMtKLP%CB-j>E`513Mq$BAuocw@Q4X zqi5Ih;9Xc^^Jctt99cRYmM8ppeb+JTjge&~2?7GR@#e`IDYhfE^(OxIR+Sm!3pcDD zMxF=LbisH@T<~x26)x22o`xyeR(Je|Mp99o9h}c|C1_qDXXWO!4u%S8l?A%s4zr)T zN;}`o)~~VSdU8`wh6=K?Uu9>!$%t)Q55jJIn8b3a=Di1Ch>ng9^f-ZT2!F<)&%k0S zUD;4sqsk3d@>CPfRZ(31M!%F5>Cxlv#mpg?X`3?s6Rz9#N4Gjq-)in49-&>e-xtmD z{bA6Z*b+uTu%UqIhGfpl%;_QiQzThW;Hi*7`B z;Ch3Il`jxNQy1$`>~q_nSXzN;Qw$Yu(m*CydC(F^f7AtpTRfMM_Ry<+>%sc-s1S z=r)jlccGYqJo3Mj`x$?TwXZ34-zN`ZiEnxV}TZ z0*7hQR5ffcPf@MxCH0gfou`8Dgs{`{r_hd$hC3MIi$U@vBfR~t+wu;!{5Z7Unfq!7 zcAg~ROiXx`f$|zd8=pk@*^$_2E*BdT+=@_%(_A5PoU&mKL|wS>3&QxkzFOgyqR&Rt)AA1alCRe* zF*Fy%<7B2^EWPUW(sNJNbG(sQ|C4iCkX`~qtg}r5G+8{AJ_RIGw}bAf5x=>1hHvAd z{lDfL9Dm`WKM$S5#bR_v3Tirt*k$Q(^{NnH)@Vr9I{n4tfI0lP|UmFVZ|Q#26(Lto`z(yaVvc-yN{ zH6+3YtvlFeXNifvVO&*9abZfHy9m}cey;ilNj+Ds1Vj0HTd~p zt|Kto3c4w-y*UPFUdvU}KwYsTd0rqzPnbLMBFGTADySz;5qfz|x#-!t69Bm1(YX$`z=a zOt;&FGiQP)2U>r?K_kR*6@)A+XIsp4(tg`0m%F+}qkTtH~?#qSFjy_4VZ zqKO{i*F{tqQF<@GrG{FlZmfj4aBQ*VnsgwQCdOTD8tE%0-!lQktR7jj)DF9z9P zUEyryGkj2YvpNa`3ElI!cH-x>&xZ%u-^-gcl)1+}jvQQ%{ldt=AavOpJrZqqhYPPu zQdwB}=jVdv3eD-G7q$F}6X-yj3Y__1D5h@JB>|e~G_P>>fJ!wTh!UVtxXLcPV%pmi z_1r7O>Ph{{19fsPV?YCCIoUcCtk%3Bh?doSQ7x|yMdVetw!wL!Z^xf=2d}~nMbMx{$bs$6WzjW67 zmgA8_<#+!Yr*{38{pzfXIM+ihEY))Ua`dI;aBXVg1VybMBUVl;TR$V|XRlYT%=9k! z49$+L0!tY5r(|!w4H?LqX-U!1duOLRcTo=I5He8_jf2D1=;@zYq2Q`V^U3Zq9b1DO z2uM8Ca{R(uFR_Hfj~;$Ldi7A+ftb7Q7Z}Y?kQ_Vq){9SBVl0G&$|x~eq-xqQIjB>| zH)kc~Yi1r{fDbXV2x@hJ|k*r=<8;qRh!M(b?FDxPlD%!6kF|!ME*ik2A}^ z+VERV_e>Q#uXSu^kC#P4FMn8U8<7s})Oe;@(&2>emw~^wX#Cm~9TOAx5%E~TD&yOBAKTGG zURBNE(xyuX0=Al6;kk#Due6n<+{Imu!RbvqI+||vV!kjbf8=43iXaZDeNWmJ{93{G zc40^=)@9{ncr_i32m;F*R4gy0R+5{F7cfNE+%AxQBm6e? zwj4yzhr*Hk9Qo1;{P<_Yb#eRKI|Fh-la`)$75*Hu^F~oW9S)xUaP7`Y9HfVhCx$f! zuI7h*%JdZuRO#cqU*Cxc4pVX)e7~Fo%~nvq@Gk7~u;&FjM$C*SI`z!Ek661o2C)X} zrCWmJEyv{y6wgK|-59J}tT{qSS1^~NgOm~B`!-oyYCe;Vb6*r2&{E|d{dkdZ@gg!5 zO$rgCCHKV6-C>}0svoMgxuJVjlxMAQh0Eks%4u%;?^_bHemi6HSf7#EB!+zE5XhUt zYPNN0mQzo7VYHa4o!c}GH-eWMQ6_=8k_`ky{Q7a@QO7}e(BcyKp*wN%L4u8)5Cs(3)|BK3#9y&8Uot`c6ba z%93*(;&GPP?%W)^b023kqu9Y7Zj(3ISW_rtFe%!)8E*PugboKD=|Mw= zK^7NTkMzAY%B$RD<|$_ z&YPy zj>`tsL6d~#x}CYv-?(+g^fY%Vi=Mu{=04>jJO5N{73C9dvShMOCvlR92$`S0Ts<%n}-~R7C_P{>Z zbdZEScSXM?c;*z~o<8$3?X0HTU~xbUyb1RM*FYf37kA?knC91=?!PX1EkLrt82;~f zAUubwmEb}fp8KN`bf1_1F|HUmWc=FbfsR92<>WnMZ2RKJwk)n!bU@FyN+#{+;^C%P z?K=abOB}e?r80kF(qg+b>hIDAsO#So%kPAZpwxX~Y*7dk_dK>+$BZ0(t}}5wmA8q; z&c7b1uN%3f5p+VEk?XJ~ySV6G{hdYk$Ll!7!S#!&M!K^zy*kh4bH2Qi2v0A-O=3Iq zaG$V=%}IesU>AeAT_+C05=9=C;1RN!V{a=8|C!jVIMMiB`kow(sN;H5$!s5tyHDkL zGUE{|jgA$%4x14n8CWJ&K(TxX?1{ko;WrdJ5^m-eJ*dDRR zJdR2G@QDls`d)r;Iry4U4ZD#r+coKJ18?y7o->4LX^qAG<8s(WVNeNUw=%gAJ$DFd z)?Mj|ygH42#BVxSRLjPy;=lSBwq5GWK+UZq(bYCjR7l0ZnSyu-TZ^{oHKjZwU4@lQ z;u4h)^AEBxs!A3r>B?VU&|W+wW+5^2656@`1rB%T2aD=8pU2MZ-?yBCM(f|{$iK?n zwcd0`sLW=nUGk6_cNeyHHK~u?=&>yB_Q1O$Vy7jsuE+KBC8!+MD$T8$-YT(Kg?Bb# z{bV@|$cta~ViY1%bE=0o?$tE-G~u@wWt}9f%_wOc7`l~)i}u<)uHbB^&?TFr;rvu= z7viVJ>|pU0>=8U5dn(SBMI3XW{It4oV=;*_Q6o^~$`Ke=-&YTsB4s@I1+nr`6IB&= za##u`4sqofb+#m=GmTdD;0q!b2&qGDvqW%WdM@&R7j6Y zeC(5n*$|y(lJ5-H?8Zj7Xi=%Q$>kC9FB75KV4iF_wY))05qxfQT;;&)bdrrTBL8+m z4^E66m^+N$RL4Z(2};T?r6SEow>A>TKw%Z4!q30hK!XX@`lCM10(h${w0HGLrusy&))h>%;_J%FeuP<6`JF^rExTmEU144 zsMc6`=o`~yyM+nTRm7L66)bqyz+(BUsYIm@_9_L3j`3a3W(lsAqoFLZCLp4PW%iG|xQaPo5h3sy}co=X)U{pX#}i` z^&g+YxUesGYnyX-WR;wDYZF3Y1A$aJ6KxeU7!RHu^Igl|u=Vw*IU<{_vE@r0JW99e zO?Xb_lVCI{qu#!-YSyOCw#m;j!BA-ZLOc!_3uDr?g}r!(#V+#K0~Y03FhuUbY)cD< zEcoJK>8WrQ|5*%qwL2Q+kPdxN`Ca}TI|uYhF~~nlIikCMzk8MKQJO{xd?``^{Y5pXZaA32@dWBq;M zExslNNrmIc9Tq}dIucO_8CD2$$V(I0%~MEiO?~RX{V+RCd5=~ z+p8cRe5x+}F0oVFRFyuV0gZ?of8L#vfitTW6pQ$%U$y_IVtvP#s{Yw2v^c@q@OtA% z2wa|T;;z5Wll-3cU#?=(?fTcd4zIwGcvN2sA z>oV2fPX6Ic2C=Rj%vQNy(W;ZFqr+pYiikvN-*Zsk&mJb&#VN9G(;!hJBrt$QF5zZ7 zJXH(v0;_zH%kzz&&AYI4JA7Cr+XNYfCHd10s}*@8zqmxAN>))-1Hv4D;SBm+IZklD zZP9?0+AZ_I1O-ZGLbj^)(q`mlHk+Ulnqy#tCd_{9uRT|@q>YDmV>Y^;yR|D+b_{^N z85Y%`Hi72@SUc;{WKoT9{)=49BG1>+LqfQ=kG{Op;&DH#9w&bmd{6zu@hQ?qe$X3r zLro9%Xi7RZpMQ+S>cM?fMDge1ss3BqQ`@$ZOA<~dcv17y?FhhnXGzKGDYtEw)Vtug_q1DhXSp zta^6>2+D({gegQSiGa-E%yRO~1uTHq zE^{sCREVvb3T5@s4c`P6v)4kA;P95pPYixjyGwF$MBW4>KX;^d+Exjt%j~IIy4(64 zRrl|{u-7UKmVU~XNB^DPJ+BYUWX336e+4^hNLwzfz*pF3X4OxY4HF7RCmhT?hk@?R~JK^`JLu>jqpD9BP!Ues#8hY zZTF{T8&wmO%T~milD`JZhG!c2i10ANOGg9zQKm&D!`a7?D{3_(z6e^$}#ZiuTg1ncAS$ti1t6 z`h-fIX}m4s_9!+PWg4FT+%@lgC(}fSnaKN@(YGItwKD{(I~EscYQ3>I{8?sS%ovu^ zEqFj!n4HV<0{{}>K|PcN!QHO_inI4u#IM`yu{+p*p?e0ZAZ~}Ah0(0hFfxIe0abmO z=^&pF-m6!5?`8fo^QN3>>7UKRs}B~3hE0&xP`y5tJOlg*)oBnZ=IT(qX1>wd#zu=qyG6F7U(Xz-IPy(n^k-f zn&7jf(ZH44+vOUV4cob3G>9QDDK1pp*~tu1h`?_b{o#bTY%3D57MW~!J#E`IGSqqQ z4*%D8%$r-uPmr?AtkN%V3PR62J_65PIxePC?snqkZZ&VTcrIA`H6h6@%Z;^oVRD-( zJxbEs^EBPKy=g|=vD|6v--p5as~oKaK`D0(!LbC6#$h}X!Vo{OtB`-F(2uyC|DGlynQ6 zP;3kGshWkYxBn-yR`^`K5q~j)d%;j_pz=52u_a?HC;Zgjcp;az*JWVaq6nuO0q}xZ zXT5QkG@EdgT5%LYtFHN@=`&%Kn2VvGl-8yN$pWuJza@!kaF`D7V!cK=T<7K%G{tFr z-pDf!mTiNvRN*!q?Ndl;X&iK1?o`=^q`eiP?5(jCbX5o z<*-Iv6%k&vE=Dnko%rpqzj32PIF=&?zehx(=C4R9zX1>|9N+)?e|WNpcwZvk&mw`6 z{tjV1+y(Ffl1#SCPC-G;G$Lenz###C=p3P*AP`T#=!d^x$6x%_{(=`ER?Sm;qzEwW zf8nS0Ltf9pDR^&9?`(SBu~7D<6n6 z*!WrNOgt$3jAS$xqTT#gGwg!Rk;~T$ESCSC$?g2dXLvH?Hd5;kbH5Kd=q~c#!RN3q z6Gn*t-h+F68&$GfHFdsMg`V4d;5Yo*QSz)GZV5N)gFnD^=quC%*%E}>>sOr$1zGe) zrUkMo(@4Mf0Aka@3c#?B=#N9~Zm4bP%U|7OqrILd{|v#-)mBMSvR-1j#KO8-m_C>g znf!qt#hoYhNXZXl!hj6#3U!|b+^5mwV$E_8@iMI&GO9BVW>)$xnE>ed?l(!CmiDu0 zS||~kN-qM>3NK>i41Kn!EZGm89-j;4w;R(nYEwVQ7sx7!js%ha=vtMVXC|?3eJEgo z0|P<>S}*F9ud%QT6zI;GcGd}{pX4}qHA4284)TN^Vy@;K6pbQX90$dBOTq4P=EUgl zBtGVy+{%i==hn9zM|z>%oZ1Dv-P>rWLEC4o+*2xxeV!nZjK&6v;1K#N!5tuGb1G0a zQ_c(7M$WugW(b8Y`S`8+rckl-Ud-Nf$mXS#(-G9OwwwpUD}6=qSpY+s>{L*t-58C+ zxzYX$`QnpB`Ol8sJJuP)6XfPCWHshr-+MtpNDIt(rQRlDx{kLX9*0 zZ9p#VhY!-_!1Xz8yqC26v#DN8%!LLGaHy$=bTYpL?9r+(uSO>z)xReK%h{tyQQ7dm z#5_$yCBrw(2Rm;r82&UD6(ji^OT9<@?q4`()HWj@Uf0^Z*p7F8cJ?%Xo3f~XmK5tH z#UlR$nI_5MM2@UHTSu1{z<($)-~#v=GBq1G#&YG0)GwIhI@fZWx~@mRx~J78I}YW8 z;s&KgAqkS#JPw^AACWkTgVy)5wb`m13vt?sGkOW-5TJ(m^_F?LW4uPexola+1bnC9boM?X4gAVQpW+FRne_oXCblxOMh? z`jM^u213EdbW&vMRcn$C@`1qrJ9E#d=YE!N2fEgIVr!1bhzMg>UEh`Kk2~dJt4=mi zFjW)TMVeK;KeeBeKh3kpCJ65^`Pxp`wB9XOVXu*m+%ind+J3MxZo^;STTQe_q?5rB z_izyH>R;hoaoMF9RZ?%e0WR84xNqC<>wcu@y};sDr2oy;|LRkCU8J9+`NfbAA!#9y zw-@NMcH!Cj3fR{6A1wnh>fu|7Vub#QhA9Mc+SRt@Dq(2g@_npoVig%FnnYlXPFwkd50tI7 zXl}x6Vq|w1c`wvrd3w16^z7OT<5({->w@0d>OxjQ>U2mZxg5ICGv%0=k^Y_+a5RJ_fQPmIWCFQu#72rujZy>L=0K$NbRt1wk`%CbS=wzsI-ZQlI8dm88pnX_ zNHx*-T`pjKhECFYaH}yns>|8Jzw%>cxW;T2JZbw|#uIB+J8}(4GjQ~j!Ij@vtS`=} zS*2V>ht8r+TaGYvB_b)_SXT_?ODSjLfaxH2#?d*wQ(>oww+B77^G>zsDzJ z%lW#0V_5Cye&11lCSSEpOR`oCk{o!3nlSuT$`uRsK|Q_$2Ft(0V$}v2Y0sHGCvw`h z_sT1pfUko0xjV0k2)eU9vw1w%XyN1z4V(p#hY}`Z7Q9X2e4W+do$SnV;mU=0oyXm5 zGNupA`ztf1tDXiUc*Z(%ic5G4;W>1DYwATlUk1axm{++_b+s#-1+oVhFaB=aD2FjD ze&*O~Htv|D4rJmAR@igpRE%O|>U>{zCNB;5`l&xzVw?VwnG|`pquQi^qmV`ga&pQ1 z32{d|Tq#c?*4);5pvP%Mcy?%jI~9Z%sMrfqUdtEhvzYf*`u6$?r>gQZ^9+eYlP+=` zvjSODjvI$hoS0q1_!bvV*;MncgQ8B}N#4*~a+VVon>4N3@#(P6EQRVCs;`b$u-E@T z@;FsZLF{&*Cz4HKesB}pNu#276Z%c_(`2cy`$BX;W>B%~Hd6X<6x}+WIRvt9)LX^&8i+3=BZ$1GI3w(s`%O zIsD4)fUmJB%uxY_Pw<=I)#E8!HYOB;jwMP>m{dZx@3k@DI+KHWqc$- zV^ebPY6FH-*LpUe!t@8NgmqMP%BdHlTi#pn?EH{jTln(Hz(CN7+@9C7Q>i2&+}FKi z;N(4>E(BA+^yBHPvO5mLoJer-7L zph8qQjNQmV=kcTn^!7-H%fVC(k%5`Qda1hd5ZT<4oMD<}|Ju9~z_~IF?vo{}W7)KW z0|sypjiSA!aE2SBVLyoTqCF*79L>!Q{q%nDlfn)_<@~*Twx2kCbx;XvVZ;0{9n_x} z*BDTIZ&2F@T82sN#CUhQ&>Q;8g`sQA1B}|Q!MpS^tlwaa!hw)EDl`1%LfmdJO`RH4 zzzw^Kx6co6VGm?6?iFc&RM^vKQ!@-u@-qtVIq!Z{Soa)=6%20e&GsLS$p0C^{sDR$ z{$A_jl@s%Un?P}Mk^G*-E&21V4jvKzt(W?@-sYbYjr~>qe}}_kOYJ2FNy30C1szou zIafO%sBv?G8JNe7ayk|^q=a*%o_=KE!(?F+02+Y+O`KF2ieQ~5TV8TitXyK?U=X%@ z)fH2`u^Af?qKCRqLMdEaYW0XjJ~9=Aq)!7PA|TYl#8$K1;yN6k>T^6+3xB3AEYiXJ z!@^|DUTp_u^Y*u+D#CI40%mpcLUf$u`ALp9`!7;aNPpT$TUylmd`X>>Q}18%PCEz+IG6@N})fm&sdeatYy%(S@rH z5R?xz*6WL@@vvsm-Uac`jEjbYZh9W|?-J>Te@f6*Jhz{Y=l1QC;h&E&lk3fW>d1PU zWO5Eke;Xydv6=IPu4h316TLI+ zYyd?!N-^Ch&8Kddt?5Kc%7>;fglDLjq^Q?w^)|bedPLg2jmi_fsvRN|va>Q0 zR)smCyi-$r=JWRl-zvRP8mjw?H&PI7wb~D7cu=H1{eg)# z87Q{%SCq|R3C)+!zCF3}J#|^)6KMF@DD*2WBSQ)q5QVSqeL++#uK7~=dy%?j_&9vr z>#eipWDM#(OiR;jta5|5fxArz)NXo)>v;;soBVdbjRF8njsd34>ol3N>#=W zi&u3MW$^kZNL%Tzgm*+L`bI#N;fxc#PTJP(fV4j+yf8w1r-2&ZJfFE7=xM}iqTT8p zRurbfX3`H>qKTIi_67kNigg+0nb+-gAFK}?BD;*l>LnvC&vu^WFWYHis5PHQhKg0K zuzO;Z&Q(WPiY$hO-pGUnevuTfYCmQ)JH^+=-)HyP4U4%juuTN9--C~!$(37N@|1+H zIJ4EMbiOUl>n=o_(LBJNtW%dKC_&-weVH>GZR$1g(u16xUhzyq_%hKZ4>R&GA+uVG zC=L)AFPpt8pDd5X<|fpuD2?>;_4BP3r)x7}F---i9ZP^V$2senG>YcrSMz;VZL8kW z9Xu7AF}EsN;&!zH+=Ygq$3wcLH!8B=Ph7sLW2P>(wR&cYYJ^Uo3n6H7Qk670eWGM7 zNi@?Q&>E7Fl3$BZKOMD%vZ_;9J%p$1$-m`ANTx&aZIB3CtUP z-W`0!od&(j8ewVGFnbww!HIe)xV-Zpe4ArWT8D@BfK>`A86vAHvIR+T(&K!uit%pHhj#9BGdwa^Q(f_U>)L|8_*J;_OFwWzDl zN!+g}UxbqETC9bq`_0<$4@exRW&Es_Dp%37<&b}jDt+(K`PZo%+OxUO#7sX{QoN?^ zU)88p#btCpG_-m}Y*h@M0H}%KrCy#C5S0hCWP6PYP#!3!CIEE@ zzBDcpM}~3l@AycgdZ@0%t=?YOpjNeEJ~Ov4RRPmru&>Xv7+5J+sf^g=xOk@Q<5QaQ zd+crM03FuGa2dpeQAwCfSKo~kVsjJTY|Ci?cxGvkGm|~K6J0AUR}IzLz)E|Ld$#;s z=DxiruXTUE#jN1&q$`fHKTS?k6kH6G4(&z&f3GOUbhf`7wRa5nUnP3+vt4W!YHfU0 zJVVmx7QT_ar;Y+*my%cah5$H~RGAL3zt7^XFUrL0X_NqcxFZg^j(+nN!CeH_$mlHYSBJ|C;ggaZWbsF1>k@Lev4v59 zAywK1tivr4$K+L;qu9&?1-t!ISR*VfWY%WG8-O4Qi`dX|Td<^^qUGdlCRg;%s2=|4 zGkl^L;IhBkYIAw|!V_0rbi--8a;MRO|51iZIaCpWZ)_>wxDl_@2I%&xo3pQ)(w8q+ zxp@_;^~$I&?I40LrcZ+Xs01z5eK3nk6AG&#pwAc!_RjilWBtWF&7~cW? zeq&YYk{YWT*VD-p`o9`t=@`nRNTOZwZs$!se(#w#VHhgPA6#krs;SX4b7SWV=>=ym z^O>C^`4_s-&Ywx1I$tPTFmOnVtru8}Ix<#ktgmFoW1>&BUF0|PK#siBZ5C2Ys~KLp zq|xz1-|W5|*6D5Y>0HV!Xp&%>%@{Uwh@rQI=Mwmc*uT~onKaqp!3zF9$hObuEcUiKf$BKWcpjB_Wh?6?e>}h>X>u$^E=t@l%+&%Dpskr!>r@jMAVEeSdxD}?BQ>R=OZ1AY+hBg0YG%J zpY=S#Oj+FiOB@tbQSbKXM(t|*gN*aav`>!vI2rXUI{9xrfxP~f)uA}Xw)7Din7(uaGjB~g7z9g#kMPPpo$~^3Ra%xAF{Ce8$ zAzJP`Y0e2mM~xF+RwFd}OE2t-4Sjhtdx)pz&^{%mghLuA(cNhP4pC8^+`@~{Z_RR zJi`Cy`uy8?*!_u&m@>MNMk!NLruZM5sC!`9G*0T%6QEINDQ^BCw^*jEJ{k>)?i zq5LNxrUqEl^vuLfi$4-ZCEB#45nZa2=%dDyo!(E)ZRhY)p3nf6{&^Wlv9uPA%?6Fg zd1lnrSm!<2cKg2nx)0FdWn-gJsGB#8WOeGgK!?PV{U_MAos|bf>Xd5*vf6h>v88bb z$S^jbz%)I`c#5!m7DKQviRo3WY|G~y20^Q}l;RcvHURiLgxdt-nmi@~wTjmZ|Nei1 zoc|Zq@f-XqO~EU3O%rf6WH%)r;KrJbzuB5tjG5Zh_8t_gKeHyVr0Wp1BM;kIX|-&d zlv5f?3Y%0b{Q=LLozVP?Tsp9#=k=7WOpB?)l&ouw?WofuQ)`@N{egIex5_K_c?;Ev zkypZ72?Ht1?`UeA*qiPkH*D!?+x+vXh-2Vu8EqvU*KbNX%)yN?PlS9TQgBr>OF591 zj7mozVVcN)>7WT3r0?`8sxBHP;2Hcn_ zvG=AzP196vlZI|H!xn~B(t;{RqhIoJnCS8p5;xg*U;PC~Thh;>>_xLsuN{*F*zWUW7FtbpV#<1IRQWAM-aB%mgQQd! z-zZvvPsBb;*LKPN+QA8XfS=QAc)YrahF4Tx(N--eRKH{lbD9p@&`!g2Sv+M`Kkd97 zW!RLA28D1}rLT6zFmbaxe2bI@Xw%VyOAWOQVRqsTF*dasYdP9mCh6p`#{(@ZVx2i; zTxnKSwCB!&^Ro4l4YTX%{qYL%2GGh65XIQchH+MxLBot}*OElI+H!bv5}w$*TCiar zcO2(ijQ%9Nfz_A|CMwy)ByBNF^1pINkQ<%e9+`+6z?DaQ#19BjEb>aNv0xat2FKw) zJ73aSL>SO%>A#RNQ|)kN`^$&CCQ%P?oulcwP;2Xayuzs~MnBZ&atii!GQ3}NgWGA`8|tA?mcrImeb!OxK?;0(;i*Q+n;Lr>r}p++ zTc=k`1p@J-Dk4XAB(XV-YAYEj&t=pAt$X@kj6^-!BIm3&T)?gAd3M5Ehol_*7&m0FqgPsI`j(VS}n%)B-W4`(V0 zrTLG5?LCXRjTxjvMQ>N1;iqm%R#lN)(c$OQ@V55$Aa*6~U$a;F;omA^;J+hEEpzZK zCJa#?({Cbf4+bTmo5>*pnBMRWIDRzG_qslN*)t#vtL4{TlDWg0;nxJ%0(5Lyo zXKMj?H$cz*Z65`71U7YZ6RLA6+)qOh7}~QYB2dw~zop|zD(+SU$?{|~++rjqKHf0A zU}fF{_mytxI2rH6T1(>r@R?bGUxIWMaTWr5|(e#1roUIjd zelT@FU&b?sD=}%Rl^?lbO^0msMPSUFTC;q@+oj|XD_tmPIzK6G*DMXjb*ZhT)-fG4 zPY~wBv)Dzha5o{$P*CU31(fJ|XH3)&+3*r8i`JoB(JWFbYu*Z<;hyvPq*^K-Wzo1* z<&sgkHF5DP{Oj`vmHRgR9%-08!|zmR)KX{*Ux6e+FR`{0fhtc(zv zIK&C{p^8*dd1QD+rOLOH8i*<(1ezV-{nkEM-75CldQEeXX)p7KMBZSFMys){ND}N& zAJH4ZtvR-+xk06eeG5(cO^P#W{E<$BZ3Pn=q9EQ?j?#Gr^@h5gG+uq@B#w`S_pV&A zu0DA&rD^zNZzb;;#pTWouUWb}#df>1$nm_@vitzvd8lqz(-SVwTPwAZ9=}*32UClV z__Y#SgTVufZzXu*3*@EgyPeQb(E__pn-$`WfmI!EBRKj5p0^QW-y^qdraBQr{h3Px z?5u-As0VX$C0Hp~Qg@M2>UlEGs-MC9*dGYFk~EpH;G4#GO1?P7zi=7-_@mkeXPi3n zBiV*wh8ezyW=xclgSjnreB@fr95nVZVh95a4y;pH^@dGZ<`>ms&4D!r^OO<$A*r(u z);k*|LnB3p`toOD=4gWwV5BqtM|^Qhxtm0>v2hHrEgd8F2oB5p&F|MpY_)CIJhi zrbh3KyZ%9=>4-EWbOlQV_$4dH;6XsWsD+O75Zfs-xx`sdvuoSDP>#cJ6;G?ytdx84 zx($3}un(1cQ4^w%lfj#|lR|hgPFn7mD(T1fEoJui8QtHkx1J+<#4{?5{;P5)vOiOC zfpntWns>Ci)rMWY80%4C)m&m6cL(y*6;2vz+25S0QR0OVpq&Q1N#4sL zOp_c2lc>ZRVkqi*nZ;ZxIQKpViLMyR9wmN-b8+hj?`WZ@Fqb|NX}64^Ws$unJ9jhV)dy-fx+Vc@`l@V!6vtO4 z&r>%l;P65~M?h~b-{~rvaY+?iygmQ(%dum0VczC|W040U&U`~-1>XqLIU&uG;F=XN z9!f{kM^$=YR5t8NTHbHI0kqMRA&VPFJPB}%z=Us69s8D5tFZ3&pDZMF_*NzVvODWt z_k_JHYlVL?7S&`8tp=k?6X?xB|Wm$JS=wr61Cgv&;~`rI&Vmn#k2hxTD$0N!^t zUUMXF05z`7_eVzl`aS~twlofv9obO`^#_y#D&apN^nYM~3VLHm>FK@;L<@v{o^@lQ zUEA~iz_0M`wO|K%EfoZFBVlaX6;^GQjiVQXh5q_4BaU}M7UO?&%hId#GHX`$x(HsfZT z26xUHCGN8}ev2{h^Ecwo^TuEov(vhO6>P&JiAjBnc&9y$7`_@QTwrL>+PN8LtbIoU zr`C)u!cwI&*!!m{ou~=^(|f+cXI_5wh2j#QF!PordL^+!SWT~vAA`K6)JGih>G6l2 zY~Z3;Lx48<1S^-vBz&R6#s`5(FS-{t(y+LH4{+lH+^So{?MMv5>`|Jd6Oj8qwp)Wj zvWi&MvEg}0@bx67H3s`-5i*Q3d|P$kkl1-b`8~{w;kR2`29IaG!!-oD8QG(q4 z(N{PvUj7X!4In7f#?0FRaR5m<1pYq>4W0d(9wqZC#PKPrar%rjt4xVwT~dBKN{QX{ z1cbw=X;NjhcAc<~Y==={`oOWn0K{GPi~|3@<;VjJ56(&)j7c>b{q7efBkoEiHzI z9(Qw?20cH*z(-IPgl*D?1u-SyjQ?Rl=vtpel#JU*G1FHZIE`F%{iicHN&DpBhp5X5 zvC@4LZ{@0tz)msALI;i>wje_hvS5WvDt@Mtb(p1ku8QTpD$f}-SIV49UVKCk$iMklI9^(yQePOQu5t=-1Y?Y*E@tT zMNoLmhk-Le{qs`Yr%J#l%nAwwsYzV%7X8obHjyRegm;${kRF90z-i$gnWIqLGPEK$ zhA?Bw_x!N&3&+9nOSq08u+ISpzTC-$K)2N}z|R*Sz~2x|)O}C1Ts{(}5+o@`8L;Ju(Vmo?Q*jlDM+g1}AwPb-4~X%=w*Dc_<$2)RTmbz3>LxZ=cL}oNLze zjOuytx9eVb>+?uHdigc)M8@xlRMr7o8a~3Zt22Y6zVSWjJKQbFCQLE6lx>iznw$={ zU(_L#N8+Ac_I$xprS@JetNckTrv?c49p_-TH-Gt}?UgntVE~d<(tg-0J05!ZsyY}9 z!BmeHAIHE6fA#bXV!}MxG2kQlqO()@apM0C$KJ&e{(6>zOY;Bp)-M!(U3od-rTkm8 zsc+>uZISfVW4jNJQr73?$3Su0%O_8sbR#?&jIELRG2;8GY0+Xe_>LdvVVsxM6^s`v zG5B0<*t3;uyF+`FoGB4O6|b(lWdlxVt>-GSyo7tGb{}VoSP6V~Pgwfqu3tQopJDf# zkW8TJ#)1zMZA>Sop09<<2ep+vV~=0}kD%q+9sb!4LFrLDziG)F9PoYIMl)RS1N<9j zEPSy+EXfQkEV;cG3};>{y1T;E>oti>g=6adw#BQ0{{L7p9!IKu3w2F(*>D4dAjmyQ LS&5X}n*aPiH9o)! literal 41733 zcmc$`bySsG+daGiF+fT|5TvBLK{^Bh>5vfElysMLOGpb6A`MDPN~d(A(v5U?=eIU^ z%H#9A@A%$7evEO3oXx&tt$VHOn%A83x?jsmi=rUmB0(S!6mc(sy&%$YBr>$Mwd7)8ur$>+x3x1frPsAE z!(ilm0M2k`q^M&1$LA0@a2kiWIprRiQAW%fwdIRVMO4gN=$Y)Oe3GVgLisNhX)Ns{ z26dAfff-grGBGP6fV@M<3q@0hG6pPDXYG%XS@ zc#WB=4(rgp%%F(!M}*g6llH8o{Y28sHPa{cvxXxN^bM=~mDRd!dEAcb zZ+#=U5smOp4YfKt+HU@tR!j0RDg}!6t%s+NHhj=2%CHiq1#>=re?k2C{(O1N54`0K zOYIFkyfV#deJ*t&TVofm*=IyhogxA_v~|jB{3sPB$4Y_XxO#{@g4!RH7}>Z|AEa6t zX?}NpyvTcBGdsQBNnJX|JV)8{QzX>&^^Po|$(?Ie8JttPCK>c5Pc=`7aWi>imRLQ# z6}t)6I*GEvR0(fMKEJ(a?~fdWjAxv9JYZ@lV=#=9^c3H(`!;?#RTpYrN^%9)qwEki ziizPopBMPuE4I&)#@N%+v-#Xh`Pz|woD#)!D`D9ocC9UEJ`zJE{xXXBDZ6cMLtg4B zS4UO9^MR|XO=a{62l>$2@;S9=RmBqLX(8&%t}%Zv9dGKv!lTr4tj6PQsh6^NPT1kT zW?8ZRGr^xV{q*}CC6Kt+l=9M)N3eSzxUNWl*XfTfkY)O~lx2fABhNBH#n{1y$Fb#3 zhx=^$ZJv}lTshI`cET6>{gv)5V){EL?wW^5*qʝ-G16Bi^$B=|)ab8VbYeF_g6 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 Date: Sat, 6 Nov 2021 02:54:20 +0800 Subject: [PATCH 646/756] Minor edits to dg --- docs/DeveloperGuide.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index fe547baa99..0de53e95e2 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -132,14 +132,14 @@ The diagram below shows the process of parsing the user's input. ![Add Contact Parsing](images/AddContactParsingSequenceDiagram.png) Upon parsing the user's input, the details are passed to an `AddContactCommand`, and this command will be -executed in `Duke`. The sequence diagram below illustrates the process of executing `AddContactCommand`. +executed in `ConTech`. The sequence diagram below illustrates the process of executing `AddContactCommand`. ![Add Sequence Diagram](images/AddContactCommandSequenceDiagram.png) ### Viewing a contact: `view` This feature is processed using `ViewContactCommand`. Whenever a user wants to view a specific contact from the contact list, user can input `view [INDEX]` with the index of the desired contact displayed from the `list` feature. -`ViewContactCommand` is then created in the `MainParser` and executed in `Duke`. +`ViewContactCommand` is then created in the `MainParser` and executed in `ConTech`. The sequence diagram below illustrates the `execute()` function in `ViewContactCommand`. ![View Sequence Diagram](images/ViewContactCommandSequenceDiagram.png) @@ -150,14 +150,14 @@ a user must enter a command in the form `edit [CONTACT INDEX] [DETAILS WITH FLAG specified in the form `- ` with up to 6 details i.e. `-g github-username -tw twitter_handle`. The user input will be parsed by `EditContactParser` methods `getIndexToStore` and `parseContactDetails` to obtain a String array with the details to be edited. An `EditContactCommand` with the specified parameters will then be created and -executed in `Duke`. The sequence diagram below shows how the whole process is carried out. +executed in `ConTech`. The sequence diagram below shows how the whole process is carried out. ![Edit Sequence Diagram](images/EditContactCommandSequenceDiagram.png) ### Deleting contacts: `rm` This feature is processed using the `DeleteContactCommand`. `DeleteContactCommand` is created -in the `MainParser`and executed in`Duke`. Users can either delete a specified contact +in the `MainParser`and executed in`ConTech`. Users can either delete a specified contact or delete all contacts at once. ![Delete Sequence Diagram](images/DeleteContactCommandSequenceDiagram.png) @@ -192,7 +192,7 @@ This feature is processed using `SearchContactParser` under `MainParser`. In ord a user must enter a command in the form `search [FLAG] [SEARCH QUERY]`. If no flag is specified, the search will be done on contact names buy default. From the user input, the search query and the search flag are obtained from the `parseSearchQuery` and the `getDetailFlag` methods respectively. A `SearchContactCommand` with the specified parameters -will be created and executed in `Duke`. The sequence diagram below shows how the whole process is carried out. +will be created and executed in `ConTech`. The sequence diagram below shows how the whole process is carried out. ![Search Sequence Diagram](images/SearchContactCommandSequenceDiagram.png) From 504c6d8d3700cd49516ee8010b7b9548aca6ca5e Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sat, 6 Nov 2021 13:30:56 +0800 Subject: [PATCH 647/756] Updated marcusbory.md PPP --- docs/team/marcusbory.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/team/marcusbory.md b/docs/team/marcusbory.md index d61a78f00b..895426ce8f 100644 --- a/docs/team/marcusbory.md +++ b/docs/team/marcusbory.md @@ -32,9 +32,15 @@ The code written by me (`marcusbory`) can be found [here](https://nus-cs2113-ay2 ### Contributions to UG The link to the User Guide (UG) can be found [here](https://ay2122s1-cs2113t-t09-1.github.io/tp/UserGuide.html). +- Added documentation for `add` function +- Added documentation for `import` function +- Updated documentation formatting and overall readability ### Contributions to DG The link to the Developer Guide (DG) can be found [here](https://ay2122s1-cs2113t-t09-1.github.io/tp/DeveloperGuide.html). +- Added documentation for `add` function +- Added documentation for `import` function +- Added UML diagrams for all the above-mentioned features ### Team-based tasks - Hosted and conducted weekly brainstorming session during ideation phases (V1.0, V2.0, V2.1) @@ -46,5 +52,8 @@ The link to the Developer Guide (DG) can be found [here](https://ay2122s1-cs2113 - Refactored entire codebase (on 27/10/21) to improve code quality (apply SLAP) and fix any coding standard violations - Updated `runtest.bat` and `runtest.sh` to automatically delete data files, and work with `import` feature +### Review/mentoring contributions +- Reviewed PRs and ensured overall code quality/formatting was up to standard + ### Community Reported Bugs during PE Dry Run. From fe61793a585e48549367fb999520d019fffc28b7 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sat, 6 Nov 2021 15:13:31 +0800 Subject: [PATCH 648/756] Add ContactsDecoder class diagram --- docs/diagrams/ContactsDecoderClass.puml | 17 +++++++++++++++++ docs/images/ContactsDecoderClassDiagram.png | Bin 0 -> 6652 bytes 2 files changed, 17 insertions(+) create mode 100644 docs/diagrams/ContactsDecoderClass.puml create mode 100644 docs/images/ContactsDecoderClassDiagram.png diff --git a/docs/diagrams/ContactsDecoderClass.puml b/docs/diagrams/ContactsDecoderClass.puml new file mode 100644 index 0000000000..888dc08357 --- /dev/null +++ b/docs/diagrams/ContactsDecoderClass.puml @@ -0,0 +1,17 @@ +@startuml +hide circle +skinparam classAttributeIconSize 0 + +class ContactsDecoder { + - decodeContact():void + - handleInvalidDetails():void + + readContacts():ContactList +} + +class "<>\nRegexParser" { + + checkRegex():void +} + +ContactsDecoder -up-|> "<>\nRegexParser" + +@enduml \ No newline at end of file diff --git a/docs/images/ContactsDecoderClassDiagram.png b/docs/images/ContactsDecoderClassDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..05af68778cb4bd349eca1f56c9f6d4292300cfe8 GIT binary patch literal 6652 zcmch6by$>Lw>~1>-O}AP(jd|;UDARMjevAWkANfHAp#Gu4|rk&Fr;%?R(w#ejv}ZRq%0Wa8OWC@YPfm^#EG}e7CVsf#;crI215k zUP>ljc5d!|&h`#oC@S`@_OETc>|Ze2`Z2!p@^Y6H5O8<4arN?capt#kb0HR#phH1< zUiyculj-rDp;dIi5f^n@H7BsScWIkMA%t|a?v<7P_ht-|6nO(19 z4arO8mme+qLneDiu7`KHWPLr}#`j*pioW* z3tC%u*!Hx6EJu$if{+;Q$sOjatwc2P1q&fT?nz>08CWeSW8TioDZr(FUT)f*4ewe~ zT&hNO=%|fzw!hCb9MrkJs@09$fuI`pT%~h1v(kUp7_Ub)RPGp4l$VAw!WrJpWoBe# zBqe#Sbw++QE>BHOz_7DJkfOvG3j`FS%r5AzTO|E_EoB zSy@>N3kyR71_Lzx?R~P?!+f(IG6kz#{%B|rcZd2xL2`0(R&z_m*iiUNTV6MJd<2(w zJQ|ZM7)%xeg+g_-wR;MC9n1G!C*U42Gdo^odgKQS^)FJCJCmD~pAuO~Q0c&sY^LdY zGpg?Dw?kQ0A(v}XOU?B&pQQa>N9S3+6cbBh*P?-U^Kqy@J2|Ltmh?WM7v)^-iN`Bg zY!+*B7@`>-)^72?qLVro;!=(%OcTgk{$?)4m*wY|=eq+ua+@0S6P4mA<|?OhQ-3rKXGm{_M9J-^~0v zWyHUzn3}q)NMCz(MljX8+S3^5t(LI8M2;7UvbwIw&cXcb3h)Sm2{ss*GmNYw#CzS3FU6n>+G2kg!yW%l1HiySrbyT=}-7f7V*VuP#^s*=TkJkbaj z8Z!Iof0zaqOAb;XcqlEme|Hhy%-R-**M$jOv;_D_cshug7t?gGAVq@?=EshYA;G~p zb3plHulwNXpF^>^A+0=r96(4tCA{VCA_}#%WI96Jy}h+HS+8xYkQ5$nbwa%Tu?CMj zU@~Bfx(y8hnft4)tORj)>#h$>L1g$#O({Evhw9^{Ony1M4kOAJhUNy7rMwO7zn5F? z%PgeCI7>LL#GR(M7Z*3Ae6$Z1sfFB@(F%Z|#LF>%emmt<-lDlz#Ws?&uu$t{{z}p( z_~-2vnV$j>k<2VFG10tO7z`CoBuxh`K}{odB_)QY$EwoggTF>c+w+1YRjbTuUg=o| zo0VcU);a!qxiK_RO^lst)s(E1c@O104vmHs;elqNM@De6-OeF$`Yi)gV;ARuQ@)>^r z-V33CsqI$B*b}o9^v`fo>xG_FH96bY)%P>EXA?RJ)OmR!q0@$Z5bC3&74P%?v5ij@ zNMLE|Dwvzf=b6n1eBHIAN6S~LML$To%pYfG!<&6{x_kJGRqlZE`OQS=;Y%LpbEwRD zx{=yGQv5}NOm3juq^%N&RY0JOX6dE*19n3SMX+4DP!rD^=+vYq(h9c`h+e|GlC2m!%H|_M5yWy#4=PIyJQ|l1; zR!~Lp2S1;zP-LHZa}Pg6fGhw8=B${Iu_SV1{{KPSX$hfRS=WlVq#pt8Lw%7l%Zf2a z$n1i4?F(Od7=#G!i6bxl`Cn!=_OkSjrKuqGFhLp#U$?Z>+G%Ue!jhcm zd~m>}LJP<$Qzmkw;zhE0+y@&u?n+)KCz-mhD@WD)c%Go}epemHJNzm)QvbnyVlk$tJKR(ucxmYVU6XdkNaN%BT*?8jTe(ZU8`2E3yrQlm3!><(I zIq$FcST?jmFD;svFV36`9XaIgpOjn5o?!0H375mh<+#8glK%dLPs%MZ@RQ96O1@0Z z{fD@e+F{DeoG?ir*Kz}7oI_WX_gdG890MNCE_U_ZwM?uiU*OeAuw2_PJ^kUUFad;u z!o#gWYID8Ufdi>*+X9JFZp#q}MEUtXgc(}&agUV5C}C^3KU}!9763IUHR)4&^U40g zpqtcyfad4qt+oQYtb26`DV7(3I^>0>!(iGj8I5>2X%i-ia z4zP=5JXU7r~Zv+hZ$CCn{}A3Y*L=v-JEN>SP9b?<7GR@kFxsu&x; z#8W&W2Je0}KpF*_C8C_B-$p5q7>O`c$nBJf^JQ|P7h{$>T|-`P@XRHb2^xBEPYc^(RMm~ZwX7s$gP?06n{dx z64FL!jzLY@+In!DFt3tHqFEVyhe{RqE>l64fO;HLLx!$r6uzVAzrj?8vM(%7Bz-zK z@m>c;C%%J6wHi%MxWIZ@mcFcOLuQ`fes~OVM*gy2H!NpwQWRJAL-w)J{VjG)5AP*~gl2_it z75BR;MW~%}7`cwgBILT550&+g=Ch{wx6>XX+cSMX@YrWe&j>6E$PMBM4V%4 zU{JVkI|0{&+eLI*;2HAjt2is4zwzB%y{S}PeODvA(1T_XO`s@NAfln6kz(PTY4Xlj z{GB`wv{J&N0$(EF48DxfK^ZK5f80g5l@O(D+L!uwg`=hB&;Q-_LVmV+qfCG@>s^ef zXo$ThI~{Sz=u3k!$n$Gr@T(VBf!G3Y%B|n&KgqAH)UGwy)JC7&r$uqBMP4o*YlRA_ zYex_wK$T_N^6WdNZ1J0LUs4-yZ+_y1jCD{^O! zAPyeg7FcE=NfPJhmW6|iL~z(1(9H-}r4$MmsQs-N&e2aaCfSLtID;{k33Q(!7f!=` z51+)ykyTHvmK)$89^ph>ZrG1ugrpe}9X(@&hg1o6t_tYl{#Ed3jR*htIZTE)ty(kR38)~L{h5q+e_fHvGGFFzwBK7{WrBhqv_88y5DRhx#|~3Y;G}F<5DT!ob#C$ z(QgZsC#el(g3b?O9R|{|OdL`uB8P}Wehwaf&Mj?wsbgR|2Z6yxP#*?3FJ1GSYszsi zK(7Y|JlE2{eyyHsoH+_*v-X6yT{|A9@@Z_VxXbySJWFg1mI*pu4V|xDio)CRTvx`> zEf^^HwBkB9o;0i^DU~4mKeWZ?$5L;cmnv+QYHGaSodjGccfGH!)(5g#@B1Llto+}q zcJgJp=D}7~UjCZOwdt1PB_AWU9FuY{T$Ai`GE@de?&u*L18bmR67TYq{U) zKX%_zi&);RhWm-R1>+Zg)(J`B9OH6>36TthXA{mtO}c!JEIqe|zql- z+RhG9l52csO3S$OrfOb|6~b;sNeJl!CrVQ|bgRw{WqO$v8(>~s zT5a-IGMTuKRRSl9@ynlIWe4A`L!G@S)MiRIBMzUSiX`SNo``CZkr&w|pry^?mQ(>k z#QN=YVj8AR(DkLH#1#C{{rXH>iQk-_e}^91k(kX1n1LDILyI=~!ZE_v;l*7)V;DfY zN>}uGxvjMd(MGKCjbT%IrTL^%sJi3)NuR-;D{Xt@MH7HL3;mVEO$#c;#H~r~#0pKJ zkX?=YlBqHLfc0Q!F6NHAZ{GM9owr)$A6lIC3{>LY&RZdY0MhL!=*yQqK#4()yj>Rj zgKm++i6C#sS-Ja0yakCjKd?!oh>Ez8j6Y|r2wC3hld$s}O{yh51s@)--92{28|j-> zzOXi<59bx~08yArG@r1$2gAS6H*T!gfV(_jlN>F}kkd9(eOBeWDb2O3wrcUGIKP~+ zVvq+0(T9#~Z@X`)47fPw=dZ1hEw^e5-SxmDz()2mOS|VYj4OUozXcS}6G9U4Ih$>3 znvcC;e(fb$*<~tA6Kt|g5s~#~FL1aLRhj-9Z{dW!qIWV6C&;=yB&kmp!PnOvuIMc5_18mnm- z&wG6NOg?9#{gw(E+zyYJmDW23i{?5RA6GZ<4zhlkM#TS2!ZUx%tXv9ZH zx{FewP#*xCMsIIVJM!~$IVS)WqDl+?3~bHLj=5ShAh>|tHU>rR@)!-acRsN!%nx8q zoHr*UYwgDsu#ycLE9gJdrsU5?!>`m4EeX@*G?dnz0+8h9qS_!QVe)Vor-Bz5j)Bf= zDvYl0{`(etBh}KcDCB7;_sMF={qL51Y<&D|k(bVD{YXCZ)copvYDrP7ARH~iBIf1p-$Lr=J?UtY$)}RE`1E&)TbU`oR`~Y@Z%Y)3+O^km;lM~t zjQm+<`iTwyC2MVSH7c)$w1bWZ(pay%I&>p-ck1-gb9&pWFA_uKNu_E5p2brk!nhj! zdRLcg=>mFvPJxhatQK`g!innEvCi+`hpA)?prRh(sHar1L?ki+Zw808KZs`kH9J8$ zWHO=Jv`2o#EBCH<^-7_FuNTO?ccs-NvAk_MRHayy(HLZ!B7<4WLDpLR0Y>t$wvd^j zEK1`*3W?}Xk8FO^vhro3YtyUmgRBY3N7IT`kaMN-JRtNhPDgxNe1-7I zE7OxG`zne}5DX!=9w%X8KxzQiS z{~Cflq<0M~x_tUuR*pEaiYphObXHnrDz(SA+B^oS1=|S+9-a5OwJjoKD$k z)|W3iPJW=PEl{5ymZ1!g9JRLxFV=md^y|R>ewoP_;tf4eAhPma)zq$jnhF`)lo_c9cM&O%$;Gs<)tNP0yG|Lans%EI-SBpD7lF^HKM+u;tV?fmpq~0+U z2RQHB_G8#e|KzYFNF{mvzg1EX32_qI3(ZA=-m0&}(>=O-b9YUjh!6KI(~_pevKgq5 z$9--8P{fRamHkP<)c0HpNZ*RtpkzKrJ4;*Dk@EL*DyTh#a`b6!uP+*MDrz?#`HwvS zkaboPd3FOyVSw7&2&Ow|5zdvnlqu^fJ-A_9{sC2~6r|Fuu8QuN8RrIbAvO_HvaBH`nqf0XNO zhJ%gHKNKZ7lKpY`vjqRqf#jbKjC9-e-~&t-iTLi79(+^oNgxJjshQwVCjIVj{z;lW ziEjm=pco$%g8;#yeIht*>@I$B#-o3v01U)PZwv!>g&go$r7>h}g%$3bDL?M`nEnm8 zh?X;@s$>ad8^oT)tUD^fLB8%E9Msg((o$88A+>cwoo;_bH8?V2eB$`wGCP|NFC#gb z%mhMdD~H+j6e6J5Sb6W Qhe1(O(pLQb)H>|H0MbU Date: Sat, 6 Nov 2021 15:13:44 +0800 Subject: [PATCH 649/756] Add ImportContactCommand sequence diagram --- docs/diagrams/ImportContactCommand.puml | 29 ++++++++++++++++++ .../ImportContactCommandSequenceDiagram.png | Bin 0 -> 17445 bytes 2 files changed, 29 insertions(+) create mode 100644 docs/diagrams/ImportContactCommand.puml create mode 100644 docs/images/ImportContactCommandSequenceDiagram.png diff --git a/docs/diagrams/ImportContactCommand.puml b/docs/diagrams/ImportContactCommand.puml new file mode 100644 index 0000000000..d6110e02ab --- /dev/null +++ b/docs/diagrams/ImportContactCommand.puml @@ -0,0 +1,29 @@ +@startuml +hide footbox +-> ":ImportContactCommand": execute() +activate ":ImportContactCommand" + +alt#gold #lightgreen foundImportFile() + ":ImportContactCommand" -> ":ImportContactCommand" : importContacts() + activate ":ImportContactCommand" + ":ImportContactCommand" --> ":ImportContactCommand" + deactivate ":ImportContactCommand" + + ":ImportContactCommand" -> ":ImportContactCommand" : appendImportedContacts() + activate ":ImportContactCommand" + ":ImportContactCommand" --> ":ImportContactCommand" + deactivate ":ImportContactCommand" + + ":ImportContactCommand" -> ":TextUi" : successfulImportMessage() + activate ":TextUi" + ":TextUi" --> ":ImportContactCommand" + deactivate ":TextUi" + +else #lightblue else + ":ImportContactCommand" -> ":ExceptionTextUi" : missingImportFileMessage() + activate ":ExceptionTextUi" + ":ExceptionTextUi" --> ":ImportContactCommand" + deactivate ":ExceptionTextUi" + +end +@enduml \ No newline at end of file diff --git a/docs/images/ImportContactCommandSequenceDiagram.png b/docs/images/ImportContactCommandSequenceDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..589476928b30dfa6cb60c47d111952dfb5228aa1 GIT binary patch literal 17445 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 OfJB9*gbD<-J^vTzNC^`F literal 0 HcmV?d00001 From b3fae31fca9c6033780797c2f6ffa69e51ec7374 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sat, 6 Nov 2021 15:15:54 +0800 Subject: [PATCH 650/756] Change method name in contacts decoder --- src/main/java/seedu/storage/ContactsDecoder.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index b1b5f7cd14..cfcceb7ddd 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -109,11 +109,11 @@ private void decodeContact(ContactList contactList, String contactText, int line ExceptionTextUi.invalidFlagMessage(); } catch (InvalidGithubUsernameException | InvalidNameException | InvalidTelegramUsernameException | InvalidLinkedinUsernameException | InvalidTwitterUsernameException | InvalidEmailException e) { - handleInvalidNames(e, lineIndex, contactFilePath); + handleInvalidDetails(e, lineIndex, contactFilePath); } } - private void handleInvalidNames(Exception e, int lineIndex, String contactFilePath) { + private void handleInvalidDetails(Exception e, int lineIndex, String contactFilePath) { ExceptionTextUi.invalidLoadedLineMessage(lineIndex, contactFilePath); if (e instanceof InvalidNameException) { ExceptionTextUi.invalidNameInput(); From 4bb17d23d00f9e897ba0be5aa380dc5ee8a1b07d Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sat, 6 Nov 2021 15:16:04 +0800 Subject: [PATCH 651/756] Add ImportContactsCommand into DG --- docs/DeveloperGuide.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 54597761f2..b3c54177c7 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -224,6 +224,25 @@ function in `TextUi` class. ![List Sequence Diagram](images/ListContactsCommandSequenceDiagram.png) +### Importing contacts: `import` +This feature is processed using the `ImportContactCommand`. This feature allows a user to import contacts over from +a text file containing comma-separated values (CSV). + +As inputs may be corrupted (having less fields than required), or may not adhere to the detail formats of each field +(such as having illegal characters in the Github username), a `ContactsDecoder` is used to read and ensure the data +integrity of imported contacts. To achieve this, the `ContactsDecoder` class inherits the `RegexParser` abstract +class, as depicted below. + +![ContactsDecoder Class Diagram](images/ContactsDecoderClassDiagram.png) + +With this implementation in place, the `ImportContactCommand` will firstly check if there exists a file `import.txt` +stored in the `data/` directory (ie. stored in `data/import.txt`). Should the `import.txt` file exist, it will then +attempt to import the contacts to a temporary `ContactList`, before adding them to the user's `ContactList`. The +sequence diagram below illustrates the process of executing `ImportContactCommand`. + +![Import Sequence Diagram](images/ImportContactCommandSequenceDiagram.png) + +Throughout the process of importing contacts, the alphabetical ordering of contacts is preserved. ## Product scope ### Target user profile From 4581dd3cc0428e3a3b824f592bdcdaba25db8af3 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Sat, 6 Nov 2021 15:57:21 +0800 Subject: [PATCH 652/756] Update Search Contact Command UML --- docs/diagrams/SearchContactCommand.puml | 91 ++++++------------------- 1 file changed, 20 insertions(+), 71 deletions(-) diff --git a/docs/diagrams/SearchContactCommand.puml b/docs/diagrams/SearchContactCommand.puml index 6074dd6e48..8765cc6b25 100644 --- a/docs/diagrams/SearchContactCommand.puml +++ b/docs/diagrams/SearchContactCommand.puml @@ -2,88 +2,37 @@ hide footbox 'https://plantuml.com/sequence-diagram --> ":MainParser": execute() -activate ":MainParser" - -":MainParser" -> ":MainParser" :getCommandWord(userInput:String) -activate ":MainParser" -":MainParser" -> ":SearchContactParser" :parseSearchQuery(userInput:String) -activate ":SearchContactParser" - -":SearchContactParser" -> ":SearchContactParser" :parseSearchQuery(userInput:String) -activate ":SearchContactParser" -":SearchContactParser" --> ":SearchContactParser" :searchInput:String -deactivate ":SearchContactParser" - -":SearchContactParser" -> ":SearchContactParser" :getDetailFlag(searchInput:String)) -activate ":SearchContactParser" -":SearchContactParser" --> ":SearchContactParser" :detailFlag:int -deactivate ":SearchContactParser" - -":SearchContactParser" -> ":SearchContactParser" :parseSearchQuery(searchInput:String) -activate ":SearchContactParser" -":SearchContactParser" --> ":SearchContactParser" :query:String -deactivate ":SearchContactParser" - - -":SearchContactParser" --> ":MainParser" : SearchContactCommand(query:String, detailFlag:int) -deactivate ":SearchContactParser" - -":MainParser" -> ":SearchContactCommand" : SearchContactCommand:Command +-> ":SearchContactCommand": execute() activate ":SearchContactCommand" + ":SearchContactCommand" -> ":ContactList" : searchContact(query:String, detailFlag:int) activate ":ContactList" loop for all contacts -":ContactList" -> ":ContactList" :getDetailFlag(userInput:String) -loop#gold #lightgreen for all contacts - alt contact.getName().contains(query) - ":ContactList" -> ":TextUI" : viewContactMessage(contact, i) - activate ":TextUI" - deactivate ":TextUI" - end - - else GITHUB_INDEX - alt contact.getGithub().contains(query) - ":ContactList" -> ":TextUI" : viewContactMessage(contact, i) - activate ":TextUI" - deactivate ":TextUI" - end - - else LINKEDIN_INDEX - alt contact.getLinkedIn().contains(query) - ":ContactList" -> ":TextUI" : viewContactMessage(contact, i) - activate ":TextUI" - deactivate ":TextUI" + loop #lightgrey for all contacts + ":ContactList" -> ":ContactList" :getContactAtIndex(i:int) + activate ":ContactList" + ":ContactList" --> ":ContactList" :contact:Contact + deactivate ":ContactList" + + opt#gold #lightgreen hasDetailMatches(query, detailType, i, contact) + ":ContactList" -> ":TextUI" :viewContactMessage(contact:Contact, Index:int) + activate ":TextUI" + ":TextUI" --> ":ContactList" + deactivate ":TextUI" + ":ContactList" -> ":ContactList" : matches++ end +end - else TELEGRAM_INDEX - alt contact.getTelegram().contains(query) - ":ContactList" -> ":TextUI" : viewContactMessage(contact, i) - activate ":TextUI" - deactivate ":TextUI" - end - else TWITTER_INDEX - alt contact.getTwitter().contains(query) - ":ContactList" -> ":TextUI" : viewContactMessage(contact, i) - activate ":TextUI" - deactivate ":TextUI" - end - else EMAIL_INDEX - alt contact.getEmail().contains(query) - ":ContactList" -> ":TextUI" : viewContactMessage(contact, i) - activate ":TextUI" - deactivate ":TextUI" - end end +opt#gold #lightgreen matches == 0 +":ContactList"->":TextUI":searchNoResultsFoundMessage() +activate ":TextUI" +":TextUI" --> ":ContactList" +deactivate ":TextUI" end ":ContactList"-->":SearchContactCommand" -deactivate ":ContactList" - -":SearchContactCommand"-->":MainParser" deactivate ":SearchContactCommand" -deactivate ":MainParser" - @enduml \ No newline at end of file From b391877ed4b056a96b566b980c72432451d4e615 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Sat, 6 Nov 2021 16:15:19 +0800 Subject: [PATCH 653/756] Update Edit Contact Command to abstract sequence diagrams --- docs/diagrams/EditContactCommand.puml | 59 +++++---------------------- 1 file changed, 11 insertions(+), 48 deletions(-) diff --git a/docs/diagrams/EditContactCommand.puml b/docs/diagrams/EditContactCommand.puml index 8d83db2392..398a13db1f 100644 --- a/docs/diagrams/EditContactCommand.puml +++ b/docs/diagrams/EditContactCommand.puml @@ -2,58 +2,21 @@ hide footbox 'https://plantuml.com/sequence-diagram --> ":MainParser": execute() -activate ":MainParser" - - -":MainParser" -> ":MainParser":getCommandWord(userInput:String) -activate ":MainParser" -":MainParser" -> ":EditContactParser" :EditContactParser(userInput:String) -activate ":EditContactParser" - - -":EditContactParser" -> ":EditContactParser" :parseContactDetails(userInput:String) -activate ":EditContactParser" -":EditContactParser" --> ":EditContactParser" :details:String[] -deactivate ":EditContactParser" - - -":EditContactParser" -> ":IndexParser" :getIndexFromInput(userInput:String) -activate ":IndexParser" -":IndexParser" --> ":EditContactParser" :userIndex:int -deactivate ":IndexParser" - -":EditContactParser" --> ":MainParser" : EditContactCommand(details, userIndex):Command -deactivate ":EditContactParser" - -":MainParser" -> ":EditContactCommand" : EditContactCommand:Command - +-> ":EditContactCommand": execute() activate ":EditContactCommand" -":EditContactCommand" -> ":ContactList" : editContact(contactDetails:String[], contactIndex:int) -activate ":ContactList" +alt#gold #lightgreen PERSONAL_CONTACT_INDEX + ref over ":EditContactCommand", ":EditContactCommand" :edit personal contact -loop until all contactDetails have been updated -alt#gold #lightgreen NAME_INDEX - ":ContactList" -> ":ContactList" : setName(contactDetails(i)) - else GITHUB_INDEX - ":ContactList" -> ":ContactList" : setGithub(contactDetails(i)) - else LINKEDIN_INDEX - ":ContactList" -> ":ContactList" : setLinkedin(contactDetails(i)) - else TELEGRAM_INDEX - ":ContactList" -> ":ContactList" : setTelegram(contactDetails(i)) - else TWITTER_INDEX - ":ContactList" -> ":ContactList" : setTwitter(contactDetails(i)) - else EMAIL_INDEX - ":ContactList" -> ":ContactList" : setEmail(contactDetails(i)) -end -end +else #lightblue ALL_CONTACTS_INDEX + ":EditContactCommand" -> ":ExceptionTextUi":numOutOfRangeEditMessage(contactListSize:int) + activate ":ExceptionTextUi" + ":ExceptionTextUi" --> ":EditContactCommand": + deactivate ":ExceptionTextUi" -":ContactList"-->":EditContactCommand" -deactivate ":ContactList" +else #gold CONTACT_INDEX + ref over ":EditContactCommand", ":EditContactCommand" :edit contact +end -":EditContactCommand"-->":MainParser" -deactivate ":EditContactCommand" -deactivate ":MainParser" @enduml \ No newline at end of file From ad40beba37a743272b94126dc4a1fcc0921a9783 Mon Sep 17 00:00:00 2001 From: lezong Date: Sat, 6 Nov 2021 16:25:55 +0800 Subject: [PATCH 654/756] Add Index Parser into implementation as well as links --- docs/DeveloperGuide.md | 24 +++++++++++++++++------- docs/diagrams/StorageClassDiagram.puml | 4 +--- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 54597761f2..067f02ddd9 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -101,7 +101,6 @@ the contacts in the `ContactList`, such as adding or editing contacts. The conta according to their names in alphabetical order. ### Storage -**API** :`Storage.java` ![Storage Class Diagram](images/StorageClassDiagram.png) @@ -158,7 +157,7 @@ executed in `ConTech`. The sequence diagram below illustrates the process of exe ### Viewing a contact: `view` This feature is processed using `ViewContactCommand`. Whenever a user wants to view a specific contact from the -contact list, user can input `view INDEX` with the index of the desired contact displayed from the `list` feature. +contact list, user can input `view INDEX` with the index of the desired contact displayed from the [`list`](#List) feature. `ViewContactCommand` is then created in the `MainParser` and executed in `ConTech`. The sequence diagram below illustrates the `execute()` function in `ViewContactCommand`. @@ -169,8 +168,10 @@ The sequence diagram below illustrates the `execute()` function in `ViewContactC This feature is processed using `EditContactParser` under `MainParser`. In order to edit a contact in the contact list, a user must enter a command in the form `edit {-n } {-g } {-l } {-te } {-tw } {-e }`. The user input will be parsed by `EditContactParser` methods `getIndexToStore` and -`parseContactDetails` to obtain a String array with the details to be edited. An `EditContactCommand` -with the specified parameters will then be created and executed in `ConTech`. The sequence diagram below +`parseContactDetails` to obtain a String array with the details to be edited. The user input will also be parsed +by the [`IndexParser`](#IndexParser) to obtain the contact index, which identifies the contact in the contact list to be edited. + +An `EditContactCommand` with the specified parameters will then be created and executed in `ConTech`. The sequence diagram below shows how the whole process is carried out. ![Edit Sequence Diagram](images/EditContactCommandSequenceDiagram.png) @@ -183,7 +184,7 @@ or delete all contacts at once. ![Delete Sequence Diagram](images/DeleteContactCommandSequenceDiagram.png) -To delete all contacts, a user must enter the command `rm all`. The sequence diagram below +To _delete all contacts_, a user must enter the command `rm all`. The sequence diagram below shows how the removal of all contacts works. Before any deletion, the user will be prompted with a message to confirm deletion. If the user confirms deletion for all contacts, deletion will be executed, along with a message to show that deletion has been executed. @@ -191,7 +192,7 @@ If user cancels deletion, a message is printed to show that the deletion has bee ![Delete All Sequence Diagram](images/DeleteAllContacts.png) -To delete a selected contact, a user must enter a command in the form `rm `. The sequence diagram below +To _delete a selected contact_, a user must enter a command in the form `rm `. The sequence diagram below shows how the removal of a contact works. Before any deletion, details of the contact with the specified`INDEX` will be displayed to the user, along with a prompt to confirm deletion. If the user confirms deletion, deletion of the selected contact will be executed, along with a message to show that deletion has been executed. @@ -199,7 +200,7 @@ If user cancels deletion, a message is printed to show that the deletion has bee ![Delete Selected Sequence Diagram](images/DeleteSelectedContact.png) -To delete specific details of a selected contact, a user must enter a command in the form `rm {-g} {-l} {-te} +To _delete specific details_ of a selected contact, a user must enter a command in the form `rm {-g} {-l} {-te} {-tw} {-e}`. The sequence diagram below shows how the removal of a contact's fields works. Before any deletion, details of the contact fields specified will be displayed to the user, along with a prompt to confirm deletion. If the user confirms deletion, deletion of the selected contact will be executed, along with a message to show @@ -224,6 +225,15 @@ function in `TextUi` class. ![List Sequence Diagram](images/ListContactsCommandSequenceDiagram.png) +### Index Parser + +The Index Parser is used when the user enters a command that specifies a contact index, such as the [`rm`](#Delete), +[`view`](#View) or [`edit`](#Edit) command. The Index Parser will parse the user's input string, and return the +specified contact index given as an integer, which will then be used in the execution of the corresponding command. + +For example, if `edit 2 -n Marcus Bobo` is given as the input, the Index Parser will identify the contact index to be `2` +and pass the contact index to the execution of the `edit` command accordingly. + ## Product scope ### Target user profile diff --git a/docs/diagrams/StorageClassDiagram.puml b/docs/diagrams/StorageClassDiagram.puml index 70bcc5975f..8a83e01fe8 100644 --- a/docs/diagrams/StorageClassDiagram.puml +++ b/docs/diagrams/StorageClassDiagram.puml @@ -1,4 +1,5 @@ @startuml +hide circle skinparam classAttributeIconSize 0 'https://plantuml.com/class-diagram @@ -15,9 +16,6 @@ Storage .right.> ContactsEncoder 'Storage -up->"personalContactFile 0..1"File ContactsEncoder ..> Storage -'class File { -'} - class Storage { -File contactFile -File personalContactFile From cb43817822fc27145ebea88234aff4dab0a26414 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Sat, 6 Nov 2021 17:10:28 +0800 Subject: [PATCH 655/756] Update detailed EditContactCommand for contacts with valid index --- docs/diagrams/EditContactCommandDetailed.puml | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 docs/diagrams/EditContactCommandDetailed.puml diff --git a/docs/diagrams/EditContactCommandDetailed.puml b/docs/diagrams/EditContactCommandDetailed.puml new file mode 100644 index 0000000000..3b29b2bf26 --- /dev/null +++ b/docs/diagrams/EditContactCommandDetailed.puml @@ -0,0 +1,46 @@ +@startuml +hide footbox +'https://plantuml.com/sequence-diagram +mainframe sd Edit Personal Contact Parsing +activate ":EditContactCommand" + +create "editedContact:Contact" +":EditContactCommand" -> "editedContact:Contact":duplicateContact() +activate "editedContact:Contact" + +loop until all details are updated +"editedContact:Contact" -> "editedContact:Contact" : setDetail(contactDetails[i]:String, i:int) +activate "editedContact:Contact" +"editedContact:Contact" --> "editedContact:Contact" +deactivate "editedContact:Contact" + +end + +"editedContact:Contact" --> ":EditContactCommand" : editedContact:Contact +deactivate "editedContact:Contact" + +alt#gold #lightgreen hasDuplicates(editedContact:Contact, contactList:ContactList, contactIndex:int) + ":EditContactCommand" -> ":TextUi":ignoreContact(type:String) + activate ":TextUi" + ":TextUi" --> ":EditContactCommand" + deactivate ":TextUi" + +else #lightblue else + ":EditContactCommand" -> ":EditContactCommand":updateContact(postEditContact:Contact) + activate ":EditContactCommand" + ":EditContactCommand" -> ":ContactList":editContactAtIndex(contactDetails:String[], contactIndex:int) + activate ":ContactList" + ":ContactList" --> ":EditContactCommand" + deactivate ":ContactList" + + ":EditContactCommand" -> ":TextUi":editContactMessage(editedContact:Contact) + activate ":TextUi" + ":TextUi" --> ":EditContactCommand" + deactivate ":TextUi" + ":EditContactCommand" --> ":EditContactCommand" + deactivate ":EditContactCommand" + + +end +deactivate ":EditContactCommand" +@enduml \ No newline at end of file From 11a5d48f5672d6b5162962263a68d89725f9e498 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Sat, 6 Nov 2021 17:13:04 +0800 Subject: [PATCH 656/756] Unabstract Personal Contact Edit Command --- docs/diagrams/EditContactCommand.puml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/diagrams/EditContactCommand.puml b/docs/diagrams/EditContactCommand.puml index 398a13db1f..db09c214b6 100644 --- a/docs/diagrams/EditContactCommand.puml +++ b/docs/diagrams/EditContactCommand.puml @@ -6,7 +6,19 @@ hide footbox activate ":EditContactCommand" alt#gold #lightgreen PERSONAL_CONTACT_INDEX - ref over ":EditContactCommand", ":EditContactCommand" :edit personal contact + ":EditContactCommand" -> ":EditContactCommand":updatePersonalContact() + activate ":EditContactCommand" + ":EditContactCommand" -> ":personalContact":editContact(contactDetails:String[]) + activate ":personalContact" + ":personalContact" --> ":EditContactCommand": + deactivate ":personalContact" + ":EditContactCommand" -> ":TextUi":editPersonalContactMessage(personalContact:Contact) + activate ":TextUi" + ":TextUi" --> ":EditContactCommand": + deactivate ":TextUi" + ":EditContactCommand" --> ":EditContactCommand": + deactivate ":EditContactCommand" + else #lightblue ALL_CONTACTS_INDEX ":EditContactCommand" -> ":ExceptionTextUi":numOutOfRangeEditMessage(contactListSize:int) From 7bab42a1f77394f06582490a25a5ffd7dd21fd9d Mon Sep 17 00:00:00 2001 From: lezong Date: Sat, 6 Nov 2021 17:23:18 +0800 Subject: [PATCH 657/756] Standardise view, edit and rm description --- docs/DeveloperGuide.md | 37 +++++++++++++-------- src/main/java/seedu/parser/IndexParser.java | 16 ++++----- 2 files changed, 32 insertions(+), 21 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 7f367ced1c..32f3458dab 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -19,6 +19,7 @@ - [Searching a contact](#Search) - [Listing all contacts](#List) - [Importing contacts](#Import) + - [Contact index parser](#IndexParser) - [Product Scope](#scope) - [Target user profile](#target) - [Value proposition](#value) @@ -157,9 +158,11 @@ executed in `ConTech`. The sequence diagram below illustrates the process of exe ### Viewing a contact: `view` This feature is processed using `ViewContactCommand`. Whenever a user wants to view a specific contact from the -contact list, user can input `view INDEX` with the index of the desired contact displayed from the [`list`](#List) feature. -`ViewContactCommand` is then created in the `MainParser` and executed in `ConTech`. +contact list, a user must input a command in the form `view `, with `INDEX` being the index of the desired +contact that is displayed using [`ls`](#List). The user input is parsed by the [`IndexParser`](#IndexParser) +to obtain the contact index, which identifies the contact in the contact list to be viewed. +A `ViewContactCommand` with the specified parameters will then be created in the `MainParser` and executed in `ConTech`. The sequence diagram below illustrates the `execute()` function in `ViewContactCommand`. ![View Sequence Diagram](images/ViewContactCommandSequenceDiagram.png) @@ -178,30 +181,38 @@ shows how the whole process is carried out. ### Deleting contacts: `rm` -This feature is processed using the `DeleteContactCommand`. `DeleteContactCommand` is created -in the `MainParser`and executed in`ConTech`. Users can either delete a specified contact -or delete all contacts at once. +This feature is processed using the `DeleteContactCommand`. Users can delete a specified contact, delete all contacts at +once or delete specific details of a selected contact. In order to determine which contact or which +contact's fields to delete, the user input is parsed using the [`IndexParser`](#IndexParser) to obtain the contact +index for executing the command. The user input is also parsed using `DeleteContactParser` to obtain the specific fields +to be deleted, if any. + +A `DeleteContactCommand` with the specified parameters will then be created in the `MainParser`and executed in`ConTech`. ![Delete Sequence Diagram](images/DeleteContactCommandSequenceDiagram.png) -To _delete all contacts_, a user must enter the command `rm all`. The sequence diagram below -shows how the removal of all contacts works. Before any deletion, the user will be +To _delete all contacts_, a user must enter the command `rm all`. + +The sequence diagram below shows how the removal of all contacts works. Before any deletion, the user will be prompted with a message to confirm deletion. If the user confirms deletion for all contacts, deletion will be executed, along with a message to show that deletion has been executed. If user cancels deletion, a message is printed to show that the deletion has been cancelled. ![Delete All Sequence Diagram](images/DeleteAllContacts.png) -To _delete a selected contact_, a user must enter a command in the form `rm `. The sequence diagram below -shows how the removal of a contact works. Before any deletion, details of the contact with the specified`INDEX` -will be displayed to the user, along with a prompt to confirm deletion. If the user confirms deletion, -deletion of the selected contact will be executed, along with a message to show that deletion has been executed. -If user cancels deletion, a message is printed to show that the deletion has been cancelled. +To _delete a selected contact_, a user must enter a command in the form `rm `. + +The sequence diagram below shows how the removal of the selected contact works. Before any deletion, details of the +contact with the specified`INDEX` will be displayed to the user, along with a prompt to confirm deletion. If the user +confirms deletion, deletion of the selected contact will be executed, along with a message to show that deletion has +been executed. If user cancels deletion, a message is printed to show that the deletion has been cancelled. ![Delete Selected Sequence Diagram](images/DeleteSelectedContact.png) To _delete specific details_ of a selected contact, a user must enter a command in the form `rm {-g} {-l} {-te} -{-tw} {-e}`. The sequence diagram below shows how the removal of a contact's fields works. Before any +{-tw} {-e}`. + +The sequence diagram below shows how the removal of a contact's fields works. Before any deletion, details of the contact fields specified will be displayed to the user, along with a prompt to confirm deletion. If the user confirms deletion, deletion of the selected contact will be executed, along with a message to show that deletion has been executed. If user cancels, deletion, a message is printed to show that the deletion has been diff --git a/src/main/java/seedu/parser/IndexParser.java b/src/main/java/seedu/parser/IndexParser.java index b7f523579d..d3cfb4009d 100644 --- a/src/main/java/seedu/parser/IndexParser.java +++ b/src/main/java/seedu/parser/IndexParser.java @@ -9,10 +9,10 @@ public class IndexParser { private static final int INDEX_POSITION = 1; private static final int SIGNIFICANT_INDEX_POSITION = 0; private static final int COMD_INDEX_LENGTH = 2; - private static final String PERSONAL_CONTACT_INDEX = "me"; - private static final int PERSONAL_CONTACT_ID = -1; - private static final String REMOVE_ALL_INDEX = "all"; - private static final int REMOVE_ALL_ID = -2; + private static final String PERSONAL_CONTACT_ID = "me"; + private static final int PERSONAL_CONTACT_INDEX = -1; + private static final String REMOVE_ALL_ID = "all"; + private static final int REMOVE_ALL_INDEX = -2; private static final String numbers = "^-?\\d+$"; public static int getIndexFromInput(String userInput) @@ -29,11 +29,11 @@ public static int getIndexFromInput(String userInput) // 1 is the significant index that is important and chosen as the index for command // index can be "me" or "all" or an integer String significantIndex = indexSplit[SIGNIFICANT_INDEX_POSITION].trim(); - if (significantIndex.equalsIgnoreCase(PERSONAL_CONTACT_INDEX)) { - return PERSONAL_CONTACT_ID; + if (significantIndex.equalsIgnoreCase(PERSONAL_CONTACT_ID)) { + return PERSONAL_CONTACT_INDEX; } - if (significantIndex.equalsIgnoreCase(REMOVE_ALL_INDEX)) { - return REMOVE_ALL_ID; + if (significantIndex.equalsIgnoreCase(REMOVE_ALL_ID)) { + return REMOVE_ALL_INDEX; } if (!significantIndex.matches(numbers)) { throw new NumberFormatException(); From e2573bcf0f8bc91c21adac247007e71d8effb65d Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Sat, 6 Nov 2021 17:35:52 +0800 Subject: [PATCH 658/756] Add Edit Contact Parser detailed diagram --- docs/diagrams/EditContactParser.puml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 docs/diagrams/EditContactParser.puml diff --git a/docs/diagrams/EditContactParser.puml b/docs/diagrams/EditContactParser.puml new file mode 100644 index 0000000000..77ffb81577 --- /dev/null +++ b/docs/diagrams/EditContactParser.puml @@ -0,0 +1,28 @@ +@startuml +hide footbox +'https://plantuml.com/sequence-diagram +mainframe sd Detailed Edit Contact Parsing +->":EditContactParser":parseContactDetails(userInput:String) +activate ":EditContactParser" + +":EditContactParser"->":EditContactParser":userInput.split(\n\tSPACE:String, \n\tNUMBER_OF_EDIT_ARGS:int\n) +activate ":EditContactParser" +":EditContactParser"-->":EditContactParser":inputDetails:String[] +deactivate ":EditContactParser" + +":EditContactParser"->":EditContactParser":inputDetails.split(DETAIL_SEPARATOR:String) +activate ":EditContactParser" +":EditContactParser"-->":EditContactParser":destructuredInputs:String[] +deactivate ":EditContactParser" + + +loop until all fields are parsed +":EditContactParser"->":EditContactParser":parseDetail(\n\tcontactDetails:String[],\n\tdestructuredInputs:String[]\n) +activate ":EditContactParser" +":EditContactParser"-->":EditContactParser" +deactivate ":EditContactParser" +end + +<--":EditContactParser":contactDetails:String[] +deactivate ":EditContactParser" +@enduml \ No newline at end of file From 1e864a78fd552a02325181884cbc7f77bef4b550 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Sat, 6 Nov 2021 18:05:20 +0800 Subject: [PATCH 659/756] Update sequence diagrams for Edit function --- ...tContactCommandDetailedSequenceDiagram.png | Bin 0 -> 33694 bytes .../EditContactCommandSequenceDiagram.png | Bin 56988 -> 24650 bytes .../EditContactParserSequenceDiagram.png | Bin 0 -> 25432 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/images/EditContactCommandDetailedSequenceDiagram.png create mode 100644 docs/images/EditContactParserSequenceDiagram.png diff --git a/docs/images/EditContactCommandDetailedSequenceDiagram.png b/docs/images/EditContactCommandDetailedSequenceDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..d4e4e853eb0d4972e610b506796642831317baac GIT binary patch literal 33694 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 c#c}3-oiaWq3t|IPdV0fSB8vj6}9 literal 0 HcmV?d00001 diff --git a/docs/images/EditContactCommandSequenceDiagram.png b/docs/images/EditContactCommandSequenceDiagram.png index e57c400d84dee026e1701385318705f30da208a5..194ea3f8a03026f704f36b721009c277759d0b11 100644 GIT binary patch literal 24650 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 literal 0 HcmV?d00001 From 0b9e5c05d25443c7025a81284fd3049e6ca0c55c Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Sat, 6 Nov 2021 18:05:37 +0800 Subject: [PATCH 660/756] Update DG for edit command --- docs/DeveloperGuide.md | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 54597761f2..d2f1621ce4 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -166,15 +166,32 @@ The sequence diagram below illustrates the `execute()` function in `ViewContactC ![View Sequence Diagram](images/ViewContactCommandSequenceDiagram.png) ### Editing a contact: `edit` -This feature is processed using `EditContactParser` under `MainParser`. In order to edit a contact in the contact list, -a user must enter a command in the form `edit {-n } {-g } {-l } {-te } -{-tw } {-e }`. The user input will be parsed by `EditContactParser` methods `getIndexToStore` and -`parseContactDetails` to obtain a String array with the details to be edited. An `EditContactCommand` -with the specified parameters will then be created and executed in `ConTech`. The sequence diagram below -shows how the whole process is carried out. +This feature is processed using `EditContactCommand`. This feature allows the user to edit a contact in their contact +list, by entering a command in the form `edit {-n } {-g } {-l } {-te } +{-tw } {-e }`. At least one detail must be specified by the user for the command to be valid. The user +can also specify `me` as an index to edit the personal contact's details. + +The user's input is parsed in `MainParser` and `EditContactParser` and the implementation is similar to that of +`AddContactParser` . + +The user input will be parsed by `EditContactParser` methods `getIndexToStore` and +`parseContactDetails` to obtain a String array with the details to be edited. The sequence diagram below +shows how the String array is obtained. + +![Edit Sequence Diagram](images/EditContactParserSequenceDiagram.png) + +Once the user's input is parsed and the index specified is obtained, an `EditContactCommand` with the specified +parameters will then be created and executed in `ConTech`. The sequence diagram below depicts the execution of +`EditContactCommand` for the index `me` as well as an invalid index `all`. ![Edit Sequence Diagram](images/EditContactCommandSequenceDiagram.png) +If a valid contact index in the contact book is specified, the details to be edited will first be checked against the +contact book for duplicates. If there are duplicates, ConTech will prompt the user for confirmation before editing the +contact. If the user accepts or there are no duplicates, the `EditContactCommand` will be executed. The sequence diagram +below depicts the execution of `EditContactCommand` for a contact in the contact list. + +![Edit Sequence Diagram](images/EditContactCommandDetailedSequenceDiagram.png) ### Deleting contacts: `rm` This feature is processed using the `DeleteContactCommand`. `DeleteContactCommand` is created From dc7d4c97141ee100c428be21e6e8d306752af881 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Sat, 6 Nov 2021 18:36:56 +0800 Subject: [PATCH 661/756] Update sequence diagrams for Search function --- .../SearchContactCommandSequenceDiagram.png | Bin 85938 -> 27691 bytes .../SearchContactParserSequenceDiagram.png | Bin 0 -> 38845 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/images/SearchContactParserSequenceDiagram.png diff --git a/docs/images/SearchContactCommandSequenceDiagram.png b/docs/images/SearchContactCommandSequenceDiagram.png index ac5a1153841c0744907c0cb268065ec1351a076b..19d4c2a8f90b49eba639cbf6cb68ee842e1bf209 100644 GIT binary patch literal 27691 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

8t~{aLUrQwTXbYHGg8ka@X2q+|CibJ6hN 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 VH;+OMcvKLGq`2Ip{0G|J{}12_TOj}d literal 0 HcmV?d00001 From b70197a05b6e561c23af105a66d29c61f87a8443 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Sat, 6 Nov 2021 18:37:16 +0800 Subject: [PATCH 662/756] Add search contact parser diagram --- docs/diagrams/SearchContactParser.puml | 37 ++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 docs/diagrams/SearchContactParser.puml diff --git a/docs/diagrams/SearchContactParser.puml b/docs/diagrams/SearchContactParser.puml new file mode 100644 index 0000000000..c47e2a7c5b --- /dev/null +++ b/docs/diagrams/SearchContactParser.puml @@ -0,0 +1,37 @@ +@startuml +hide footbox +'https://plantuml.com/sequence-diagram +mainframe sd Detailed Search Query Parsing +->":SearchContactParser":parseSearchQuery(searchInput:String) +activate ":SearchContactParser" +":SearchContactParser"->":SearchContactParser": searchInput.split(\n\tSPACE:String, \n\tNUMBER_OF_DETAILS:int\n) +activate ":SearchContactParser" +":SearchContactParser"-->":SearchContactParser": destructuredInputs:String[] +deactivate ":SearchContactParser" + +opt#gold #lightgreen searchInput begins with '-' +<--":SearchContactParser":destructuredInputs[NUMBER_OF_DETAILS - 1]:String +end + +<--":SearchContactParser":searchInput:String +deactivate ":SearchContactParser" + +->":SearchContactParser":getDetailFlag(searchInput:String) +activate ":SearchContactParser" +opt#gold #lightgreen searchInput begins with '-' +":SearchContactParser"->":SearchContactParser": searchInput.split(\n\tSPACE:String, \n\tNUMBER_OF_DETAILS:int\n) +activate ":SearchContactParser" +":SearchContactParser"-->":SearchContactParser": destructuredInputs:String[] +deactivate ":SearchContactParser" + +":SearchContactParser"->":ContactDetails": getIndexToStore(flag:String) +activate ":ContactDetails" +":ContactDetails"-->":SearchContactParser": flagIndex:int +deactivate ":ContactDetails" +<--":SearchContactParser":flagIndex:int +end + +<--":SearchContactParser":NAME_INDEX:int +deactivate ":SearchContactParser" + +@enduml \ No newline at end of file From 7ca0061b978e624ed538a05ef036e33039075207 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Sat, 6 Nov 2021 18:37:33 +0800 Subject: [PATCH 663/756] Update DG to include diagrams for search function --- docs/DeveloperGuide.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index d2f1621ce4..0c6b793e93 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -227,10 +227,16 @@ cancelled. ### Searching a contact: `search` This feature is processed using `SearchContactParser` under `MainParser`. In order to edit a contact in the contact list, -a user must enter a command in the form `search {-n | -g | -l | -te | -tw | -e} `. If no flag is specified, the search will be done -on contact names buy default. From the user input, the search query and the search flag are obtained from the -`parseSearchQuery` and the `getDetailFlag` methods respectively. A `SearchContactCommand` with the specified parameters -will be created and executed in `ConTech`. The sequence diagram below shows how the whole process is carried out. +a user must enter a command in the form `search {-n | -g | -l | -te | -tw | -e} `. If no flag is specified, +the search will be done on contact names buy default. + +From the user input, the search query and the search flag are obtained from the `parseSearchQuery` and the `getDetailFlag` +methods respectively. The sequence diagram below shows how the required parameters are obtained. + +![Search Sequence Diagram](images/SearchContactParserSequenceDiagram.png) + +A `SearchContactCommand` with the specified parameters will then be created and executed in `ConTech`. The sequence +diagram below shows how the `SearchContactCommand` is executed. ![Search Sequence Diagram](images/SearchContactCommandSequenceDiagram.png) From 708df4b5bcc0ef9e64dbbd78daab953d8aa6f492 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Sat, 6 Nov 2021 20:05:29 +0800 Subject: [PATCH 664/756] Add FAQ and coming soon for duplicate prevention for import --- docs/UserGuide.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index cd12aa0c5e..3821e2ec4d 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -422,9 +422,11 @@ marcus,null,null,null,null,null ``` - Invalid or corrupt data will not be imported into the contact list and will be discarded. Their line number in the `import.txt` will be specified for convenience in identifying problems. +- Additional input after the `import` command will be treated as erroneous input and discarded. - However, there is a limitation that duplicates will not be checked for when performing contact imports. Do import with caution. -- Additional input after the `import` command will be treated as erroneous input and discarded. +- Coming Soon: Duplicate checks for importing contacts will be added in future versions, with prompts for every contact +and option to skip all/accept all duplicates. Expected outcome of usage: @@ -541,6 +543,11 @@ corrupt data will be discarded by ConTech upon launch. Users are recommended to app instead of manually editing the save data files. For adding a large number of contacts at once, the `import` function can be used. +**Q**: Does ConTech support duplicate prevention? + +**A**: Yes, ConTech has built-in duplicate protection for all commands except `import` currently. This will be added in +a future revision with more granular controls to allow users to easily handle multiple duplicate contacts when importing. + ## Command Summary From 352f8828097333cb59bc63e2762b8f42e89e5799 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Sat, 6 Nov 2021 20:09:16 +0800 Subject: [PATCH 665/756] Update UG with implementation ideas for import duplicates --- docs/UserGuide.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 3821e2ec4d..93e4f4aba2 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -548,6 +548,13 @@ can be used. **A**: Yes, ConTech has built-in duplicate protection for all commands except `import` currently. This will be added in a future revision with more granular controls to allow users to easily handle multiple duplicate contacts when importing. +Current implementation ideas include: +- import all with/without duplicates (use flag to specify) +- manually check every single duplicate (inefficient, but can be an option with flag for users who want to check every duplicate) +- allow Windows-style duplicate handling (Ignore, Ignore all, Cancel) +- summarise every single duplicate and give user a one time confirmation to add/discard (no granularity) + + ## Command Summary From 1c0e454cdc3fdf90149ca62df189188d655928cb Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Sat, 6 Nov 2021 20:36:22 +0800 Subject: [PATCH 666/756] Add IndexParser reference in Edit section --- docs/DeveloperGuide.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 21da94f6a5..fb12eaa578 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -177,8 +177,9 @@ The user's input is parsed in `MainParser` and `EditContactParser` and the imple `AddContactParser` . The user input will be parsed by `EditContactParser` methods `getIndexToStore` and -`parseContactDetails` to obtain a String array with the details to be edited. The sequence diagram below -shows how the String array is obtained. +`parseContactDetails` to obtain a String array with the details to be edited. +The user input will also be parsed by the [`IndexParser`](#IndexParser) to obtain the contact index, which identifies the contact in the +contact list to be edited.The sequence diagram below shows how the String array is obtained. ![Edit Sequence Diagram](images/EditContactParserSequenceDiagram.png) From 4f20c1a2bdd6b4686f9295fbc094259e67c4b532 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Sat, 6 Nov 2021 22:40:06 +0800 Subject: [PATCH 667/756] Remove possible implementation ideas from FAQ and add link to DG --- docs/UserGuide.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 93e4f4aba2..202e471f6a 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -547,13 +547,7 @@ can be used. **A**: Yes, ConTech has built-in duplicate protection for all commands except `import` currently. This will be added in a future revision with more granular controls to allow users to easily handle multiple duplicate contacts when importing. - -Current implementation ideas include: -- import all with/without duplicates (use flag to specify) -- manually check every single duplicate (inefficient, but can be an option with flag for users who want to check every duplicate) -- allow Windows-style duplicate handling (Ignore, Ignore all, Cancel) -- summarise every single duplicate and give user a one time confirmation to add/discard (no granularity) - +For more information on the implementation, please refer to the [Developer Guide](https://ay2122s1-cs2113t-t09-1.github.io/tp/DeveloperGuide.html#ComingSoon). ## Command Summary From 1aa3539ab2c48dfa1f24ef098589e3c8eac5f86f Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Sat, 6 Nov 2021 22:40:17 +0800 Subject: [PATCH 668/756] Update UG for import --- docs/UserGuide.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 202e471f6a..64c3556921 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -425,8 +425,7 @@ marcus,null,null,null,null,null - Additional input after the `import` command will be treated as erroneous input and discarded. - However, there is a limitation that duplicates will not be checked for when performing contact imports. Do import with caution. -- Coming Soon: Duplicate checks for importing contacts will be added in future versions, with prompts for every contact -and option to skip all/accept all duplicates. +- Coming Soon: Duplicate checks for importing contacts will be added in future versions, with more granular controls. Expected outcome of usage: From 1970f07b817a1abdb926a5124daac212a46d30ce Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Sat, 6 Nov 2021 22:40:29 +0800 Subject: [PATCH 669/756] Add Coming Soon section with anchor link in DG --- docs/DeveloperGuide.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index fb12eaa578..6f0ce37256 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -278,6 +278,17 @@ sequence diagram below illustrates the process of executing `ImportContactComman Throughout the process of importing contacts, the alphabetical ordering of contacts is preserved. +**Coming soon:** `import` currently does not support duplicate checks. This will be implemented +in future revisions to the application. Currently, + +Current implementation ideas include: +- import all with/without duplicates (use flag to specify) +- manually check every single duplicate (inefficient, but can be an option with flag for users who want to check every duplicate) +- allow Windows-style duplicate handling (Ignore, Ignore all, Cancel) +- summarise every single duplicate and give user a one time confirmation to add/discard (no granularity) + + + ### Index Parser The Index Parser is used when the user enters a command that specifies a contact index, such as the [`rm`](#Delete), From f356bba97dbf009030e6a116d028e2e44474110d Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Sat, 6 Nov 2021 23:11:33 +0800 Subject: [PATCH 670/756] Remove icons from StorageClassDiagram --- docs/images/StorageClassDiagram.png | Bin 9816 -> 8203 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/images/StorageClassDiagram.png b/docs/images/StorageClassDiagram.png index 852aa19e5ee60b19f25c93ff2cc432a41c21e9d5..33016cf1b5ea734d1ab776a0b8ca4d99b98296be 100644 GIT binary patch literal 8203 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 literal 9816 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 Date: Sat, 6 Nov 2021 23:11:52 +0800 Subject: [PATCH 671/756] Update ViewContactCommand sequence diagram --- .../ViewContactCommandSequenceDiagram.png | Bin 12545 -> 24723 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/images/ViewContactCommandSequenceDiagram.png b/docs/images/ViewContactCommandSequenceDiagram.png index 6b8f21218fce26a8149208524ecd42443d39ef36..96e3684327c9a93c5ef3463bfac6b09f7f4bfc6b 100644 GIT binary patch literal 24723 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

KOv=xol01mXDZXg`cp^a3*XCJqbjprN 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 literal 12545 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 Date: Sat, 6 Nov 2021 23:12:28 +0800 Subject: [PATCH 672/756] Refactor view contact ui to show index --- src/main/java/seedu/ui/TextUi.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index e82d6c5d85..1c90f95b41 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -151,7 +151,7 @@ public static String formatContactFields(Contact addedContact) { public static void viewContactMessage(Contact viewingContact, int index) { String viewName = ViewMessageFormatterUi.viewNameFormatter(viewingContact); - String message = "Name: " + viewName + formatContactFields(viewingContact); + String message = index + ".\n" + "Name: " + viewName + formatContactFields(viewingContact); printDoubleLineMessage(message); } From b85f0acf62b1b6ff1a674ab946c97e0d98934c47 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Sat, 6 Nov 2021 23:12:52 +0800 Subject: [PATCH 673/756] Refactor rm contact ui for consistency --- src/main/java/seedu/ui/TextUi.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 1c90f95b41..b87d0932b0 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -189,8 +189,8 @@ public static void editPersonalContactMessage(Contact personalContact) { } public static void confirmDeleteContactMessage(Contact deletedContact, int deletedIndex) { - String message = "Delete this contact? (y/n)\n" - + deletedIndex + ". " + deletedContact.getName() + formatContactFields(deletedContact); + String message = "Delete this contact? (y/n)\n\n" + + deletedIndex + ".\n" + "Name: " + deletedContact.getName() + formatContactFields(deletedContact); printDoubleLineMessage(message); } From 3f5d55e3a1aa55b255121f3c5af9f0200d50604e Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Sat, 6 Nov 2021 23:13:24 +0800 Subject: [PATCH 674/756] Refactor missingIndexDeleteMessage for errors --- src/main/java/seedu/ui/ExceptionTextUi.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index 288d645f46..c21e530015 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -213,17 +213,17 @@ public static void missingIndexDeleteMessage(int listSize) { message = "There seems to be missing or invalid index in your request.\n" + "Please enter command in the following way:\n" + " rm {REMOVE_DETAIL_FLAGS}\n" - + "Enter as \"me\" to view personal contact"; + + "Enter as 0"; } else if (listSize == 1) { message = "There seems to be missing or invalid index in your request.\n" + "Please enter command in the following way:\n" + " rm {REMOVE_DETAIL_FLAGS}\n" - + "Enter as 0 or \"me\" (personal contact)"; + + "Enter as 0 or 1"; } else { message = "There seems to be missing or invalid index in your request.\n" + "Please enter command in the following way:\n" + " rm {REMOVE_DETAIL_FLAGS}\n" - + "Enter between 0 and " + (listSize - 1) + ", \"me\" (personal contact) or \"all\""; + + "Enter between 0 and " + (listSize - 1); } printDoubleLineMessage(message); } From a8bf9496f7e7fc46cad4b12bca4a0b29737f8fb1 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Sat, 6 Nov 2021 23:13:51 +0800 Subject: [PATCH 675/756] Refactor ViewContactCommand sequence diagram code --- .../ViewContactCommandSequenceDiagram.puml | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/docs/diagrams/ViewContactCommandSequenceDiagram.puml b/docs/diagrams/ViewContactCommandSequenceDiagram.puml index e56a8ced57..259154ad2d 100644 --- a/docs/diagrams/ViewContactCommandSequenceDiagram.puml +++ b/docs/diagrams/ViewContactCommandSequenceDiagram.puml @@ -1,18 +1,31 @@ @startuml hide footbox 'https://plantuml.com/sequence-diagram --> ":ViewContactCommand": execute() +-> ":ViewContactCommand":execute() activate ":ViewContactCommand" +alt#gold #lightgreen contactIndex:int == -1 +":ViewContactCommand" -> ":TextUi" :viewPersonalContactMessage(personalContact: Contact) +activate ":TextUi" + +":TextUi" --> ":ViewContactCommand" +deactivate ":TextUi" + +else #lightblue contactIndex:int == -2 +":ViewContactCommand" -> ":ExceptionTextUi" :missingIndexMessage() +activate ":ExceptionTextUi" -":ViewContactCommand" -> ":IndexParser" :getContactFromIndex(contactIndex:int, contactList:ContactList) -activate ":IndexParser" -":IndexParser" --> ":ViewContactCommand" :viewingContact:Contact -deactivate ":IndexParser" +":ExceptionTextUi" --> ":ViewContactCommand" +deactivate ":ExceptionTextUi" -":ViewContactCommand" -> ":TextUi":viewContactMessage(viewingContact:Contact, contactIndex:int) +else #yellow else +":ViewContactCommand" -> ":ContactList" :getContactAtIndex(contactIndex: int) +activate ":ContactList" +":ContactList" --> ":ViewContactCommand" :viewingContact: Contact +deactivate ":ContactList" +":ViewContactCommand" -> ":TextUi" :viewContactMessage(viewingContact: Contact, contactIndex: int) activate ":TextUi" ":TextUi" --> ":ViewContactCommand" deactivate ":TextUi" - +end deactivate ":ViewContactCommand" -@enduml \ No newline at end of file +@enduml From 37c6caa918395e018b2d212078bec7f4f5a21970 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Sat, 6 Nov 2021 23:14:04 +0800 Subject: [PATCH 676/756] Refactor StorageClassDiagram code --- docs/diagrams/StorageClassDiagram.puml | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/diagrams/StorageClassDiagram.puml b/docs/diagrams/StorageClassDiagram.puml index 70bcc5975f..0a941e4552 100644 --- a/docs/diagrams/StorageClassDiagram.puml +++ b/docs/diagrams/StorageClassDiagram.puml @@ -1,4 +1,5 @@ @startuml +hide circle skinparam classAttributeIconSize 0 'https://plantuml.com/class-diagram From 16ca0e2d10e7b01419157568b94a0232e4531f97 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Sat, 6 Nov 2021 23:14:41 +0800 Subject: [PATCH 677/756] Update UG for search and delete expected output --- docs/UserGuide.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index cd12aa0c5e..ab3b9ab07f 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -198,6 +198,7 @@ Expected outcome of usage: ``` view 0 ____________________________________________________________ +0. Name: Alex Lee Github: github.com/alexlee Email: alex.lee@contech.sg @@ -273,7 +274,9 @@ Expected outcome of usages: rm 0 ____________________________________________________________ Delete this contact? (y/n) -0. Alex Lee + +0. +Name: Alex Lee Github: github.com/alexlee Email: alex.lee@contech.sg Telegram: t.me/alex133 @@ -392,6 +395,7 @@ Expected outcome of usage: ``` search -g lee ____________________________________________________________ +1. Name: Alex Lee Github: github.com/alexlee Email: alex.lee@contech.sg @@ -399,6 +403,7 @@ Telegram: t.me/alexl33 ____________________________________________________________ ____________________________________________________________ +6. Name: John Lee Github: github.com/johnlee Email: john.lee@contech.sg From 1a6b63509623b6a6987b105db01b56cdc9253549 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Sat, 6 Nov 2021 23:15:31 +0800 Subject: [PATCH 678/756] Add sections for manual testing in ToC --- docs/DeveloperGuide.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 54597761f2..4d516a99fd 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -26,6 +26,11 @@ - [Non-Function Requirements](#nf-req) - [Glossary](#glossary) - [Instructions for manual testing](#manual-test) + - [Launch and Shutdown](#launch-and-shutdown) + - [Adding a contact](#testing-add) + - [Viewing a contact](#testing-view) + - [Editing a contact](#testing-edit) + - [Deleting a contact](#testing-delete) ## Acknowledgements From 11596bc69c4e1f0a907462d09499a07e75733e1c Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Sat, 6 Nov 2021 23:15:57 +0800 Subject: [PATCH 679/756] Add TextUi component explanation --- docs/DeveloperGuide.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 4d516a99fd..a394215e7c 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -79,10 +79,18 @@ ConTech comprises five main components, namely: The five main components interact with each other, as shown in the sequence diagram below for the example: `view 2` -![Sysem Architecture Sequence Diagram](images/SystemArchitectureSequence.png) +![System Architecture Sequence Diagram](images/SystemArchitectureSequence.png) ### TextUi +The `TextUi` component is responsible for displaying all outputs to the Command Line User Interface. After a user's input +has been processed and ConTech has performed its commands depending on the input, in order to output the results of the +commands, a relevant method in the `TextUi` class will be called. + +Methods for printing **error messages** have been separated +from the main feature outputs. These methods have been placed in the `ExceptionTextUi` class within the same `ui` package +as `TextUi`. + ### MainParser The `MainParser` component is responsible for making sense of the user's inputs. It functions as the not only the identifier for commands, but also calls its relevant sub-parsers to further destructure From c1940d86ba3de4877b86379f926c0e6e3defce18 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Sat, 6 Nov 2021 23:16:38 +0800 Subject: [PATCH 680/756] Add instructions for testing launch and shutown --- docs/DeveloperGuide.md | 43 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index a394215e7c..9289bd9d99 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -281,3 +281,46 @@ additional devices or platforms. ## 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} +Given below are instructions to test the app manually. + +**Note:** These instructions only provide a starting point for testers to work on; testers are expected to do more +exploratory testing. + +### Launch and Shutdown + +1. Initial launch + 1. Ensure that you have Java `11` or above installed in your Computer. + 2. Download the latest version of `contech.jar` from **[here](https://github.com/AY2122S1-CS2113T-T09-1/tp/releases)**. + 3. Copy the `contech.jar` file to the folder you want to use as the _home folder_ for **ConTech**. + 4. Open your desired _Command Line Interface_ from the folder with `contech.jar` and enter the following code: + `java -jar contech.jar`. + + +2. First time user + 1. For a first time user, you would be required to type in your personal details. + 2. Entering your name will be **mandatory**. The other 5 fields (GitHub, Telegram, Twitter, Email and LinkedIn) are + **optional**. You will be prompted to enter each detail accordingly. For the optional fields, you can press ENTER + to skip. + + +3. Regular user + 1. For regular users, ConTech will simply greet you and you are ready to input your command. + Expected: + ``` + ____________________________________________________________ + Hello, John. + Welcome back to ConTech, your personal contact tracker. + ____________________________________________________________ + ``` + +4. Shutting down ConTech + 1. Once you are done with your tasks and would like to shutdown ConTech, simply input `exit`. + 2. Test case: `exit`
+ Expected: + ``` + ____________________________________________________________ + ConTech will now shutdown. + We hope you have enjoyed using it. + ____________________________________________________________ + ``` + From 5efc2f6bd8af5c90dea4dda9fc7ce090f5dc4721 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Sat, 6 Nov 2021 23:17:12 +0800 Subject: [PATCH 681/756] Add instructions for testing add contact --- docs/DeveloperGuide.md | 117 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 116 insertions(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 9289bd9d99..8246190156 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -280,7 +280,6 @@ additional devices or platforms. ## 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} Given below are instructions to test the app manually. **Note:** These instructions only provide a starting point for testers to work on; testers are expected to do more @@ -324,3 +323,119 @@ exploratory testing. ____________________________________________________________ ``` +### Adding a contact +1. Adding a contact with all fields + 1. Test case: `add -n Alex Lee -g alexlee -te alexlee -tw alexl33 -e alex.lee@email.com -l alexlee`
+ Expected: New contact will have all fields added. Each field will be displayed after it has been added to the + contact list. + ``` + ____________________________________________________________ + ConTech has added the specified contact: + Name: Alex Lee + Github: github.com/alexlee + Email: alex.lee@email.com + Telegram: t.me/alexlee + LinkedIn: linkedin.com/in/alexlee + Twitter: twitter.com/alexl33 + + You now have 1 contact(s). + ____________________________________________________________ + ``` + +2. Adding a contact with fewer fields + 1. Test case: `add -n Jake Tan -g tanjakey -e jakeytan@email.com`
+ Expected: New contact will only have the fields mentioned added to the contact. Each field that is field will be + displayed after it has been added to the contact list. + ``` + ____________________________________________________________ + ConTech has added the specified contact: + Name: Jake Tan + Github: github.com/tanjakey + Email: jakeytan@email.com + + You now have 1 contact(s). + ____________________________________________________________ + ``` + +3. Adding a contact with no field entered + 1. Test case: `add`
+ Expected: An error message will notify user that there are missing parameters. + ``` + ____________________________________________________________ + There seems to be missing parameters in your request. + Please enter command in this format: + add -n {-g } {-e } {-te } {-l } {-tw } + example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe + NOTE : At least NAME required + Order of parameters do not matter + ____________________________________________________________ + ``` + +4. Adding a contact with duplicates + 1. Prerequisites: A contact with similar either similar name or details must already be in the contact list. For + simplicity, we will re-use the same command from `1`. + 2. Test case: `add -n Alex Lee -g alexlee -te alexlee -tw alexl33 -e alex.lee@email.com -l alexlee`
+ Expected: ConTech will display a list of contacts that are already in your contact list with the same fields as + the one you are adding. It will then ask for your confirmation whether you would still like to add the contact + or ignore it. + ``` + ____________________________________________________________ + One of your saved contacts has a duplicate field: + + 0. + Name: Alex Lee + Github: github.com/alexlee + Email: alex.lee@email.com + Telegram: t.me/alexlee + LinkedIn: linkedin.com/in/alexlee + Twitter: twitter.com/alexl33 + + Do you still want to add the contact? (y/n) + ____________________________________________________________ + ``` + 3. Follow up: You can either input `y` which stands for **yes** allowing you to still add the contact despite having + a duplicate field or `n` which stands for **no** to disregard adding the contact. + + +5. Adding a contact with a wrong flag + 1. Test case: `add -n Ali -p alixpress`
+ Expected: An error message will notify user that there appears to be a flag that is not recognised. + ``` + ____________________________________________________________ + There appears to be a flag that is not recognised. + Please try again with a valid flag. + -n NAME + -g GITHUB + -l LINKEDIN + -te TELEGRAM + -tw TWITTER + -e EMAIL + ____________________________________________________________ + ``` + +6. Adding a contact with a wrong command + 1. Test case: `Add -n Ben`
+ Expected: An error message will notify user that ConTech is unable to understand the command and + that the user can try to input a valid command. The issue with the test case is that the `add` command has a capital + A. + ``` + ____________________________________________________________ + ConTech is unable to understand your request. + Please try again with a valid command. + ____________________________________________________________ + ``` + +7. Adding a contact with an invalid field format + 1. Test case: `add -n George -e george`
+ 2. Expected: An error message will notify user on the field with the invalid format. For this test case, the email + has the wrong format. + ``` + ____________________________________________________________ + The email id is not correctly formatted, + Rules for email id : + * Lowercase letters only + * Numbers, underscore, hyphen and dot allowed + * @ cannot be at the start or end + ____________________________________________________________ + ``` + From bbffa33bffc2ccaf694ad50ebd5ddc05b4e6f5ac Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Sat, 6 Nov 2021 23:17:35 +0800 Subject: [PATCH 682/756] Add instructions for testing view contact --- docs/DeveloperGuide.md | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 8246190156..5fe42d291b 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -439,3 +439,45 @@ exploratory testing. ____________________________________________________________ ``` +### Viewing a contact +1. Viewing a contact that is in the contact list + 1. Prerequisites: List all contacts using the `ls` command to find the index of specific contact. + 2. Test case: `view 1`
+ Expected: All details of the contact with index `1` will be displayed. + ``` + ____________________________________________________________ + Name: Alex Lee + Github: github.com/alexlee + Email: alex.lee@email.com + Telegram: t.me/alexlee + LinkedIn: linkedin.com/in/alexlee + Twitter: twitter.com/alexl33 + ____________________________________________________________ + ``` + +2. Viewing user's own personal contact + 1. Test case: `view me` + 2. Expected: All personal details of the user will be displayed. + + +3. Viewing a contact with a missing or invalid index + 1. Prerequisites: List all contacts using the `ls` command to find the index of specific contact. + 2. Test case: `view -1`
+ Expected: An error message will notify user on what the valid indexes are. + ``` + ____________________________________________________________ + The index you have input is out of range. + Please input a index between 0 and 2. + ____________________________________________________________ + ``` + 3. Test case: `view`
+ Expected: An error message will notify user that there is an index missing. + ``` + ____________________________________________________________ + There seems to be missing or invalid index in your request. + Please enter command in the following way: + view + Enter between 0 and 2 or "me" (personal contact) + ____________________________________________________________ + ``` + From 92c1cf10f189cf9083bdb036ec3bff77cb63edd3 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Sat, 6 Nov 2021 23:17:55 +0800 Subject: [PATCH 683/756] Add instructions for testing edit contact --- docs/DeveloperGuide.md | 111 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 5fe42d291b..b2684425af 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -481,3 +481,114 @@ exploratory testing. ____________________________________________________________ ``` +### Editing a contact +1. Editing a contact with all fields + 1. Prerequisites: List all contacts using the `ls` command to find the index of specific contact. + 2. Test case: `edit 1 -n Ben tan -g bentan -e ben.tan@email.com -te bentn -tw bent4n -l bentan`
+ Expected: Contact at index 1 will have all fields edited. Each field will be displayed after it has been edited. + The index of contacts will be changed after editing as the list will be sorted after the edit. + ``` + ____________________________________________________________ + ConTech has edited the specified contact: + Name: Ben tan + Github: github.com/bentan + Email: ben.tan@email.com + Telegram: t.me/bentn + LinkedIn: linkedin.com/in/bentan + Twitter: twitter.com/bent4n + ____________________________________________________________ + ``` + +2. Editing a contact with fewer fields + 1. Prerequisites: List all contacts using the `ls` command to find the index of specific contact. + 2. Test case: `edit 2 -n Charles -g chacharles -e charles@email.com`
+ Expected: Contact at index 2 will have only the name, GitHub and email edited while the other fields, if filled + will remain the same. All details will then be displayed. + + +3. Editing a contact with missing or invalid index + 1. Prerequisites: List all contacts using the `ls` command to find the index of specific contact. + 2. Test case: `edit -n Brandon`
+ Expected: An error message will appear to notify that there are missing parameters. + ``` + ____________________________________________________________ + There seems to be missing parameters in your request. + Please enter command in this format: + edit {-n } {-g } {-e } {-te } {-l } {-tw } + example : edit 0 -n George -g procoder -te george123 + NOTE : At least one flag and description required + Order of parameters do not matter except for INDEX + "me" is used as the INDEX for personal contact. + ____________________________________________________________ + ``` + 3. Test case: `edit 4 -n Brandon`
+ Expected: An error message will appear to notify that the index is out of range. + ``` + ____________________________________________________________ + The index you have input is out of range. + Please input a number between 0 and 3 to edit saved contacts. + Otherwise, input index "me" if you wish to edit your Personal Contact details. + ____________________________________________________________ + ``` + +4. Editing a user's personal contact + 1. Test case: `edit me -n Zack -g zackster -e zack@email.com`
+ 2. Expected: User's personal detail will be edited and the personal details will be displayed including fields that + were not edited. + + +5. Editing a contact with duplicates + 1. Prerequisites: A contact with similar either similar name or details must already be in the contact list. For + simplicity, we will re-use the same command from `1`. + 2. Prerequisites: List all contacts using the `ls` command to find the index of specific contact. + 3. Test case: `edit 0 -n Ben tan -g bentan -e ben.tan@email.com -te bentn -tw bent4n -l bentan`
+ Expected: ConTech will display a list of contacts that are already in your contact list with the same fields as + the ones you are editing. It will then ask for your confirmation whether you would still like to edit the contact + or ignore it. + ``` + ____________________________________________________________ + One of your saved contacts has a duplicate field: + + 1. + Name: Ben tan + Github: github.com/bentan + Email: ben.tan@email.com + Telegram: t.me/bentn + LinkedIn: linkedin.com/in/bentan + Twitter: twitter.com/bent4n + + Do you still want to edit the contact? (y/n) + ____________________________________________________________ + ``` + 3. Follow up: You can either input `y` which stands for **yes** allowing you to still edit the contact despite having + a duplicate field or `n` which stands for **no** to disregard editing the contact. + + +5. Editing a contact with a wrong flag + 1. Test case: `edit 0 -p ali`
+ Expected: An error message will appear to notify the user that there appears to be a flag that is not recognised. + ``` + ____________________________________________________________ + There appears to be a flag that is not recognised. + Please try again with a valid flag. + -n NAME + -g GITHUB + -l LINKEDIN + -te TELEGRAM + -tw TWITTER + -e EMAIL + ____________________________________________________________ + ``` + +6. Editing a contact with a wrong command + 1. Test case: `Edit -n Ben`
+ Expected: An error message will appear to notify the user that ConTech is unable to understand the command and + that the user can try to input a valid command. The issue with the test case is that the `edit` command has a capital + E. + ``` + ____________________________________________________________ + ConTech is unable to understand your request. + Please try again with a valid command. + ____________________________________________________________ + ``` + From cd1ae03c92846b64319f4b43eab59e1f10f1ce97 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Sat, 6 Nov 2021 23:18:07 +0800 Subject: [PATCH 684/756] Add instructions for testing delete contact --- docs/DeveloperGuide.md | 72 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index b2684425af..3b05e020e4 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -592,3 +592,75 @@ exploratory testing. ____________________________________________________________ ``` +### Deleting a contact +1. Deleting a contact that is in the contact list + 1. Prerequisites: List all contacts using the `ls` command to find the index of specific contact. + 2. Test case: `rm 1`
+ Expected: User will be asked to confirm deleting the contact at the specified index. All details of the contact + at index `1` will be displayed to allow user to check before confirming. + ``` + ____________________________________________________________ + Delete this contact? (y/n) + + 1. + Name: Alex Lee + Github: github.com/alexlee + Email: alex.lee@email.com + Telegram: t.me/alexlee + LinkedIn: linkedin.com/in/alexlee + Twitter: twitter.com/alexl33 + ____________________________________________________________ + ``` + 3. Follow up: You can either input `y` which stands for **yes** allowing you to delete the contact or `n` which + stands for **no** to cancel deleting the contact. + + +2. Deleting a contact with a missing or invalid index + 1. Prerequisites: List all contacts using the `ls` command to find the index of specific contact. + 2. Test case: `rm -1`
+ Expected: An error message will notify user on what the valid indexes are. + ``` + ____________________________________________________________ + The index you have input is out of range. + Please input a index between 0 and 2. + ____________________________________________________________ + ``` + 3. Test case: `rm`
+ Expected: An error message will notify user that there is an index missing. + ``` + ____________________________________________________________ + There seems to be missing or invalid index in your request. + Please enter command in the following way: + rm {REMOVE_DETAIL_FLAGS} + Enter between 0 and 3 + ____________________________________________________________ + ``` + +3. Deleting all contacts in the contact list + 1. Test case: `rm all`
+ Expected: User will be asked to confirm deleting all the contacts in the contact list. + ``` + ____________________________________________________________ + Delete all of your contacts? (y/n) + ____________________________________________________________ + ``` + 3. Follow up: You can either input `y` which stands for **yes** allowing you to delete all contacts or `n` which + stands for **no** to cancel deleting all contacts. + + +4. Deleting one or few fields from a contact + 1. Prerequisites: List all contacts using the `ls` command to find the index of specific contact. + 2. Test case: `rm 1 -g`
+ Expected: User will be asked to confirm deleting a field from the contact at the specified index. The specified + field of the contact at index `1` will be displayed to allow user to check before confirming. For this test case, + only the GitHub for the contact at index `1` will be displayed as only the `-g` flag is mentioned. + ``` + ____________________________________________________________ + Delete the following fields for Ben tan? (y/n) + + Github: github.com/bentan + ____________________________________________________________ + ``` + 3. Follow up: You can either input `y` which stands for **yes** allowing you to delete the field from the contact + or `n` which stands for **no** to cancel deleting the field from the contact. + From cd115fe8c8ad723ba0d0346afb8a255d2b1520dc Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Sat, 6 Nov 2021 23:40:07 +0800 Subject: [PATCH 685/756] Update viewing a contact section in DG --- docs/DeveloperGuide.md | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 3b05e020e4..cdcbb432d0 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -171,8 +171,20 @@ executed in `ConTech`. The sequence diagram below illustrates the process of exe ### Viewing a contact: `view` This feature is processed using `ViewContactCommand`. Whenever a user wants to view a specific contact from the -contact list, user can input `view INDEX` with the index of the desired contact displayed from the `list` feature. -`ViewContactCommand` is then created in the `MainParser` and executed in `ConTech`. +contact list, user can input `view INDEX` with the index of the desired contact displayed from the `ls` feature. +`ViewContactCommand` is then created in the `MainParser` and executed in `ConTech` after parsing for the index +of the desired contact. + +If the `INDEX` is input as `me`, it will be equivalent to the `contactIndex` being `-1` in which case the personal details +of the user will be printed by calling the `viewPersonalContactMessage` method in `TextUi`. + +If the `INDEX` is missing, it will be equivalent to the `contactIndex` being `-2` in which case the error message to +notify the user that the index is missing will be printed by calling the `missingIndexMessage` method in +`ExceptionTextUi`. + +Lastly, if the `INDEX` is within range and valid, the contact will be retrieved by calling the `getContactAtIndex` +method in `ContactList` which will return the `Contact` and store it as `viewingContact` in `ViewContactCommand`. +To print out the contact, the `viewContactMessage` method in `TextUi` will be called. The sequence diagram below illustrates the `execute()` function in `ViewContactCommand`. From 530717e1e81bc2c9b104c2bb79d0c84acab40267 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Sat, 6 Nov 2021 23:42:31 +0800 Subject: [PATCH 686/756] Update view contact in DG --- docs/DeveloperGuide.md | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index cdcbb432d0..9b68515908 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -175,18 +175,14 @@ contact list, user can input `view INDEX` with the index of the desired contact `ViewContactCommand` is then created in the `MainParser` and executed in `ConTech` after parsing for the index of the desired contact. -If the `INDEX` is input as `me`, it will be equivalent to the `contactIndex` being `-1` in which case the personal details -of the user will be printed by calling the `viewPersonalContactMessage` method in `TextUi`. - -If the `INDEX` is missing, it will be equivalent to the `contactIndex` being `-2` in which case the error message to -notify the user that the index is missing will be printed by calling the `missingIndexMessage` method in -`ExceptionTextUi`. - -Lastly, if the `INDEX` is within range and valid, the contact will be retrieved by calling the `getContactAtIndex` -method in `ContactList` which will return the `Contact` and store it as `viewingContact` in `ViewContactCommand`. -To print out the contact, the `viewContactMessage` method in `TextUi` will be called. - -The sequence diagram below illustrates the `execute()` function in `ViewContactCommand`. +If the `INDEX` is input as `me`, it will be equivalent to the `contactIndex` being `-1` in which case the personal +details of the user will be printed by calling the `viewPersonalContactMessage` method in `TextUi`. If the `INDEX` is +missing, it will be equivalent to the `contactIndex` being `-2` in which case the error message to notify the user that +the index is missing will be printed by calling the `missingIndexMessage` method in `ExceptionTextUi`. Lastly, if the +`INDEX` is within range and valid, the contact will be retrieved by calling the `getContactAtIndex` method in +`ContactList` which will return the `Contact` and store it as `viewingContact` in `ViewContactCommand`. To print out +the contact, the `viewContactMessage` method in `TextUi` will be called. The sequence diagram below illustrates the +process of viewing a contact. ![View Sequence Diagram](images/ViewContactCommandSequenceDiagram.png) From a13c86f1911614bb445c501655980fce195cf205 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Sun, 7 Nov 2021 00:12:04 +0800 Subject: [PATCH 687/756] Update FAQ and Import command for extra fields in save file --- docs/UserGuide.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 64c3556921..236e9f123f 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -415,7 +415,9 @@ Command format: `import` - Data to be imported should be stored in the file `data/import.txt`. - Data to be imported should adhere to the following format: - CSV for **six** fields in the order of `NAME,GITHUB,LINKEDIN,TELEGRAM,TWITTER,EMAIL` + - Any extra fields will be treated as erroneous input and discarded. - For values that are empty, a `null` has to be specified. + ``` Le Zong,lezongmun,null,lezongg,null,lezongmun@gmail.com marcus,null,null,null,null,null @@ -537,10 +539,10 @@ computer. The files are `data/contacts.txt` and `data/me.txt`. **Q**: Can I edit the files in `data/` manually? **A**: Yes, ConTech supports manual editing of `contacts.txt` and `me.txt` in the `data/` directory, although this is -not recommended. When doing so, remember to follow the correct syntax for contact details. Any incomplete/incorrect/ -corrupt data will be discarded by ConTech upon launch. Users are recommended to use the `add` and `edit` commands in the -app instead of manually editing the save data files. For adding a large number of contacts at once, the `import` function -can be used. +not recommended. When doing so, remember to follow the correct syntax for contact details. Any contacts with incomplete/ +incorrect/corrupt data such as extra or missing fields will be discarded by ConTech upon launch. As such, users are +recommended to use the `add` and `edit` commands in the app instead of manually editing the save data files. For adding +a large number of contacts at once, the `import` function can be used. **Q**: Does ConTech support duplicate prevention? From 7a0ef265345f5e8b46c8ef8b64161809549ed63b Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Sun, 7 Nov 2021 00:29:03 +0800 Subject: [PATCH 688/756] Add javadocs for methods by ashrafjfr --- .../java/seedu/command/AddContactCommand.java | 28 +++++++++++++++++-- .../seedu/command/EditContactCommand.java | 24 ++++++++++++++++ .../seedu/command/ViewContactCommand.java | 3 ++ src/main/java/seedu/parser/MainParser.java | 7 +++++ 4 files changed, 60 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/command/AddContactCommand.java b/src/main/java/seedu/command/AddContactCommand.java index 4da543714f..d3269c0635 100644 --- a/src/main/java/seedu/command/AddContactCommand.java +++ b/src/main/java/seedu/command/AddContactCommand.java @@ -70,6 +70,15 @@ public void execute() { } //@@author ashrafjfr + /** + * This method takes in the addedContact and contactList and checks whether there are any contacts already in the + * contactList that are duplicates to the addedContact. If there are duplicates, a confirmation message will be + * output to confirm whether the user would like to still add the duplicated contact. + * + * @param addedContact Contact that user has just input to add + * @param contactList List of current contacts + * @throws InvalidFlagException If the flag given is not recognised + */ private boolean hasDuplicates(Contact addedContact, ContactList contactList) throws InvalidFlagException { ArrayList duplicatedIndex = new ArrayList<>(); String[] addedContactDetails = addedContact.getContactStringArray(); @@ -92,11 +101,26 @@ private boolean hasDuplicates(Contact addedContact, ContactList contactList) thr return false; } + /** + * This method returns true if the input string is equal to the similar field of a saved contact indicating a + * duplicate. + * + * @param input String of field that user has input to add + * @param saved String of field that is already in the list of contacts + * @return boolean + */ private boolean hasDuplicateField(String input, String saved) { - return stringCleaner(saved).equals(stringCleaner(input)); + return cleanString(saved).equals(cleanString(input)); } - private String stringCleaner(String input) { + /** + * This method cleans a string by removing all spaces and converting each letter to lower case for ease of + * comparison. + * + * @param input String of a contact detail + * @return input String that is cleaned + */ + private String cleanString(String input) { return input.replace(" ", "").toLowerCase(); } //@@author diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index 2b95c0529f..55f301bb13 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -61,6 +61,15 @@ private void updateContact(Contact postEditContact) throws IndexOutOfBoundsExcep } //@@author ashrafjfr + /** + * This method takes in the postEditcontact, contactList and contactIndex to check whether there are any contacts + * already in the contactList that are duplicates to the postEditContact. If there are duplicates, a confirmation + * message will be output to confirm whether the user would like to still edit the duplicated contact. + * + * @param postEditContact Contact that has been edited with fields user intends to edit to + * @param contactList List of current contacts + * @param contactIndex int to know which index of contactList is being edited + */ private boolean hasDuplicates(Contact postEditContact, ContactList contactList, int contactIndex) { ArrayList duplicatedIndex = new ArrayList<>(); boolean[] hasEditedField = hasEditedFields(contactDetails); @@ -89,10 +98,25 @@ && hasDuplicateField(postEditContactDetails[j], currentContactDetails[j])) { return false; } + /** + * This method returns true if the input string is equal to the similar field of a saved contact indicating a + * duplicate. + * + * @param input String of field that user has input to add + * @param saved String of field that is already in the list of contacts + * @return boolean + */ private boolean hasDuplicateField(String input, String saved) { return cleanString(saved).equals(cleanString(input)); } + /** + * This method cleans a string by removing all spaces and converting each letter to lower case for ease of + * comparison. + * + * @param input String of a contact detail + * @return input String that is cleaned + */ private String cleanString(String input) { return input.replace(" ", "").toLowerCase(); } diff --git a/src/main/java/seedu/command/ViewContactCommand.java b/src/main/java/seedu/command/ViewContactCommand.java index 14cb1c433f..67a7f6aa41 100644 --- a/src/main/java/seedu/command/ViewContactCommand.java +++ b/src/main/java/seedu/command/ViewContactCommand.java @@ -20,6 +20,9 @@ public int getIndex() { return contactIndex; } + /** + * This method executes the process of printing out the contact the user wants to view. + */ public void execute() { try { if (contactIndex == PERSONAL_CONTACT_INDEX) { diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 74a84ae3a2..2f114b2967 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -237,6 +237,13 @@ private Command parseInvalidDetailCommand(Exception e) { } //@@author ashrafjfr + /** + * This method parses the userInput according to the view command. After parsing for the viewedIndex, it will + * initialise a new ViewContactCommand. + * + * @param userInput String that user has input + * @return new ViewContactCommand(viewedIndex) + */ private Command parseViewContact(String userInput) { try { int viewedIndex = IndexParser.getIndexFromInput(userInput); From 937a862e19dde205738f1ef2f05a5245d15150f8 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Sun, 7 Nov 2021 00:31:03 +0800 Subject: [PATCH 689/756] Update text-ui-test after changes to UI --- text-ui-test/ACTUAL.TXT | 35 +++++++++++++++++++++++++++------- text-ui-test/EXPECTED-UNIX.TXT | 35 +++++++++++++++++++++++++++------- text-ui-test/EXPECTED.TXT | 35 +++++++++++++++++++++++++++------- 3 files changed, 84 insertions(+), 21 deletions(-) diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index 2f64ad844c..0d442c31ce 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -147,7 +147,9 @@ ____________________________________________________________ ____________________________________________________________ Delete this contact? (y/n) -1. ng andre + +1. +Name: ng andre Github: github.com/ng-andre ____________________________________________________________ @@ -157,7 +159,9 @@ ____________________________________________________________ ____________________________________________________________ Delete this contact? (y/n) -1. ng andre + +1. +Name: ng andre Github: github.com/ng-andre ____________________________________________________________ @@ -218,6 +222,7 @@ ____________________________________________________________ ____________________________________________________________ ____________________________________________________________ +1. Name: ashraf Github: github.com/ashraf ____________________________________________________________ @@ -235,7 +240,7 @@ ____________________________________________________________ There seems to be missing or invalid index in your request. Please enter command in the following way: rm {REMOVE_DETAIL_FLAGS} -Enter between 0 and 4, "me" (personal contact) or "all" +Enter between 0 and 4 ____________________________________________________________ ____________________________________________________________ @@ -269,13 +274,16 @@ ____________________________________________________________ ____________________________________________________________ ____________________________________________________________ +3. Name: lezong Github: github.com/lezongmun ____________________________________________________________ ____________________________________________________________ Delete this contact? (y/n) -0. andre + +0. +Name: andre Github: github.com/ng-andre ____________________________________________________________ @@ -286,7 +294,9 @@ ____________________________________________________________ ____________________________________________________________ Delete this contact? (y/n) -0. ashraf + +0. +Name: ashraf Github: github.com/ashraf ____________________________________________________________ @@ -305,6 +315,7 @@ NOTE : At least NAME required ____________________________________________________________ ____________________________________________________________ +2. Name: mayank Github: github.com/mayankp123 ____________________________________________________________ @@ -345,7 +356,9 @@ ____________________________________________________________ ____________________________________________________________ Delete this contact? (y/n) -1. lezong + +1. +Name: lezong Github: github.com/lezongmun ____________________________________________________________ @@ -355,7 +368,9 @@ ____________________________________________________________ ____________________________________________________________ Delete this contact? (y/n) -1. lezong + +1. +Name: lezong Github: github.com/lezongmun ____________________________________________________________ @@ -437,6 +452,7 @@ You now have 6 contact(s). ____________________________________________________________ ____________________________________________________________ +0. Name: asjoda sadfsd Telegram: t.me/_123adad ____________________________________________________________ @@ -594,11 +610,13 @@ No search results found. ____________________________________________________________ ____________________________________________________________ +1. Name: bory Github: github.com/marcus ____________________________________________________________ ____________________________________________________________ +5. Name: lezongmun Github: github.com/lezong ____________________________________________________________ @@ -684,6 +702,7 @@ Telegram: t.me/ashrafjfr ____________________________________________________________ ____________________________________________________________ +0. Name: ashraf Github: github.com/ashrafjfr Email: ashrafjfr@gmail.com @@ -707,6 +726,7 @@ ConTech has successfully imported 3 lines ____________________________________________________________ ____________________________________________________________ +6. Name: lezai Github: github.com/lezongmun ____________________________________________________________ @@ -777,6 +797,7 @@ The specified fields for ashraf have been deleted. ____________________________________________________________ ____________________________________________________________ +0. Name: ashraf Github: github.com/ashrafjfr ____________________________________________________________ diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index 2f64ad844c..0d442c31ce 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -147,7 +147,9 @@ ____________________________________________________________ ____________________________________________________________ Delete this contact? (y/n) -1. ng andre + +1. +Name: ng andre Github: github.com/ng-andre ____________________________________________________________ @@ -157,7 +159,9 @@ ____________________________________________________________ ____________________________________________________________ Delete this contact? (y/n) -1. ng andre + +1. +Name: ng andre Github: github.com/ng-andre ____________________________________________________________ @@ -218,6 +222,7 @@ ____________________________________________________________ ____________________________________________________________ ____________________________________________________________ +1. Name: ashraf Github: github.com/ashraf ____________________________________________________________ @@ -235,7 +240,7 @@ ____________________________________________________________ There seems to be missing or invalid index in your request. Please enter command in the following way: rm {REMOVE_DETAIL_FLAGS} -Enter between 0 and 4, "me" (personal contact) or "all" +Enter between 0 and 4 ____________________________________________________________ ____________________________________________________________ @@ -269,13 +274,16 @@ ____________________________________________________________ ____________________________________________________________ ____________________________________________________________ +3. Name: lezong Github: github.com/lezongmun ____________________________________________________________ ____________________________________________________________ Delete this contact? (y/n) -0. andre + +0. +Name: andre Github: github.com/ng-andre ____________________________________________________________ @@ -286,7 +294,9 @@ ____________________________________________________________ ____________________________________________________________ Delete this contact? (y/n) -0. ashraf + +0. +Name: ashraf Github: github.com/ashraf ____________________________________________________________ @@ -305,6 +315,7 @@ NOTE : At least NAME required ____________________________________________________________ ____________________________________________________________ +2. Name: mayank Github: github.com/mayankp123 ____________________________________________________________ @@ -345,7 +356,9 @@ ____________________________________________________________ ____________________________________________________________ Delete this contact? (y/n) -1. lezong + +1. +Name: lezong Github: github.com/lezongmun ____________________________________________________________ @@ -355,7 +368,9 @@ ____________________________________________________________ ____________________________________________________________ Delete this contact? (y/n) -1. lezong + +1. +Name: lezong Github: github.com/lezongmun ____________________________________________________________ @@ -437,6 +452,7 @@ You now have 6 contact(s). ____________________________________________________________ ____________________________________________________________ +0. Name: asjoda sadfsd Telegram: t.me/_123adad ____________________________________________________________ @@ -594,11 +610,13 @@ No search results found. ____________________________________________________________ ____________________________________________________________ +1. Name: bory Github: github.com/marcus ____________________________________________________________ ____________________________________________________________ +5. Name: lezongmun Github: github.com/lezong ____________________________________________________________ @@ -684,6 +702,7 @@ Telegram: t.me/ashrafjfr ____________________________________________________________ ____________________________________________________________ +0. Name: ashraf Github: github.com/ashrafjfr Email: ashrafjfr@gmail.com @@ -707,6 +726,7 @@ ConTech has successfully imported 3 lines ____________________________________________________________ ____________________________________________________________ +6. Name: lezai Github: github.com/lezongmun ____________________________________________________________ @@ -777,6 +797,7 @@ The specified fields for ashraf have been deleted. ____________________________________________________________ ____________________________________________________________ +0. Name: ashraf Github: github.com/ashrafjfr ____________________________________________________________ diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 2f64ad844c..0d442c31ce 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -147,7 +147,9 @@ ____________________________________________________________ ____________________________________________________________ Delete this contact? (y/n) -1. ng andre + +1. +Name: ng andre Github: github.com/ng-andre ____________________________________________________________ @@ -157,7 +159,9 @@ ____________________________________________________________ ____________________________________________________________ Delete this contact? (y/n) -1. ng andre + +1. +Name: ng andre Github: github.com/ng-andre ____________________________________________________________ @@ -218,6 +222,7 @@ ____________________________________________________________ ____________________________________________________________ ____________________________________________________________ +1. Name: ashraf Github: github.com/ashraf ____________________________________________________________ @@ -235,7 +240,7 @@ ____________________________________________________________ There seems to be missing or invalid index in your request. Please enter command in the following way: rm {REMOVE_DETAIL_FLAGS} -Enter between 0 and 4, "me" (personal contact) or "all" +Enter between 0 and 4 ____________________________________________________________ ____________________________________________________________ @@ -269,13 +274,16 @@ ____________________________________________________________ ____________________________________________________________ ____________________________________________________________ +3. Name: lezong Github: github.com/lezongmun ____________________________________________________________ ____________________________________________________________ Delete this contact? (y/n) -0. andre + +0. +Name: andre Github: github.com/ng-andre ____________________________________________________________ @@ -286,7 +294,9 @@ ____________________________________________________________ ____________________________________________________________ Delete this contact? (y/n) -0. ashraf + +0. +Name: ashraf Github: github.com/ashraf ____________________________________________________________ @@ -305,6 +315,7 @@ NOTE : At least NAME required ____________________________________________________________ ____________________________________________________________ +2. Name: mayank Github: github.com/mayankp123 ____________________________________________________________ @@ -345,7 +356,9 @@ ____________________________________________________________ ____________________________________________________________ Delete this contact? (y/n) -1. lezong + +1. +Name: lezong Github: github.com/lezongmun ____________________________________________________________ @@ -355,7 +368,9 @@ ____________________________________________________________ ____________________________________________________________ Delete this contact? (y/n) -1. lezong + +1. +Name: lezong Github: github.com/lezongmun ____________________________________________________________ @@ -437,6 +452,7 @@ You now have 6 contact(s). ____________________________________________________________ ____________________________________________________________ +0. Name: asjoda sadfsd Telegram: t.me/_123adad ____________________________________________________________ @@ -594,11 +610,13 @@ No search results found. ____________________________________________________________ ____________________________________________________________ +1. Name: bory Github: github.com/marcus ____________________________________________________________ ____________________________________________________________ +5. Name: lezongmun Github: github.com/lezong ____________________________________________________________ @@ -684,6 +702,7 @@ Telegram: t.me/ashrafjfr ____________________________________________________________ ____________________________________________________________ +0. Name: ashraf Github: github.com/ashrafjfr Email: ashrafjfr@gmail.com @@ -707,6 +726,7 @@ ConTech has successfully imported 3 lines ____________________________________________________________ ____________________________________________________________ +6. Name: lezai Github: github.com/lezongmun ____________________________________________________________ @@ -777,6 +797,7 @@ The specified fields for ashraf have been deleted. ____________________________________________________________ ____________________________________________________________ +0. Name: ashraf Github: github.com/ashrafjfr ____________________________________________________________ From 1211a5402c9082ff1a7235864dae624a08744601 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Sun, 7 Nov 2021 00:50:28 +0800 Subject: [PATCH 690/756] Add team profile pictures to images --- docs/images/AndreProfile.jpg | Bin 0 -> 106571 bytes docs/images/AshrafProfile.jpg | Bin 0 -> 56532 bytes docs/images/LezongProfile.jpg | Bin 0 -> 72617 bytes docs/images/MarcusProfile.jpg | Bin 0 -> 25267 bytes docs/images/MayankProfile.png | Bin 0 -> 53789 bytes 5 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/images/AndreProfile.jpg create mode 100644 docs/images/AshrafProfile.jpg create mode 100644 docs/images/LezongProfile.jpg create mode 100644 docs/images/MarcusProfile.jpg create mode 100644 docs/images/MayankProfile.png diff --git a/docs/images/AndreProfile.jpg b/docs/images/AndreProfile.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e5d6d02a0c0342441a7d7f23133d2dda33e8f881 GIT binary patch literal 106571 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≻`qwSx5w>ar@A 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 R)0*KxSI<+ctG!O9{|}rrLazV- literal 0 HcmV?d00001 diff --git a/docs/images/AshrafProfile.jpg b/docs/images/AshrafProfile.jpg new file mode 100644 index 0000000000000000000000000000000000000000..cd37114f81250664fb1919ca85b326d5a1c35173 GIT binary patch literal 56532 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 z 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 T6XBO|&+$=36{&?plhFU!@`loE literal 0 HcmV?d00001 diff --git a/docs/images/LezongProfile.jpg b/docs/images/LezongProfile.jpg new file mode 100644 index 0000000000000000000000000000000000000000..780df70c6a921b130a2c2a49f3e5884a3f4f7728 GIT binary patch literal 72617 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 Ppo8}&2W!uH{~rBcaXE11 literal 0 HcmV?d00001 diff --git a/docs/images/MarcusProfile.jpg b/docs/images/MarcusProfile.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3e7563d990aa6431edcfc52677ca9816d0f0e748 GIT binary patch literal 25267 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 gy*uxtj=kvPxkrNFy(?*t6{@W)b*Oz4_5T3>* literal 0 HcmV?d00001 diff --git a/docs/images/MayankProfile.png b/docs/images/MayankProfile.png new file mode 100644 index 0000000000000000000000000000000000000000..60cf9cfa55a220b3aa824ba48d270fb983c92f10 GIT binary patch literal 53789 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 z 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 Date: Sun, 7 Nov 2021 00:50:54 +0800 Subject: [PATCH 691/756] Include profile pics to AboutUs --- docs/AboutUs.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index fb8ff19901..96e34d6837 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -2,9 +2,9 @@ Display | Name | Github Profile | Portfolio --------|:----:|:--------------:|:---------: -![](https://via.placeholder.com/100.png?text=Photo) | Marcus Ong | [Github](https://github.com/marcusbory) | [Portfolio](team/marcusbory.md) -![](https://via.placeholder.com/100.png?text=Photo) | Andre | [Github](https://github.com/ng-andre) | [Portfolio](team/ng-andre.md) -![](https://via.placeholder.com/100.png?text=Photo) | Mun Le Zong | [Github](https://github.com/lezongmun) | [Portfolio](team/lezongmun.md) -![](https://via.placeholder.com/100.png?text=Photo) | Mayank Panjiyara | [Github](https://github.com/mayankp291) | [Portfolio](team/mayankp291.md) -![](https://via.placeholder.com/100.png?text=Photo) | Ashraf| [Github](https://github.com/ashrafjfr) | [Portfolio](team/ashrafjfr.md) +![](images/MarcusProfile.jpg) | Marcus Ong | [Github](https://github.com/marcusbory) | [Portfolio](team/marcusbory.md) +![](images/AndreProfile.jpg) | Andre | [Github](https://github.com/ng-andre) | [Portfolio](team/ng-andre.md) +![](images/LezongProfile.jpg) | Mun Le Zong | [Github](https://github.com/lezongmun) | [Portfolio](team/lezongmun.md) +![](images/MayankProfile.png) | Mayank Panjiyara | [Github](https://github.com/mayankp291) | [Portfolio](team/mayankp291.md) +![](images/AshrafProfile.jpg) | Ashraf| [Github](https://github.com/ashrafjfr) | [Portfolio](team/ashrafjfr.md) From f6c42736153e518c18617b15847f976cbc3bf092 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Sun, 7 Nov 2021 00:51:08 +0800 Subject: [PATCH 692/756] Update ashrafjfr PPP --- docs/team/ashrafjfr.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/team/ashrafjfr.md b/docs/team/ashrafjfr.md index 7bec114b40..d901139d09 100644 --- a/docs/team/ashrafjfr.md +++ b/docs/team/ashrafjfr.md @@ -40,6 +40,9 @@ The code written by me (`ashrafjfr`) can be found [here](https://nus-cs2113-ay21 - Updated overall UG and fixed inconsistencies between UG and output from application - Added the `Table of Contents` with links to each feature in the UG - Added table of user stories for `User Stories` section in the DG + - Added `Instructions for Manual Testing` section in the DG +- Attended weekly meeting sessions with team to plan for product +- Updated UI of various features to ensure consistency across features ### Review/mentoring contributions - Reviewed PRs and ensured overall code quality/formatting was up to standard From 115ddcf34f8b2d54199b1e7702f9d1d79927367d Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Sun, 7 Nov 2021 01:03:27 +0800 Subject: [PATCH 693/756] Refactor javadoc for checkstyle --- src/main/java/seedu/command/AddContactCommand.java | 2 +- src/main/java/seedu/command/EditContactCommand.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/command/AddContactCommand.java b/src/main/java/seedu/command/AddContactCommand.java index d3269c0635..241ca74e93 100644 --- a/src/main/java/seedu/command/AddContactCommand.java +++ b/src/main/java/seedu/command/AddContactCommand.java @@ -102,7 +102,7 @@ private boolean hasDuplicates(Contact addedContact, ContactList contactList) thr } /** - * This method returns true if the input string is equal to the similar field of a saved contact indicating a + * Returns true if the input string is equal to the similar field of a saved contact indicating a * duplicate. * * @param input String of field that user has input to add diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index 55f301bb13..f135913e5b 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -99,7 +99,7 @@ && hasDuplicateField(postEditContactDetails[j], currentContactDetails[j])) { } /** - * This method returns true if the input string is equal to the similar field of a saved contact indicating a + * Returns true if the input string is equal to the similar field of a saved contact indicating a * duplicate. * * @param input String of field that user has input to add From f04130c8e1490b3f87f58abb6ae4f497883b8c74 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sun, 7 Nov 2021 04:12:26 +0800 Subject: [PATCH 694/756] Update userguide --- docs/UserGuide.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 6b832c6cdb..6cb76d5768 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -545,9 +545,9 @@ computer. The files are `data/contacts.txt` and `data/me.txt`. **A**: Yes, ConTech supports manual editing of `contacts.txt` and `me.txt` in the `data/` directory, although this is not recommended. When doing so, remember to follow the correct syntax for contact details. Any contacts with incomplete/ -incorrect/corrupt data such as extra or missing fields will be discarded by ConTech upon launch. As such, users are -recommended to use the `add` and `edit` commands in the app instead of manually editing the save data files. For adding -a large number of contacts at once, the `import` function can be used. +incorrect/corrupt data such as missing fields will be discarded by ConTech upon launch. In addition, extra fields +will be ignored. As such, users are recommended to use the `add` and `edit` commands in the app instead of manually +editing the save data files. For adding a large number of contacts at once, the `import` function can be used. **Q**: Does ConTech support duplicate prevention? From 35fdc96ccf203929a8a8f17c98c6a4e140f507a0 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sun, 7 Nov 2021 04:12:48 +0800 Subject: [PATCH 695/756] Add javadocs --- .../java/seedu/command/AddContactCommand.java | 4 ++ src/main/java/seedu/command/Command.java | 8 ++++ .../seedu/command/ImportContactCommand.java | 15 ++++++++ src/main/java/seedu/contact/Contact.java | 4 ++ src/main/java/seedu/contech/ConTech.java | 5 +++ .../java/seedu/parser/ContactDetails.java | 6 +++ src/main/java/seedu/parser/ContactParser.java | 11 ++---- src/main/java/seedu/parser/MainParser.java | 6 +++ .../java/seedu/storage/ContactsDecoder.java | 37 +++++++++++++++++++ .../java/seedu/storage/ContactsEncoder.java | 14 +++++++ src/main/java/seedu/storage/Storage.java | 12 ++++++ 11 files changed, 115 insertions(+), 7 deletions(-) diff --git a/src/main/java/seedu/command/AddContactCommand.java b/src/main/java/seedu/command/AddContactCommand.java index 241ca74e93..11b5a35857 100644 --- a/src/main/java/seedu/command/AddContactCommand.java +++ b/src/main/java/seedu/command/AddContactCommand.java @@ -55,6 +55,10 @@ public String getGithub() { return github; } + /** + * Executes the AddContactCommand with the supplied fields to add a new contact to the contact list. + * This method also checks for existing duplicates in the contact list. + */ public void execute() { try { Contact addedContact = new Contact(name, github, linkedin, telegram, twitter, email); diff --git a/src/main/java/seedu/command/Command.java b/src/main/java/seedu/command/Command.java index a71cb8f594..93646aab78 100644 --- a/src/main/java/seedu/command/Command.java +++ b/src/main/java/seedu/command/Command.java @@ -8,6 +8,10 @@ public abstract class Command { protected ContactList contactList; protected Contact personalContact; + /** + * Sets the current contact list as a context before proceeding with any command execution. + * @param contactList Current ContactList to be set + */ public void setContactList(ContactList contactList) { this.contactList = contactList; } @@ -18,6 +22,10 @@ public void setPersonalContact(Contact personalContact) { public abstract void execute(); + /** + * Returns true if the Command given is an ExitCommand + * @return boolean True if ExitCommand is given by user + */ public boolean isExit() { return this instanceof ExitCommand; } diff --git a/src/main/java/seedu/command/ImportContactCommand.java b/src/main/java/seedu/command/ImportContactCommand.java index 0225c6fd8a..57dbedd634 100644 --- a/src/main/java/seedu/command/ImportContactCommand.java +++ b/src/main/java/seedu/command/ImportContactCommand.java @@ -20,6 +20,10 @@ public ImportContactCommand() { importFile = new File(importFilePath); } + /** + * Executes the ImportContactCommand by attempting to read and append the import file's contents into the user's + * contact list. + */ public void execute() { if (foundImportFile()) { importContacts(); @@ -30,10 +34,17 @@ public void execute() { } } + /** + * Returns true if there exists an import file at the target location. + * @return boolean True if the import file exists + */ private boolean foundImportFile() { return importFile.exists(); } + /** + * Attempts to decode the import file and read its contents into a temporary contact list. + */ private void importContacts() { assert importFile.exists(); try { @@ -44,6 +55,10 @@ private void importContacts() { } } + /** + * Appends the temporary contact list to the user's contact list. + * Note: User's contact list is always sorted at any point during import. + */ private void appendImportedContacts() { for (int i = 0; i < importedContacts.getListSize(); i++) { contactList.addContact(importedContacts.getContactAtIndex(i)); diff --git a/src/main/java/seedu/contact/Contact.java b/src/main/java/seedu/contact/Contact.java index 37401a717e..7c835161f7 100644 --- a/src/main/java/seedu/contact/Contact.java +++ b/src/main/java/seedu/contact/Contact.java @@ -61,6 +61,10 @@ public void editContact(String[] contactDetails) { } //@@author marcusbory + /** + * Attempts to remove fields in the given contact. + * @param hasDeletedDetails boolean[] Array of whether a specified field is to be deleted + */ public void deleteContactFields(boolean[] hasDeletedDetails) { for (int i = GITHUB_INDEX; i <= EMAIL_INDEX; i++) { if (hasDeletedDetails[i]) { diff --git a/src/main/java/seedu/contech/ConTech.java b/src/main/java/seedu/contech/ConTech.java index b3ea068ffb..0bb91b5839 100644 --- a/src/main/java/seedu/contech/ConTech.java +++ b/src/main/java/seedu/contech/ConTech.java @@ -56,6 +56,11 @@ private void runConTech() { } while (!command.isExit()); } + /** + * Runs the Command Procedure by setting the contact list and personal contact contexts before executing any + * given command. Upon execution of given command, the contact list and personal contact are saved to local storage. + * @param command Supplied Command after parsing + */ private void runCommandProcedure(Command command) { try { command.setContactList(contactList); diff --git a/src/main/java/seedu/parser/ContactDetails.java b/src/main/java/seedu/parser/ContactDetails.java index dc6daef66d..e837a25be7 100644 --- a/src/main/java/seedu/parser/ContactDetails.java +++ b/src/main/java/seedu/parser/ContactDetails.java @@ -14,6 +14,12 @@ public interface ContactDetails { String EMAIL_FLAG = "e"; String LINKEDIN_FLAG = "l"; + /** + * Returns the index that identifies the detail type denoted by the flag. + * @param flag Flag specified by the user representing the field + * @return int Unique index of the detail + * @throws InvalidFlagException If the flag given is not recognised + */ default int getIndexToStore(String flag) throws InvalidFlagException { int indexToStore; switch (flag) { diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index 9bb772896c..46d137c556 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -34,9 +34,8 @@ public abstract String[] parseContactDetails(String userInput) MissingArgEditException, MissingArgAddException, DuplicateDetailException; /** - * This method takes in the contactDetails array and populates it with contact - * details. It will sift out the flags to decide what details to populate, using - * the enumeration from DetailType. + * Takes in the contactDetails array and populates it with contact details. Sifts out the flags to decide + * what details to populate, using the enumeration from DetailType. * * @param contactDetails String array containing contact details * @param detail Unparsed detail @@ -47,10 +46,8 @@ public void parseDetail(String[] contactDetails, String detail) InvalidGithubUsernameException, InvalidTelegramUsernameException, InvalidLinkedinUsernameException, InvalidTwitterUsernameException, InvalidEmailException, DuplicateDetailException { String[] destructuredDetails = detail.split(" ", NUMBER_OF_DETAILS); - // for commands that specify a flag, but do not specify any argument for that - // flag - // IndexOutOfBoundsException should not be thrown as the first if case will be - // true + // for commands that specify a flag, but do not specify any argument for that flag + // IndexOutOfBoundsException should not be thrown as the first if case will be true if (destructuredDetails.length == 1 || destructuredDetails[1].isBlank()) { throw new MissingDetailException(); } diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 2f114b2967..1d9ae2881c 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -163,6 +163,12 @@ private Command parseQueryCommand(String commandWord, String userInput) { } //@@author marcusbory + /** + * Returns an AddContactCommand after parsing the user's input if the specified input command was for adding a + * contact. + * @param userInput String that user has input + * @return Command AddContactCommand if the parsing was successful + */ private Command parseAddContact(String userInput) { try { String[] details = addContactParser.parseContactDetails(userInput); diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index cfcceb7ddd..00fd1a9965 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -24,7 +24,18 @@ import static seedu.parser.ContactParser.NUMBER_OF_FIELDS; import static seedu.storage.Storage.SEPARATOR; +/** + * This class inherits the abstract RegexParser class to decode and read local storage files. + */ public class ContactsDecoder extends RegexParser { + + /** + * Returns a ContactList containing contacts from parsing inputs in a specified file in local storage. + * @param contactFile Specified file to be read + * @param contactFilePath File path of specified file + * @return ContactList Returns a ContactList containing parsed contacts + * @throws FileErrorException If the program faces issues relating to local storage + */ public ContactList readContacts(File contactFile, String contactFilePath) throws FileErrorException { ContactList updatedContactList = new ContactList(); try { @@ -89,6 +100,13 @@ private Contact decodePersonalContact(String contactText, Contact contact) { } //@@author marcusbory + /** + * Decodes a string read from the file and attempts to parse it as a contact. + * @param contactList Given contact list for contact to be added to + * @param contactText String read from the file + * @param lineIndex Line which contactText was from + * @param contactFilePath File path of specified file + */ private void decodeContact(ContactList contactList, String contactText, int lineIndex, String contactFilePath) { // Add the decoded details into the contact list try { @@ -113,6 +131,12 @@ private void decodeContact(ContactList contactList, String contactText, int line } } + /** + * Prints the relevant message for invalid details pertaining to the parsed contacts + * @param e Exception that was caught + * @param lineIndex Line in the file which the exception was thrown + * @param contactFilePath File path of specified file + */ private void handleInvalidDetails(Exception e, int lineIndex, String contactFilePath) { ExceptionTextUi.invalidLoadedLineMessage(lineIndex, contactFilePath); if (e instanceof InvalidNameException) { @@ -130,6 +154,19 @@ private void handleInvalidDetails(Exception e, int lineIndex, String contactFile } } + /** + * Returns a String array containing parsed details relating to a contact + * @param contactText String read from the file + * @return String[] String array containing parsed contact details + * @throws IndexOutOfBoundsException If contactText contains fewer fields than required + * @throws InvalidGithubUsernameException If there exists an invalid Github username + * @throws InvalidNameException If there exists an invalid name + * @throws InvalidFlagException If there exists an invalid flag + * @throws InvalidTelegramUsernameException If there exists an invalid Telegram username + * @throws InvalidTwitterUsernameException If there exists an invalid Twitter username + * @throws InvalidLinkedinUsernameException If there exists an invalid Linkedin username + * @throws InvalidEmailException If there exists an invalid email + */ private String[] decodeDetails(String contactText) throws IndexOutOfBoundsException, InvalidGithubUsernameException, InvalidNameException, InvalidFlagException, InvalidTelegramUsernameException, InvalidTwitterUsernameException, diff --git a/src/main/java/seedu/storage/ContactsEncoder.java b/src/main/java/seedu/storage/ContactsEncoder.java index b166aa25f9..59439f018a 100644 --- a/src/main/java/seedu/storage/ContactsEncoder.java +++ b/src/main/java/seedu/storage/ContactsEncoder.java @@ -9,6 +9,9 @@ import static seedu.storage.Storage.SEPARATOR; +/** + * This class facilitates the saving of the user's contact list to their local storage file. + */ public class ContactsEncoder { //@@author lezongmun public void savePersonalContact(String contactFilePath, Contact personalContact) throws FileErrorException { @@ -23,6 +26,12 @@ public void savePersonalContact(String contactFilePath, Contact personalContact) } //@@author marcusbory + /** + * Saves a specified ContactList to a specified file path. + * @param contactFilePath Destination for the contact list to be saved + * @param contactList Contact list to be saved + * @throws FileErrorException If there an error writing to the file destination + */ public void saveContacts(String contactFilePath, ContactList contactList) throws FileErrorException { try { FileWriter fileWriter = new FileWriter(contactFilePath); @@ -37,6 +46,11 @@ public void saveContacts(String contactFilePath, ContactList contactList) throws } } + /** + * Returns a String containing the encoded details of a contact + * @param contact Contact in the contact list + * @return String Returns a string containing encoded details + */ private String encodeContact(Contact contact) { String stringifiedContact = contact.getName() + SEPARATOR + contact.getGithub() + SEPARATOR + contact.getLinkedin() + SEPARATOR + contact.getTelegram() + SEPARATOR diff --git a/src/main/java/seedu/storage/Storage.java b/src/main/java/seedu/storage/Storage.java index c0b75a3380..160fbf243a 100644 --- a/src/main/java/seedu/storage/Storage.java +++ b/src/main/java/seedu/storage/Storage.java @@ -52,6 +52,12 @@ private boolean hasEmptyExistingPersonalContactFile() { } //@@author marcusbory + /** + * Checks if there is already an existing local storage file, and attempts to create a new local storage file for + * data persistence if one does not exist. + * @return boolean Returns true if local storage file exists + * @throws FileErrorException If there are errors writing or checking for local storage files + */ private boolean hasExistingContactFile() throws FileErrorException { try { if (!contactFile.exists()) { @@ -67,6 +73,12 @@ private boolean hasExistingContactFile() throws FileErrorException { return true; } + /** + * Attempts to decode and retrieve existing contacts from a user's local storage file, or returns a new contact + * list if no local storage files are found. + * @return ContactList Decoded contact list from local storage file + * @throws FileErrorException If there are errors reading from local storage file + */ public ContactList loadExistingContacts() throws FileErrorException { if (!hasExistingContactFile()) { return new ContactList(); From e4f7b402309184553325efcc2650e7799fee3146 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sun, 7 Nov 2021 11:01:09 +0800 Subject: [PATCH 696/756] Fix checkstyle --- src/main/java/seedu/command/Command.java | 2 +- src/main/java/seedu/storage/ContactsDecoder.java | 4 ++-- src/main/java/seedu/storage/ContactsEncoder.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/seedu/command/Command.java b/src/main/java/seedu/command/Command.java index 93646aab78..a9dd319e12 100644 --- a/src/main/java/seedu/command/Command.java +++ b/src/main/java/seedu/command/Command.java @@ -23,7 +23,7 @@ public void setPersonalContact(Contact personalContact) { public abstract void execute(); /** - * Returns true if the Command given is an ExitCommand + * Returns true if the Command given is an ExitCommand. * @return boolean True if ExitCommand is given by user */ public boolean isExit() { diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index 00fd1a9965..9654aeebd3 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -132,7 +132,7 @@ private void decodeContact(ContactList contactList, String contactText, int line } /** - * Prints the relevant message for invalid details pertaining to the parsed contacts + * Prints the relevant message for invalid details pertaining to the parsed contacts. * @param e Exception that was caught * @param lineIndex Line in the file which the exception was thrown * @param contactFilePath File path of specified file @@ -155,7 +155,7 @@ private void handleInvalidDetails(Exception e, int lineIndex, String contactFile } /** - * Returns a String array containing parsed details relating to a contact + * Returns a String array containing parsed details relating to a contact. * @param contactText String read from the file * @return String[] String array containing parsed contact details * @throws IndexOutOfBoundsException If contactText contains fewer fields than required diff --git a/src/main/java/seedu/storage/ContactsEncoder.java b/src/main/java/seedu/storage/ContactsEncoder.java index 59439f018a..678cceeba9 100644 --- a/src/main/java/seedu/storage/ContactsEncoder.java +++ b/src/main/java/seedu/storage/ContactsEncoder.java @@ -47,7 +47,7 @@ public void saveContacts(String contactFilePath, ContactList contactList) throws } /** - * Returns a String containing the encoded details of a contact + * Returns a String containing the encoded details of a contact. * @param contact Contact in the contact list * @return String Returns a string containing encoded details */ From c87b34d444166b560d470be384a69b60c3efb47d Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Sun, 7 Nov 2021 15:00:36 +0800 Subject: [PATCH 697/756] Update error message for no contacts --- src/main/java/seedu/ui/ExceptionTextUi.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index c21e530015..1fdc9bb690 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -210,10 +210,7 @@ public static void missingIndexViewMessage(int listSize) { public static void missingIndexDeleteMessage(int listSize) { String message; if (listSize == 0) { - message = "There seems to be missing or invalid index in your request.\n" - + "Please enter command in the following way:\n" - + " rm {REMOVE_DETAIL_FLAGS}\n" - + "Enter as 0"; + message = "There are no contacts stored in ConTech."; } else if (listSize == 1) { message = "There seems to be missing or invalid index in your request.\n" + "Please enter command in the following way:\n" From 1846fdf2f89070da3796bb5363952b426e12a60b Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Sun, 7 Nov 2021 15:00:47 +0800 Subject: [PATCH 698/756] Update messsage for 1 contact --- src/main/java/seedu/ui/ExceptionTextUi.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index 1fdc9bb690..e5e79670d6 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -215,7 +215,7 @@ public static void missingIndexDeleteMessage(int listSize) { message = "There seems to be missing or invalid index in your request.\n" + "Please enter command in the following way:\n" + " rm {REMOVE_DETAIL_FLAGS}\n" - + "Enter as 0 or 1"; + + "Enter as 0 as only one contact is stored"; } else { message = "There seems to be missing or invalid index in your request.\n" + "Please enter command in the following way:\n" From 1bd9f7a5ded53bedca3b7ea58b6c363bd1e30df3 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Sun, 7 Nov 2021 15:01:00 +0800 Subject: [PATCH 699/756] Update name regex message --- src/main/java/seedu/ui/ExceptionTextUi.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index e5e79670d6..5fe7366c50 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -330,9 +330,9 @@ public static void missingImportFileMessage() { public static void invalidNameInput() { String message = "The name is not correctly formatted,\n" + "Rules for name :\n" - + " * Uppercase and lowercase letters\n" - + " * Spaces\n" - + " * No numbers or special characters\n" + + " * Uppercase and lowercase letters allowed\n" + + " * Spaces, fullstops, apostrophes and slashes allowed\n" + + " * No numbers or other special characters\n" + " * Cannot be \"null\""; printDoubleLineMessage(message); } From 610d55c2e07f6eef4177b5119cfada40df485d8b Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Sun, 7 Nov 2021 15:01:15 +0800 Subject: [PATCH 700/756] Update email regex message --- src/main/java/seedu/ui/ExceptionTextUi.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index 5fe7366c50..a6b4fe485e 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -376,7 +376,7 @@ public static void invalidEmailInput() { + "Rules for email id :\n" + " * Lowercase letters only\n" + " * Numbers, underscore, hyphen and dot allowed\n" - + " * @ cannot be at the start or end"; + + " * @ cannot be at the start or end and only one allowed"; printDoubleLineMessage(message); } From bc05c30223acd560ffa696fd78dfd1a875a9b5d3 Mon Sep 17 00:00:00 2001 From: lezong Date: Sun, 7 Nov 2021 15:08:20 +0800 Subject: [PATCH 701/756] Stash --- docs/DeveloperGuide.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 32f3458dab..f1b39fb9c8 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -265,6 +265,7 @@ specified contact index given as an integer, which will then be used in the exec For example, if `edit 2 -n Marcus Bobo` is given as the input, the Index Parser will identify the contact index to be `2` and pass the contact index to the execution of the `edit` command accordingly. + ## Product scope ### Target user profile From 68230e816a62614ddd8fb4206bd5c357c60f01f0 Mon Sep 17 00:00:00 2001 From: lezong Date: Sun, 7 Nov 2021 16:01:53 +0800 Subject: [PATCH 702/756] JavaDocs for DeleteContactCommand --- .../seedu/command/DeleteContactCommand.java | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/command/DeleteContactCommand.java b/src/main/java/seedu/command/DeleteContactCommand.java index 67d49f8703..a7243b8e29 100644 --- a/src/main/java/seedu/command/DeleteContactCommand.java +++ b/src/main/java/seedu/command/DeleteContactCommand.java @@ -25,7 +25,14 @@ public int getContactIndex() { return contactIndex; } - + /** + * This method is used to delete one specified contact given by the user. It finds + * the contact to be deleted and prompts the user for confirmation to delete, before + * executing any deletion of a contact. + * + * @throws IndexOutOfBoundsException If index given in the DeleteContactCommand is + * outside the size of the Contact List. + */ private void deleteSelectedContact() throws IndexOutOfBoundsException { // throws IndexOutOfBoundsException if index is outside of the range Contact deletedContact = contactList.getContactAtIndex(contactIndex); @@ -45,6 +52,11 @@ private void deleteSelectedContact() throws IndexOutOfBoundsException { } } + /** + * This method is used to delete all of the contacts in the Contact List. It + * prompts the user for confirmation to delete before executing any deletion + * of all the contacts. + */ private void deleteAllContacts() { TextUi.confirmDeleteAllMessage(); String userConfirmation = UserInputTextUi.getUserConfirmation(); @@ -58,6 +70,11 @@ private void deleteAllContacts() { } } + /** + * This method is used to delete specified fields of a selected contact. It + * finds the selected contact with fields to be deleted, and prompts the user + * for confirmation to delete before executing any deletion of fields. + */ private void deleteFields() { Contact deletedContact = contactList.getContactAtIndex(contactIndex); assert contactIndex >= 0 && contactIndex < contactList.getListSize(); @@ -77,6 +94,11 @@ private void deleteFields() { } } + /** + * This method executes the deletion process of the DeleteContactCommand. It + * checks whether the deletion is for all contacts, a single contact or a + * contact's fields, before running their corresponding delete methods + */ public void execute() { try { if (contactIndex == DELETE_ALL_CONTACTS_INDEX) { From 876520fc94c65d6b69234c7d111e2e6187f73c23 Mon Sep 17 00:00:00 2001 From: lezong Date: Sun, 7 Nov 2021 16:23:47 +0800 Subject: [PATCH 703/756] Add some JavaDocs in EditContactCommand --- .../seedu/command/DeleteContactCommand.java | 4 ++-- .../seedu/command/EditContactCommand.java | 21 +++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/command/DeleteContactCommand.java b/src/main/java/seedu/command/DeleteContactCommand.java index a7243b8e29..986d429c23 100644 --- a/src/main/java/seedu/command/DeleteContactCommand.java +++ b/src/main/java/seedu/command/DeleteContactCommand.java @@ -30,8 +30,8 @@ public int getContactIndex() { * the contact to be deleted and prompts the user for confirmation to delete, before * executing any deletion of a contact. * - * @throws IndexOutOfBoundsException If index given in the DeleteContactCommand is - * outside the size of the Contact List. + * @throws IndexOutOfBoundsException If index given in the DeleteContactCommand by user + * is outside the size of the Contact List. */ private void deleteSelectedContact() throws IndexOutOfBoundsException { // throws IndexOutOfBoundsException if index is outside of the range diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index f135913e5b..e5f32f05e3 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -40,11 +40,24 @@ public void execute() { } } + /** + * This method edits the fields of the personal contact, based on + * the contactDetails of the EditContactCommand. + */ private void updatePersonalContact() { personalContact.editContact(contactDetails); TextUi.editPersonalContactMessage(personalContact); } + /** + * This method is used to check whether the EditContactCommand has to + * handle any contact duplicates in the Contact List or to edit the + * contact's details. + * + * @param postEditContact Contact that has been edited with fields user intends to edit to + * @throws IndexOutOfBoundsException If index given in the EditContactCommand by user is + * outside the size of the Contact List. + */ private void handleDuplicates(Contact postEditContact) throws IndexOutOfBoundsException { if (hasDuplicates(postEditContact, contactList, contactIndex)) { TextUi.ignoreContact(EDIT_TYPE); @@ -53,6 +66,14 @@ private void handleDuplicates(Contact postEditContact) throws IndexOutOfBoundsEx } } + /** + * This method edits the fields of the selected contact in the Contact List, + * based on the contactDetails of the EditContactCommand. + * + * @param postEditContact Contact that has been edited with fields user intends to edit to + * @throws IndexOutOfBoundsException If index given in the EditContactCommand by user is + * outside the size of the Contact List. + */ private void updateContact(Contact postEditContact) throws IndexOutOfBoundsException { contactList.editContactAtIndex(contactDetails, contactIndex); //sort the contact list based on name after a contact has been edited From 653a898f6a630bd398d5c99608af76e5616e0feb Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Sun, 7 Nov 2021 16:48:53 +0800 Subject: [PATCH 704/756] Update email regex message --- src/main/java/seedu/ui/ExceptionTextUi.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index a6b4fe485e..508e67a9f7 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -374,7 +374,7 @@ public static void invalidTwitterUsernameInput() { public static void invalidEmailInput() { String message = "The email id is not correctly formatted,\n" + "Rules for email id :\n" - + " * Lowercase letters only\n" + + " * Lowercase and uppercase letters allowed\n" + " * Numbers, underscore, hyphen and dot allowed\n" + " * @ cannot be at the start or end and only one allowed"; printDoubleLineMessage(message); From 2049ccb5af9938cf707e102a527aac6d0465320e Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Sun, 7 Nov 2021 16:50:22 +0800 Subject: [PATCH 705/756] Add javadoc for regex parser --- src/main/java/seedu/parser/RegexParser.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/main/java/seedu/parser/RegexParser.java b/src/main/java/seedu/parser/RegexParser.java index 51ecb2494d..ad2ffb043e 100644 --- a/src/main/java/seedu/parser/RegexParser.java +++ b/src/main/java/seedu/parser/RegexParser.java @@ -25,6 +25,23 @@ public abstract class RegexParser { TELEGRAM_FLAG, TWITTER_FLAG, EMAIL_FLAG}; private static final Logger LOGGER = Logger.getLogger(RegexParser.class.getName()); + /** + * Throws an exception if the field does not comply with the regex. + * If the field passes the regex check nothing is returned and program + * flow continues. + * The flag provided is checked in a switch case to invoke the respective + * function to check the regex of the field. + * + * @param flag field type + * @param detailToParse field contents + * @throws InvalidGithubUsernameException If GitHub username does not match regex + * @throws InvalidNameException If Name does not match regex + * @throws InvalidFlagException If flag is invalid + * @throws InvalidTelegramUsernameException If Telegram username does not match regex + * @throws InvalidTwitterUsernameException If Twitter username does not match regex + * @throws InvalidLinkedinUsernameException If LinkedIn username does not match regex + * @throws InvalidEmailException If Email does not match regex + */ public void checkRegex(String flag, String detailToParse) throws InvalidGithubUsernameException, InvalidNameException, InvalidFlagException, InvalidTelegramUsernameException, InvalidTwitterUsernameException, From f3d6011acc1d55bc24b1ed2f5bd702fdc38ddcc0 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Sun, 7 Nov 2021 16:50:56 +0800 Subject: [PATCH 706/756] Add javadoc for email regex parser --- src/main/java/seedu/parser/RegexParser.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/RegexParser.java b/src/main/java/seedu/parser/RegexParser.java index ad2ffb043e..df20c98fdc 100644 --- a/src/main/java/seedu/parser/RegexParser.java +++ b/src/main/java/seedu/parser/RegexParser.java @@ -72,8 +72,22 @@ public void checkRegex(String flag, String detailToParse) } } + /** + * Throws an exception if the email id does not comply with the regex. + * If the email passes the regex check nothing is returned and program + * flow continues. + * The function only allows emails in lowercase and uppercase letters, + * numbers, with symbols including hyphens, underscores, "@" and dot. + * The symbols cannot be placed at the start or end of the + * email or be consecutive. Also, only one "@" symbol allowed. + * + * @param detailToParse email id to be checked + * @throws InvalidEmailException If email does not match regex + */ protected void checkEmailRegex(String detailToParse) throws InvalidEmailException { - //allow lowercase email ids + // Allows lowercase, uppercase, numbers, hyphen, underscore, "@" and dot. + // Blocks consecutive symbols or if placed at start or end + // Only one "@" symbol allowed String emailRegex = "^(([^<>()\\[\\]\\\\.,;:\\s@\"]+(\\.[^<>()\\[\\]\\\\.,;:\\s@\"]+)*)|" + "(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|" + "(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$"; From 52c4be3852aebe9db251e4d718859bae46649e63 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Sun, 7 Nov 2021 16:51:09 +0800 Subject: [PATCH 707/756] Add javadoc for linkedin regex parser --- src/main/java/seedu/parser/RegexParser.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/RegexParser.java b/src/main/java/seedu/parser/RegexParser.java index df20c98fdc..1cbbf963f5 100644 --- a/src/main/java/seedu/parser/RegexParser.java +++ b/src/main/java/seedu/parser/RegexParser.java @@ -97,8 +97,19 @@ protected void checkEmailRegex(String detailToParse) throws InvalidEmailExceptio } } + /** + * Throws an exception if the LinkedIn username does not comply with the regex. + * If the LinkedIn username passes the regex check nothing is returned and program + * flow continues. + * The regex only allows usernames in lowercase letters, numbers, underscore and + * hyphen with a length between 3 and 100 characters. + * + * @param detailToParse LinkedIn username to be checked + * @throws InvalidLinkedinUsernameException If LinkedIn does not match regex + */ protected void checkLinkedinUsernameRegex(String detailToParse) throws InvalidLinkedinUsernameException { - //allows lowercase, numbers, underscore and hyphen. Length must be 3-100 characters + // Allows lowercase, numbers, underscore and hyphen + // Length must be 3-100 characters String linkedinRegex = "^[a-z0-9-_]{3,100}$"; if (!detailToParse.matches(linkedinRegex)) { LOGGER.log(Level.FINE, "Regex check for Linkedin failed"); From 52d0ed5659e79cf56374f44e690c7b40c5e7bad1 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Sun, 7 Nov 2021 16:51:18 +0800 Subject: [PATCH 708/756] Add javadoc for twitter regex parser --- src/main/java/seedu/parser/RegexParser.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/RegexParser.java b/src/main/java/seedu/parser/RegexParser.java index 1cbbf963f5..6015e3b7f0 100644 --- a/src/main/java/seedu/parser/RegexParser.java +++ b/src/main/java/seedu/parser/RegexParser.java @@ -117,8 +117,19 @@ protected void checkLinkedinUsernameRegex(String detailToParse) throws InvalidLi } } + /** + * Throws an exception if the Twitter username does not comply with the regex. + * If the Twitter username passes the regex check nothing is returned and program + * flow continues. + * The regex only allows usernames in lowercase letters, numbers, and underscore + * with a max length of 15 characters. + * + * @param detailToParse Twitter username id to be checked + * @throws InvalidTwitterUsernameException If Twitter username does not match regex + */ protected void checkTwitterUsernameRegex(String detailToParse) throws InvalidTwitterUsernameException { - //allows lowercase, numbers and underscore. Length must be max 15 characters + // Allows lowercase, numbers and underscore + // Length must be max 15 characters String twitterRegex = "^[a-z0-9_]{1,15}$"; if (!detailToParse.matches(twitterRegex)) { LOGGER.log(Level.FINE, "Regex check for Name failed"); From ee307ee7383c455eff1d5aa2df507f52ea50969c Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Sun, 7 Nov 2021 16:51:43 +0800 Subject: [PATCH 709/756] Add javadoc for twitter regex parser --- src/main/java/seedu/parser/RegexParser.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/RegexParser.java b/src/main/java/seedu/parser/RegexParser.java index 6015e3b7f0..4596db33b7 100644 --- a/src/main/java/seedu/parser/RegexParser.java +++ b/src/main/java/seedu/parser/RegexParser.java @@ -137,8 +137,19 @@ protected void checkTwitterUsernameRegex(String detailToParse) throws InvalidTwi } } + /** + * Throws an exception if the Telegram username does not comply with the regex. + * If the Telegram username passes the regex check nothing is returned and program + * flow continues. + * The regex only allows usernames in lowercase and uppercase letters, numbers, and underscore + * with a length of at least 5 characters. + * + * @param detailToParse Telegram username to be checked + * @throws InvalidTelegramUsernameException If Telegram username does not match regex + */ protected void checkTelegramUsernameRegex(String detailToParse) throws InvalidTelegramUsernameException { - //allows uppercase, lowercase, numbers and underscore. Length must be at least 5 characters + // Allows uppercase, lowercase, numbers and underscore + // Length must be at least 5 characters String telegramRegex = "^[a-zA-Z0-9_]{5,}$"; if (!detailToParse.matches(telegramRegex)) { LOGGER.log(Level.FINE, "Regex check for Telegram username failed"); From be732d879467587108923e9a9ff592e46cd7f1a5 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Sun, 7 Nov 2021 16:51:50 +0800 Subject: [PATCH 710/756] Add javadoc for github regex parser --- src/main/java/seedu/parser/RegexParser.java | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/main/java/seedu/parser/RegexParser.java b/src/main/java/seedu/parser/RegexParser.java index 4596db33b7..dbe0ee16d7 100644 --- a/src/main/java/seedu/parser/RegexParser.java +++ b/src/main/java/seedu/parser/RegexParser.java @@ -157,11 +157,22 @@ protected void checkTelegramUsernameRegex(String detailToParse) throws InvalidTe } } + /** + * Throws an exception if the GitHub username does not comply with the regex. + * If the GitHub username passes the regex check nothing is returned and program + * flow continues. + * The regex only allows usernames in lowercase and uppercase letters, numbers and hyphen + * with a max length of 39 characters. It also blocks multiple consecutive hyphens or + * hyphens at the start or end of the username. + * + * @param detailToParse GitHub username to be checked + * @throws InvalidGithubUsernameException If GitHub username does not match regex + */ protected void checkGithubUsernameRegex(String detailToParse) throws InvalidGithubUsernameException { - //GitHub username may only contain alphanumeric characters or hyphens. - //GitHub username cannot have multiple consecutive hyphens. - //GitHub username cannot begin or end with a hyphen. - //Maximum is 39 characters. + // Allows alphanumeric characters or hyphens. + // Blocks multiple consecutive hyphens. + // Cannot begin or end with a hyphen. + // Length must be max 39 characters String githubUsernameRegex = "^[a-zA-Z\\d](?:[a-zA-Z\\d]|-(?=[a-zA-Z\\d])){0,39}$"; if (!detailToParse.matches(githubUsernameRegex)) { LOGGER.log(Level.FINE, "Regex check for Github username failed"); From 693008fad6b800a6e345a3b7a28139c006b36b73 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Sun, 7 Nov 2021 16:51:56 +0800 Subject: [PATCH 711/756] Add javadoc for name regex parser --- src/main/java/seedu/parser/RegexParser.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/RegexParser.java b/src/main/java/seedu/parser/RegexParser.java index dbe0ee16d7..ece40878ba 100644 --- a/src/main/java/seedu/parser/RegexParser.java +++ b/src/main/java/seedu/parser/RegexParser.java @@ -180,8 +180,20 @@ protected void checkGithubUsernameRegex(String detailToParse) throws InvalidGith } } + /** + * Throws an exception if the Name does not comply with the regex. + * If the Name passes the regex check nothing is returned and program + * flow continues. + * The regex only allows Names in lowercase and uppercase letters with + * symbols fullstop, apostrophe and slash. Space is also allowed between + * words. + * + * @param detailToParse Name to be checked + * @throws InvalidNameException If Name does not match regex + */ protected void checkNameRegex(String detailToParse) throws InvalidNameException { - //only letters and spaces allowed + // Allows uppercase, lowercase, fullstop, apostrophe and slash + // Allows one space between consecutive words String nameRegex = "^([a-zA-Z.'/]+\\s)*[a-zA-Z.'/]+$"; if (!detailToParse.matches(nameRegex)) { LOGGER.log(Level.FINE, "Regex check for name failed"); From 6ef1cef6e34f6f349c965930db92e598bc02f893 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Sun, 7 Nov 2021 16:57:03 +0800 Subject: [PATCH 712/756] Add javadocs --- src/main/java/seedu/command/InvalidDetailCommand.java | 7 +++++++ src/main/java/seedu/command/ListContactsCommand.java | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/src/main/java/seedu/command/InvalidDetailCommand.java b/src/main/java/seedu/command/InvalidDetailCommand.java index cc66fed0b7..c7b34168b3 100644 --- a/src/main/java/seedu/command/InvalidDetailCommand.java +++ b/src/main/java/seedu/command/InvalidDetailCommand.java @@ -12,10 +12,17 @@ public InvalidDetailCommand(FailedCommandType type) { this.type = type; } + /** + * Returns the type of failed command. + */ public FailedCommandType getType() { return type; } + /** + * Invokes the respective Text Ui function to print + * the error message based on the "type" provided. + */ public void execute() { switch (type) { case INVALID_NAME: diff --git a/src/main/java/seedu/command/ListContactsCommand.java b/src/main/java/seedu/command/ListContactsCommand.java index 482e20f325..2ac45d588f 100644 --- a/src/main/java/seedu/command/ListContactsCommand.java +++ b/src/main/java/seedu/command/ListContactsCommand.java @@ -5,6 +5,10 @@ import seedu.ui.TextUi; public class ListContactsCommand extends Command { + /** + * Prints all the contacts stored with the respective index + * and name. + */ public void execute() { int listSize = contactList.getListSize(); if (listSize == 0) { From 1b2bd93a195b2837e985281ab6e38c0f5131363e Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Sun, 7 Nov 2021 17:03:28 +0800 Subject: [PATCH 713/756] Update IO tests --- text-ui-test/ACTUAL.TXT | 20 ++++++++++---------- text-ui-test/EXPECTED-UNIX.TXT | 20 ++++++++++---------- text-ui-test/EXPECTED.TXT | 20 ++++++++++---------- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index 0d442c31ce..56c33d3cef 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -108,9 +108,9 @@ ____________________________________________________________ ____________________________________________________________ The email id is not correctly formatted, Rules for email id : - * Lowercase letters only + * Lowercase and uppercase letters allowed * Numbers, underscore, hyphen and dot allowed - * @ cannot be at the start or end + * @ cannot be at the start or end and only one allowed ____________________________________________________________ ____________________________________________________________ @@ -437,9 +437,9 @@ ____________________________________________________________ ____________________________________________________________ The name is not correctly formatted, Rules for name : - * Uppercase and lowercase letters - * Spaces - * No numbers or special characters + * Uppercase and lowercase letters allowed + * Spaces, fullstops, apostrophes and slashes allowed + * No numbers or other special characters * Cannot be "null" ____________________________________________________________ @@ -545,9 +545,9 @@ ____________________________________________________________ ____________________________________________________________ The email id is not correctly formatted, Rules for email id : - * Lowercase letters only + * Lowercase and uppercase letters allowed * Numbers, underscore, hyphen and dot allowed - * @ cannot be at the start or end + * @ cannot be at the start or end and only one allowed ____________________________________________________________ ____________________________________________________________ @@ -564,9 +564,9 @@ ____________________________________________________________ ____________________________________________________________ The name is not correctly formatted, Rules for name : - * Uppercase and lowercase letters - * Spaces - * No numbers or special characters + * Uppercase and lowercase letters allowed + * Spaces, fullstops, apostrophes and slashes allowed + * No numbers or other special characters * Cannot be "null" ____________________________________________________________ diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index 0d442c31ce..56c33d3cef 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -108,9 +108,9 @@ ____________________________________________________________ ____________________________________________________________ The email id is not correctly formatted, Rules for email id : - * Lowercase letters only + * Lowercase and uppercase letters allowed * Numbers, underscore, hyphen and dot allowed - * @ cannot be at the start or end + * @ cannot be at the start or end and only one allowed ____________________________________________________________ ____________________________________________________________ @@ -437,9 +437,9 @@ ____________________________________________________________ ____________________________________________________________ The name is not correctly formatted, Rules for name : - * Uppercase and lowercase letters - * Spaces - * No numbers or special characters + * Uppercase and lowercase letters allowed + * Spaces, fullstops, apostrophes and slashes allowed + * No numbers or other special characters * Cannot be "null" ____________________________________________________________ @@ -545,9 +545,9 @@ ____________________________________________________________ ____________________________________________________________ The email id is not correctly formatted, Rules for email id : - * Lowercase letters only + * Lowercase and uppercase letters allowed * Numbers, underscore, hyphen and dot allowed - * @ cannot be at the start or end + * @ cannot be at the start or end and only one allowed ____________________________________________________________ ____________________________________________________________ @@ -564,9 +564,9 @@ ____________________________________________________________ ____________________________________________________________ The name is not correctly formatted, Rules for name : - * Uppercase and lowercase letters - * Spaces - * No numbers or special characters + * Uppercase and lowercase letters allowed + * Spaces, fullstops, apostrophes and slashes allowed + * No numbers or other special characters * Cannot be "null" ____________________________________________________________ diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 0d442c31ce..56c33d3cef 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -108,9 +108,9 @@ ____________________________________________________________ ____________________________________________________________ The email id is not correctly formatted, Rules for email id : - * Lowercase letters only + * Lowercase and uppercase letters allowed * Numbers, underscore, hyphen and dot allowed - * @ cannot be at the start or end + * @ cannot be at the start or end and only one allowed ____________________________________________________________ ____________________________________________________________ @@ -437,9 +437,9 @@ ____________________________________________________________ ____________________________________________________________ The name is not correctly formatted, Rules for name : - * Uppercase and lowercase letters - * Spaces - * No numbers or special characters + * Uppercase and lowercase letters allowed + * Spaces, fullstops, apostrophes and slashes allowed + * No numbers or other special characters * Cannot be "null" ____________________________________________________________ @@ -545,9 +545,9 @@ ____________________________________________________________ ____________________________________________________________ The email id is not correctly formatted, Rules for email id : - * Lowercase letters only + * Lowercase and uppercase letters allowed * Numbers, underscore, hyphen and dot allowed - * @ cannot be at the start or end + * @ cannot be at the start or end and only one allowed ____________________________________________________________ ____________________________________________________________ @@ -564,9 +564,9 @@ ____________________________________________________________ ____________________________________________________________ The name is not correctly formatted, Rules for name : - * Uppercase and lowercase letters - * Spaces - * No numbers or special characters + * Uppercase and lowercase letters allowed + * Spaces, fullstops, apostrophes and slashes allowed + * No numbers or other special characters * Cannot be "null" ____________________________________________________________ From 4678ad144f59d39763bcca385de6c3678312ce7e Mon Sep 17 00:00:00 2001 From: lezong Date: Sun, 7 Nov 2021 17:19:47 +0800 Subject: [PATCH 714/756] JavaDocs for AddPersonalContactParser --- .../seedu/command/DeleteContactCommand.java | 2 +- .../seedu/command/PersonalContactCommand.java | 3 + .../parser/AddPersonalContactParser.java | 131 +++++++++++++++++- 3 files changed, 134 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/command/DeleteContactCommand.java b/src/main/java/seedu/command/DeleteContactCommand.java index 986d429c23..4acacd04dd 100644 --- a/src/main/java/seedu/command/DeleteContactCommand.java +++ b/src/main/java/seedu/command/DeleteContactCommand.java @@ -31,7 +31,7 @@ public int getContactIndex() { * executing any deletion of a contact. * * @throws IndexOutOfBoundsException If index given in the DeleteContactCommand by user - * is outside the size of the Contact List. + * is outside the size of the Contact List. */ private void deleteSelectedContact() throws IndexOutOfBoundsException { // throws IndexOutOfBoundsException if index is outside of the range diff --git a/src/main/java/seedu/command/PersonalContactCommand.java b/src/main/java/seedu/command/PersonalContactCommand.java index 27e90f8b50..8eddd826cb 100644 --- a/src/main/java/seedu/command/PersonalContactCommand.java +++ b/src/main/java/seedu/command/PersonalContactCommand.java @@ -3,6 +3,9 @@ import seedu.ui.TextUi; public class PersonalContactCommand extends Command { + /** + * This method executes the process to view details of the personal contact. + */ public void execute() { TextUi.viewPersonalContactMessage(this.personalContact); } diff --git a/src/main/java/seedu/parser/AddPersonalContactParser.java b/src/main/java/seedu/parser/AddPersonalContactParser.java index 10a0f42762..41ba36e64a 100644 --- a/src/main/java/seedu/parser/AddPersonalContactParser.java +++ b/src/main/java/seedu/parser/AddPersonalContactParser.java @@ -20,6 +20,11 @@ public AddPersonalContactParser() { personalContact = new Contact(null, null, null, null, null, null); } + /** + * This method is used to start the process of welcoming the user + * and prompting them for their contact details when they first + * use ConTech app. + */ public void collectPersonalDetails() { TextUi.welcomeMessage(); parsePersonalName(true); @@ -33,8 +38,13 @@ public void collectPersonalDetails() { TextUi.finishSetUpMessage(); } + /** + * This method is used to restart the process of collecting the + * user's contact details if any of the data in the personal contact + * file becomes invalid or lost, and cannot be loaded. + */ public void recallPersonalDetails() { - String userConfirmation = UserInputTextUi.getUserConfirmation(); + UserInputTextUi.getUserConfirmation(); parsePersonalName(false); parsePersonalGithubUsername(); parsePersonalTelegramUsername(); @@ -43,6 +53,15 @@ public void recallPersonalDetails() { parsePersonalLinkedinUsername(); } + /** + * This method is used to obtain the user's name as an input, and then + * parses it as the personalContact's name field. It checks if the name given + * is in a valid format, and if it is not, this method will continue + * to prompt the user until a valid name is given and parses it. + * + * @param isFirstTime boolean to check if it is the user's first time + * running the application + */ private void parsePersonalName(boolean isFirstTime) { boolean isValidDetail = false; TextUi.promptPersonalNameMessage(isFirstTime); @@ -59,6 +78,13 @@ private void parsePersonalName(boolean isFirstTime) { } while (!isValidDetail); } + /** + * This method is used to obtain the user's Github username as an input, + * and then parses it as the personalContact's Github username field. It checks + * if the username given is in a valid format, and if it is not, this method + * will continue to prompt the user, until a valid username is given and + * parses it. + */ private void parsePersonalGithubUsername() { boolean isValidDetail = false; TextUi.promptPersonalGithubUsernameMessage(); @@ -73,6 +99,15 @@ private void parsePersonalGithubUsername() { } while (!isValidDetail); } + /** + * This method is used to check the validity of the Github username given + * by the user. Inputs that are blank or adhere to the Github username + * restrictions are allowed. + * + * @param userInput String that user has input + * @return boolean to determine if Github username is valid + * @throws InvalidGithubUsernameException If input does not adhere to the Github username restrictions + */ private boolean checkGithubValidity(String userInput) throws InvalidGithubUsernameException { if (userInput.isEmpty()) { return true; @@ -82,6 +117,12 @@ private boolean checkGithubValidity(String userInput) throws InvalidGithubUserna return true; } + /** + * This method is used to set personalContact Github username field. NULL + * is set for blank inputs. + * + * @param userInput String that user has input + */ private void setParsedGithubUsername(String userInput) { if (userInput.isEmpty()) { this.personalContact.setGithub(null); @@ -90,6 +131,13 @@ private void setParsedGithubUsername(String userInput) { } } + /** + * This method is used to obtain the user's Telegram username as an input, + * and then parses it as the personalContact's Telegram username field. It checks + * if the username given is in a valid format, and if it is not, this method + * will continue to prompt the user, until a valid username is given and + * parses it. + */ private void parsePersonalTelegramUsername() { boolean isValidDetail = false; TextUi.promptPersonalTelegramUsernameMessage(); @@ -104,6 +152,15 @@ private void parsePersonalTelegramUsername() { } while (!isValidDetail); } + /** + * This method is used to check the validity of the Telegram username given + * by the user. Inputs that are blank or adhere to the Telegram username + * restrictions are allowed. + * + * @param userInput String that user has input + * @return boolean to determine if Telegram username is valid + * @throws InvalidTelegramUsernameException If input does not adhere to the Telegram username restrictions + */ private boolean checkTelegramValidity(String userInput) throws InvalidTelegramUsernameException { if (userInput.isEmpty()) { return true; @@ -113,6 +170,12 @@ private boolean checkTelegramValidity(String userInput) throws InvalidTelegramUs return true; } + /** + * This method is used to set personalContact Telegram username field. NULL + * is set for blank inputs. + * + * @param userInput String that user has input + */ private void setParsedTelegramUsername(String userInput) { if (userInput.isEmpty()) { this.personalContact.setTelegram(null); @@ -121,6 +184,13 @@ private void setParsedTelegramUsername(String userInput) { } } + /** + * This method is used to obtain the user's Twitter username as an input, + * and then parses it as the personalContact's Twitter username field. It checks + * if the username given is in a valid format, and if it is not, this method + * will continue to prompt the user, until a valid username is given and + * parses it. + */ private void parsePersonalTwitterUsername() { boolean isValidDetail = false; TextUi.promptPersonalTwitterUsernameMessage(); @@ -135,6 +205,15 @@ private void parsePersonalTwitterUsername() { } while (!isValidDetail); } + /** + * This method is used to check the validity of the Twitter username given + * by the user. Inputs that are blank or adhere to the Twitter username + * restrictions are allowed. + * + * @param userInput String that user has input + * @return boolean to determine if Twitter username is valid + * @throws InvalidTwitterUsernameException If input does not adhere to the Twitter username restrictions + */ private boolean checkTwitterValidity(String userInput) throws InvalidTwitterUsernameException { if (userInput.isEmpty()) { return true; @@ -144,6 +223,12 @@ private boolean checkTwitterValidity(String userInput) throws InvalidTwitterUser return true; } + /** + * This method is used to set personalContact Twitter username field. NULL + * is set for blank inputs. + * + * @param userInput String that user has input + */ private void setParsedTwitterUsername(String userInput) { if (userInput.isEmpty()) { this.personalContact.setTwitter(null); @@ -152,6 +237,13 @@ private void setParsedTwitterUsername(String userInput) { } } + /** + * This method is used to obtain the user's email address as an input, + * and then parses it as the personalContact's email address field. It checks + * if the email address given is in a valid format, and if it is not, + * this method will continue to prompt the user, until a valid email address + * is given and parses it. + */ private void parsePersonalEmailAddress() { boolean isValidDetail = false; TextUi.promptPersonalEmailMessage(); @@ -166,6 +258,15 @@ private void parsePersonalEmailAddress() { } while (!isValidDetail); } + /** + * This method is used to check the validity of the email address given + * by the user. Inputs that are blank or adhere to the email address + * restrictions are allowed. + * + * @param userInput String that user has input + * @return boolean to determine if email address is valid + * @throws InvalidEmailException If input does not adhere to the email address restrictions + */ private boolean checkEmailValidity(String userInput) throws InvalidEmailException { if (userInput.isEmpty()) { return true; @@ -175,6 +276,12 @@ private boolean checkEmailValidity(String userInput) throws InvalidEmailExceptio return true; } + /** + * This method is used to set personalContact email address field. NULL + * is set for blank inputs. + * + * @param userInput String that user has input + */ private void setParsedEmailAddress(String userInput) { if (userInput.isEmpty()) { this.personalContact.setEmail(null); @@ -183,6 +290,13 @@ private void setParsedEmailAddress(String userInput) { } } + /** + * This method is used to obtain the user's LinkedIn username as an input, + * and then parses it as the personalContact's LinkedIn username field. It checks + * if the username given is in a valid format, and if it is not, this method + * will continue to prompt the user, until a valid username is given and + * parses it. + */ private void parsePersonalLinkedinUsername() { boolean isValidDetail = false; TextUi.promptPersonalLinkedinUsernameMessage(); @@ -197,6 +311,15 @@ private void parsePersonalLinkedinUsername() { } while (!isValidDetail); } + /** + * This method is used to check the validity of the LinkedIn username given + * by the user. Inputs that are blank or adhere to the LinkedIn username + * restrictions are allowed. + * + * @param userInput String that user has input + * @return boolean to determine if LinkedIn username is valid + * @throws InvalidEmailException If input does not adhere to the LinkedIn username restrictions + */ private boolean checkLinkedinValidity(String userInput) throws InvalidLinkedinUsernameException { if (userInput.isEmpty()) { return true; @@ -206,6 +329,12 @@ private boolean checkLinkedinValidity(String userInput) throws InvalidLinkedinUs return true; } + /** + * This method is used to set personalContact LinkedIn username field. NULL + * is set for blank inputs. + * + * @param userInput String that user has input + */ private void setParsedLinkedinUsername(String userInput) { if (userInput.isEmpty()) { this.personalContact.setLinkedin(null); From 5563cf3f2d2b6e848bb6e669cc18e6856e623d8d Mon Sep 17 00:00:00 2001 From: lezong Date: Sun, 7 Nov 2021 17:29:25 +0800 Subject: [PATCH 715/756] JavaDocs for IndexParser --- src/main/java/seedu/parser/IndexParser.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/java/seedu/parser/IndexParser.java b/src/main/java/seedu/parser/IndexParser.java index d3cfb4009d..a6d91ced76 100644 --- a/src/main/java/seedu/parser/IndexParser.java +++ b/src/main/java/seedu/parser/IndexParser.java @@ -15,6 +15,17 @@ public class IndexParser { private static final int REMOVE_ALL_INDEX = -2; private static final String numbers = "^-?\\d+$"; + /** + * This method is used to obtain the contact index from the user's input. It + * is used when the user specifies a command with a contact index. This method + * will attempt to parse a contact index in a string and return them as an integer. + * If "me" or "all" is given as the index, it will return -1 or -2 respectively. + * + * @param userInput String that user has input + * @return Contact index obtained as an integer from the user input string + * @throws NumberFormatException If user gives a non-number as the contact index, other than "me" or "all" + * @throws MissingIndexException If user does not give any contact index + */ public static int getIndexFromInput(String userInput) throws NumberFormatException, MissingIndexException { //split user input into 2 strings: command word string and index string From fe565b58d15d1a57abc9a5daac2c93a2dac01cb2 Mon Sep 17 00:00:00 2001 From: lezong Date: Sun, 7 Nov 2021 17:58:22 +0800 Subject: [PATCH 716/756] JavaDocs for MainParser --- src/main/java/seedu/parser/MainParser.java | 26 ++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 1d9ae2881c..c702da1335 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -71,11 +71,24 @@ public Command parseCommand(String userInput) { return command; } + /** + * This method is used to obtain the command word from the user input. + * + * @param userInput String that user has input + * @return command word string in user input + */ public String getCommandWord(String userInput) { String[] destructuredInputs = userInput.split(" ", ISOLATE_COMD_WORD); return destructuredInputs[COMD_WORD_INDEX]; } + /** + * This method differentiates the command given by user into either manipulation, + * query or control type, and then returns the type. + * + * @param userInput String that user has input + * @return command type of the command in user input + */ public CommandType getCommandType(String userInput) { String commandWord = getCommandWord(userInput); CommandType commandType; @@ -262,6 +275,13 @@ private Command parseViewContact(String userInput) { } //@@author lezongmun + /** + * This method returns a DeleteContactCommand after parsing the user's input if the + * specified input command was for deletion. + * + * @param userInput String that user has input + * @return DeleteContactCommand object as a Command type + */ private Command parseDeleteContact(String userInput) { try { boolean[] hasDeletedDetail = deleteContactParser.hasDeletedDetail(userInput); @@ -294,6 +314,12 @@ private Command parseSearchCommand(String userInput) { } //@author lezongmun + /** + * This method returns a PersonalContactCommand after parsing the user's input if the specified + * input command was for viewing personal contact. + * + * @return PersonalContactCommand object as a Command type + */ private Command parsePersonalContact() { return new PersonalContactCommand(); } From 54f69e28e48ae2017942ff2cd20b96631296b7b4 Mon Sep 17 00:00:00 2001 From: lezong Date: Sun, 7 Nov 2021 18:14:56 +0800 Subject: [PATCH 717/756] JavaDocs for ContactsDecoder --- .../java/seedu/storage/ContactsDecoder.java | 30 +++++++++++++++---- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index 9654aeebd3..f00c5db98b 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -52,25 +52,43 @@ public ContactList readContacts(File contactFile, String contactFilePath) throws return updatedContactList; } - //@@author lezongmun + //@author lezongmun + /** + * This method returns the personal contact after parsing inputs from the specified + * personal contact file in local storage. + * + * @param personalContactFile Specified file to be read + * @return Personal contact of user + * @throws FileErrorException If the program faces issues relating to local storage + */ public Contact readPersonalContact(File personalContactFile) throws FileErrorException { - Contact personalContact = new Contact(null, null, null, null, null, null); + Contact nullContact = new Contact(null, null, null, null, null, null); try { Scanner fileScanner = new Scanner(personalContactFile); if (fileScanner.hasNext()) { String contactText = fileScanner.nextLine(); - personalContact = decodePersonalContact(contactText, personalContact); + Contact personalContact = decodePersonalContact(contactText); + return personalContact; } } catch (FileNotFoundException e) { throw new FileErrorException(); } - return personalContact; + return nullContact; } //@author lezongmun - private Contact decodePersonalContact(String contactText, Contact contact) { - Contact personalContact = contact; + /** + * This method decodes a string read from the personal contact file and + * attempts to parse it as a contact. If there are errors in the file, + * and the data cannot be loaded, user's personal contact details will + * be prompted to create a new personal contact + * + * @param contactText String read from the file + * @return personal contact with details read from file + */ + private Contact decodePersonalContact(String contactText) { + Contact personalContact = new Contact(null, null, null, null, null, null); try { String[] compiledDetails = decodeDetails(contactText); String contactName = compiledDetails[DetailType.NAME.getIndex()]; From dff0dc261501317f3856af894a834e2348ae8ad1 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Sun, 7 Nov 2021 18:21:47 +0800 Subject: [PATCH 718/756] Update with requested changes --- src/main/java/seedu/ui/ExceptionTextUi.java | 3 ++- text-ui-test/ACTUAL.TXT | 6 ++++-- text-ui-test/EXPECTED-UNIX.TXT | 6 ++++-- text-ui-test/EXPECTED.TXT | 6 ++++-- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index 508e67a9f7..e9352e100f 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -376,7 +376,8 @@ public static void invalidEmailInput() { + "Rules for email id :\n" + " * Lowercase and uppercase letters allowed\n" + " * Numbers, underscore, hyphen and dot allowed\n" - + " * @ cannot be at the start or end and only one allowed"; + + " * Only one @ character allowed\n" + + " * Email cannot start or end with a symbol"; printDoubleLineMessage(message); } diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index 56c33d3cef..5a1627724d 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -110,7 +110,8 @@ The email id is not correctly formatted, Rules for email id : * Lowercase and uppercase letters allowed * Numbers, underscore, hyphen and dot allowed - * @ cannot be at the start or end and only one allowed + * Only one @ character allowed + * Email cannot start or end with a symbol ____________________________________________________________ ____________________________________________________________ @@ -547,7 +548,8 @@ The email id is not correctly formatted, Rules for email id : * Lowercase and uppercase letters allowed * Numbers, underscore, hyphen and dot allowed - * @ cannot be at the start or end and only one allowed + * Only one @ character allowed + * Email cannot start or end with a symbol ____________________________________________________________ ____________________________________________________________ diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index 56c33d3cef..5a1627724d 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -110,7 +110,8 @@ The email id is not correctly formatted, Rules for email id : * Lowercase and uppercase letters allowed * Numbers, underscore, hyphen and dot allowed - * @ cannot be at the start or end and only one allowed + * Only one @ character allowed + * Email cannot start or end with a symbol ____________________________________________________________ ____________________________________________________________ @@ -547,7 +548,8 @@ The email id is not correctly formatted, Rules for email id : * Lowercase and uppercase letters allowed * Numbers, underscore, hyphen and dot allowed - * @ cannot be at the start or end and only one allowed + * Only one @ character allowed + * Email cannot start or end with a symbol ____________________________________________________________ ____________________________________________________________ diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 56c33d3cef..5a1627724d 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -110,7 +110,8 @@ The email id is not correctly formatted, Rules for email id : * Lowercase and uppercase letters allowed * Numbers, underscore, hyphen and dot allowed - * @ cannot be at the start or end and only one allowed + * Only one @ character allowed + * Email cannot start or end with a symbol ____________________________________________________________ ____________________________________________________________ @@ -547,7 +548,8 @@ The email id is not correctly formatted, Rules for email id : * Lowercase and uppercase letters allowed * Numbers, underscore, hyphen and dot allowed - * @ cannot be at the start or end and only one allowed + * Only one @ character allowed + * Email cannot start or end with a symbol ____________________________________________________________ ____________________________________________________________ From fdd50c829d2581aaf2d078986d01e56b647485ee Mon Sep 17 00:00:00 2001 From: lezong Date: Sun, 7 Nov 2021 18:24:31 +0800 Subject: [PATCH 719/756] JavaDocs for Storage --- .../java/seedu/storage/ContactsDecoder.java | 4 ++-- .../java/seedu/storage/ContactsEncoder.java | 9 +++++++- src/main/java/seedu/storage/Storage.java | 21 +++++++++++++++++++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index f00c5db98b..a728e98158 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -54,7 +54,7 @@ public ContactList readContacts(File contactFile, String contactFilePath) throws //@author lezongmun /** - * This method returns the personal contact after parsing inputs from the specified + * Returns the personal contact after parsing inputs from the specified * personal contact file in local storage. * * @param personalContactFile Specified file to be read @@ -79,7 +79,7 @@ public Contact readPersonalContact(File personalContactFile) //@author lezongmun /** - * This method decodes a string read from the personal contact file and + * Decodes a string read from the personal contact file and * attempts to parse it as a contact. If there are errors in the file, * and the data cannot be loaded, user's personal contact details will * be prompted to create a new personal contact diff --git a/src/main/java/seedu/storage/ContactsEncoder.java b/src/main/java/seedu/storage/ContactsEncoder.java index 678cceeba9..e94110d653 100644 --- a/src/main/java/seedu/storage/ContactsEncoder.java +++ b/src/main/java/seedu/storage/ContactsEncoder.java @@ -13,7 +13,14 @@ * This class facilitates the saving of the user's contact list to their local storage file. */ public class ContactsEncoder { + //@@author lezongmun + /** + * This method saves the personal contact to a specified file path. + * @param contactFilePath Destination for person contact to be saved + * @param personalContact Personal contact to be saved + * @throws FileErrorException If there is an error writing to the file destination + */ public void savePersonalContact(String contactFilePath, Contact personalContact) throws FileErrorException { try { FileWriter fileWriter = new FileWriter(contactFilePath); @@ -30,7 +37,7 @@ public void savePersonalContact(String contactFilePath, Contact personalContact) * Saves a specified ContactList to a specified file path. * @param contactFilePath Destination for the contact list to be saved * @param contactList Contact list to be saved - * @throws FileErrorException If there an error writing to the file destination + * @throws FileErrorException If there is an error writing to the file destination */ public void saveContacts(String contactFilePath, ContactList contactList) throws FileErrorException { try { diff --git a/src/main/java/seedu/storage/Storage.java b/src/main/java/seedu/storage/Storage.java index 160fbf243a..4395b32856 100644 --- a/src/main/java/seedu/storage/Storage.java +++ b/src/main/java/seedu/storage/Storage.java @@ -31,6 +31,12 @@ public Storage(String contactFilePath, String personalContactFilePath, ContactsD } //@@author lezongmun + /** + * Checks if there already exists a local storage file, and creates one if + * it does not exist. + * @return True if local storage file exists + * @throws FileErrorException If there are errors writing or checking for local storage files + */ private boolean hasExistingPersonalContactFile() throws FileErrorException { try { if (!personalContactFile.exists()) { @@ -47,6 +53,12 @@ private boolean hasExistingPersonalContactFile() throws FileErrorException { } //@@author lezongmun + + /** + * Checks if there exists an empty local storage file. + * + * @return True if empty local storage file exists + */ private boolean hasEmptyExistingPersonalContactFile() { return personalContactFile.exists() && personalContactFile.length() == 0; } @@ -87,6 +99,15 @@ public ContactList loadExistingContacts() throws FileErrorException { } //@@author lezongmun + + /** + * Returns a personal contact by attempting to retrieve any existing personal contact data + * from user's local storage file. If there does not exist any existing personal contact data, + * a new personal contact will be created and saved into the local storage. + * + * @return Contact decoded personal contact from the local storage file + * @throws FileErrorException If there are errors reading from local storage file + */ public Contact loadExistingPersonalContact() throws FileErrorException { if (!hasExistingPersonalContactFile() || hasEmptyExistingPersonalContactFile()) { // get new contact's name From 6edbe7f1967ec6566972d93bd109a251bdcce098 Mon Sep 17 00:00:00 2001 From: lezong Date: Sun, 7 Nov 2021 18:36:19 +0800 Subject: [PATCH 720/756] Minor edits to javadocs --- .../parser/AddPersonalContactParser.java | 30 +++++++++---------- src/main/java/seedu/parser/IndexParser.java | 4 +-- src/main/java/seedu/parser/MainParser.java | 19 ++++++------ .../java/seedu/storage/ContactsDecoder.java | 10 +++---- src/main/java/seedu/storage/Storage.java | 1 - 5 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/main/java/seedu/parser/AddPersonalContactParser.java b/src/main/java/seedu/parser/AddPersonalContactParser.java index 41ba36e64a..5c3834e367 100644 --- a/src/main/java/seedu/parser/AddPersonalContactParser.java +++ b/src/main/java/seedu/parser/AddPersonalContactParser.java @@ -100,12 +100,12 @@ private void parsePersonalGithubUsername() { } /** - * This method is used to check the validity of the Github username given - * by the user. Inputs that are blank or adhere to the Github username + * Returns a boolean to determine if Github username given by the user + * is valid. Inputs that are blank or adhere to the Github username * restrictions are allowed. * * @param userInput String that user has input - * @return boolean to determine if Github username is valid + * @return boolean True if Github username is valid or blank * @throws InvalidGithubUsernameException If input does not adhere to the Github username restrictions */ private boolean checkGithubValidity(String userInput) throws InvalidGithubUsernameException { @@ -153,12 +153,12 @@ private void parsePersonalTelegramUsername() { } /** - * This method is used to check the validity of the Telegram username given - * by the user. Inputs that are blank or adhere to the Telegram username + * Returns a boolean to determine if Telegram username given by the user + * is valid. Inputs that are blank or adhere to the Telegram username * restrictions are allowed. * * @param userInput String that user has input - * @return boolean to determine if Telegram username is valid + * @return boolean True if Telegram username is valid or blank * @throws InvalidTelegramUsernameException If input does not adhere to the Telegram username restrictions */ private boolean checkTelegramValidity(String userInput) throws InvalidTelegramUsernameException { @@ -206,12 +206,12 @@ private void parsePersonalTwitterUsername() { } /** - * This method is used to check the validity of the Twitter username given - * by the user. Inputs that are blank or adhere to the Twitter username + * Returns a boolean to determine if Twitter username given by the user + * is valid. Inputs that are blank or adhere to the Twitter username * restrictions are allowed. * * @param userInput String that user has input - * @return boolean to determine if Twitter username is valid + * @return boolean True if Twitter username is valid or blank * @throws InvalidTwitterUsernameException If input does not adhere to the Twitter username restrictions */ private boolean checkTwitterValidity(String userInput) throws InvalidTwitterUsernameException { @@ -259,12 +259,12 @@ private void parsePersonalEmailAddress() { } /** - * This method is used to check the validity of the email address given - * by the user. Inputs that are blank or adhere to the email address + * Returns a boolean to determine if email address given by the user + * is valid. Inputs that are blank or adhere to the email address * restrictions are allowed. * * @param userInput String that user has input - * @return boolean to determine if email address is valid + * @return boolean True if email address is valid or blank * @throws InvalidEmailException If input does not adhere to the email address restrictions */ private boolean checkEmailValidity(String userInput) throws InvalidEmailException { @@ -312,12 +312,12 @@ private void parsePersonalLinkedinUsername() { } /** - * This method is used to check the validity of the LinkedIn username given - * by the user. Inputs that are blank or adhere to the LinkedIn username + * Returns a boolean to determine if LinkedIn username given by the user + * is valid. Inputs that are blank or adhere to the LinkedIn username * restrictions are allowed. * * @param userInput String that user has input - * @return boolean to determine if LinkedIn username is valid + * @return boolean True if LinkedIn username is valid or blank * @throws InvalidEmailException If input does not adhere to the LinkedIn username restrictions */ private boolean checkLinkedinValidity(String userInput) throws InvalidLinkedinUsernameException { diff --git a/src/main/java/seedu/parser/IndexParser.java b/src/main/java/seedu/parser/IndexParser.java index a6d91ced76..bef7d4ed37 100644 --- a/src/main/java/seedu/parser/IndexParser.java +++ b/src/main/java/seedu/parser/IndexParser.java @@ -16,13 +16,13 @@ public class IndexParser { private static final String numbers = "^-?\\d+$"; /** - * This method is used to obtain the contact index from the user's input. It + * Returns the contact index obtained as an integer from the user input string. It * is used when the user specifies a command with a contact index. This method * will attempt to parse a contact index in a string and return them as an integer. * If "me" or "all" is given as the index, it will return -1 or -2 respectively. * * @param userInput String that user has input - * @return Contact index obtained as an integer from the user input string + * @return int Contact index obtained from the user input string * @throws NumberFormatException If user gives a non-number as the contact index, other than "me" or "all" * @throws MissingIndexException If user does not give any contact index */ diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index c702da1335..491cdae603 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -72,10 +72,10 @@ public Command parseCommand(String userInput) { } /** - * This method is used to obtain the command word from the user input. + * Returns the command word string given in the user input. * * @param userInput String that user has input - * @return command word string in user input + * @return String command word in user input */ public String getCommandWord(String userInput) { String[] destructuredInputs = userInput.split(" ", ISOLATE_COMD_WORD); @@ -83,11 +83,12 @@ public String getCommandWord(String userInput) { } /** - * This method differentiates the command given by user into either manipulation, - * query or control type, and then returns the type. + * Returns the command type of the command given in the user input. This method + * differentiates the command given by user into either manipulation, query or + * control type. * * @param userInput String that user has input - * @return command type of the command in user input + * @return CommandType command type of the command given in user input */ public CommandType getCommandType(String userInput) { String commandWord = getCommandWord(userInput); @@ -276,11 +277,11 @@ private Command parseViewContact(String userInput) { //@@author lezongmun /** - * This method returns a DeleteContactCommand after parsing the user's input if the + * Returns a DeleteContactCommand after parsing the user's input if the * specified input command was for deletion. * * @param userInput String that user has input - * @return DeleteContactCommand object as a Command type + * @return Command DeleteContactCommand */ private Command parseDeleteContact(String userInput) { try { @@ -315,10 +316,10 @@ private Command parseSearchCommand(String userInput) { //@author lezongmun /** - * This method returns a PersonalContactCommand after parsing the user's input if the specified + * Returns a PersonalContactCommand after parsing the user's input if the specified * input command was for viewing personal contact. * - * @return PersonalContactCommand object as a Command type + * @return Command PersonalContactCommand */ private Command parsePersonalContact() { return new PersonalContactCommand(); diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index a728e98158..e4f09a5ea5 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -79,13 +79,13 @@ public Contact readPersonalContact(File personalContactFile) //@author lezongmun /** - * Decodes a string read from the personal contact file and - * attempts to parse it as a contact. If there are errors in the file, - * and the data cannot be loaded, user's personal contact details will - * be prompted to create a new personal contact + * Returns the personal contact created from decoding a string read from + * the personal contact file. If there are errors in the file, and + * the data cannot be loaded, user's personal contact details will + * be collected to create a new personal contact * * @param contactText String read from the file - * @return personal contact with details read from file + * @return Contact personal contact with details read from file */ private Contact decodePersonalContact(String contactText) { Contact personalContact = new Contact(null, null, null, null, null, null); diff --git a/src/main/java/seedu/storage/Storage.java b/src/main/java/seedu/storage/Storage.java index 4395b32856..b57cd1dfab 100644 --- a/src/main/java/seedu/storage/Storage.java +++ b/src/main/java/seedu/storage/Storage.java @@ -99,7 +99,6 @@ public ContactList loadExistingContacts() throws FileErrorException { } //@@author lezongmun - /** * Returns a personal contact by attempting to retrieve any existing personal contact data * from user's local storage file. If there does not exist any existing personal contact data, From 6b6cc30d229998383a3b8dd69c2f787301e68b21 Mon Sep 17 00:00:00 2001 From: ng-andre Date: Sun, 7 Nov 2021 19:18:14 +0800 Subject: [PATCH 721/756] Add Javadocs for edit contact parser --- .../java/seedu/parser/EditContactParser.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/main/java/seedu/parser/EditContactParser.java b/src/main/java/seedu/parser/EditContactParser.java index 10948c8c20..525b407edc 100644 --- a/src/main/java/seedu/parser/EditContactParser.java +++ b/src/main/java/seedu/parser/EditContactParser.java @@ -16,6 +16,22 @@ public class EditContactParser extends ContactParser { public static final String BUFFER = " "; + /** + * Takes in the userInput and returns a String array of the contact's fields to be edited. + * @param userInput The command input from the user in full. + * @return String array of size 6 containing user details to be edited, or null if field is not specified. + * @throws InvalidFlagException if the flag specified is not one of the six flags allowed. + * @throws MissingDetailException if there is a flag specified but no detail specified + * @throws ForbiddenDetailException if the detail specified contains illegal Strings eg. null + * @throws InvalidNameException if the name contains illegal characters + * @throws InvalidGithubUsernameException if the Github username contains illegal characters + * @throws InvalidTelegramUsernameException if the Telegram username contains illegal characters + * @throws InvalidLinkedinUsernameException if the LinkedIn username contains illegal characters + * @throws InvalidTwitterUsernameException if the Twitter handle contains illegal characters + * @throws InvalidEmailException if the email contains illegal characters + * @throws MissingArgEditException if the userInput is missing arguments such as index + * @throws DuplicateDetailException if the userInput has duplicate flags + */ public String[] parseContactDetails(String userInput) throws InvalidFlagException, MissingDetailException, ForbiddenDetailException, InvalidNameException, InvalidGithubUsernameException, InvalidTelegramUsernameException, InvalidLinkedinUsernameException, From 3edd3dca5513440abb52da83e70af56bfea086ca Mon Sep 17 00:00:00 2001 From: ng-andre Date: Sun, 7 Nov 2021 19:31:49 +0800 Subject: [PATCH 722/756] Author updates --- src/main/java/seedu/command/EditContactCommand.java | 2 ++ src/main/java/seedu/parser/EditContactParser.java | 3 ++- src/main/java/seedu/parser/IndexParser.java | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index f135913e5b..43371e5c5f 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -1,3 +1,5 @@ +//@@author ng-andre + package seedu.command; import seedu.contact.Contact; diff --git a/src/main/java/seedu/parser/EditContactParser.java b/src/main/java/seedu/parser/EditContactParser.java index 525b407edc..c5ff097ef8 100644 --- a/src/main/java/seedu/parser/EditContactParser.java +++ b/src/main/java/seedu/parser/EditContactParser.java @@ -1,3 +1,5 @@ +//@@author ng-andre + package seedu.parser; import seedu.exception.DuplicateDetailException; @@ -12,7 +14,6 @@ import seedu.exception.MissingArgEditException; import seedu.exception.MissingDetailException; -//@@author ng-andre public class EditContactParser extends ContactParser { public static final String BUFFER = " "; diff --git a/src/main/java/seedu/parser/IndexParser.java b/src/main/java/seedu/parser/IndexParser.java index d3cfb4009d..ab467574da 100644 --- a/src/main/java/seedu/parser/IndexParser.java +++ b/src/main/java/seedu/parser/IndexParser.java @@ -1,4 +1,4 @@ -//@@author lezongmun +//@@author ng-andre package seedu.parser; From 4a4d20e40374e9c24c1f480c4938ab7f56e2e8e1 Mon Sep 17 00:00:00 2001 From: ng-andre Date: Sun, 7 Nov 2021 19:32:50 +0800 Subject: [PATCH 723/756] Add javadoc for main parser --- src/main/java/seedu/parser/MainParser.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 1d9ae2881c..c880eaedab 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -163,9 +163,11 @@ private Command parseQueryCommand(String commandWord, String userInput) { } //@@author marcusbory + /** * Returns an AddContactCommand after parsing the user's input if the specified input command was for adding a * contact. + * * @param userInput String that user has input * @return Command AddContactCommand if the parsing was successful */ @@ -191,6 +193,12 @@ private Command parseAddContact(String userInput) { } } + /** + * Parses the edit command and returns a new command with the required parameters. + * + * @param userInput The command input from the user in full. + * @return new EditContactCommand with the edited details and contact index + */ //@@author ng-andre private Command parseEditContact(String userInput) { // userInput is raw user input try { @@ -243,6 +251,7 @@ private Command parseInvalidDetailCommand(Exception e) { } //@@author ashrafjfr + /** * This method parses the userInput according to the view command. After parsing for the viewedIndex, it will * initialise a new ViewContactCommand. @@ -278,6 +287,12 @@ private Command parseDeleteContact(String userInput) { } } + /** + * Parses the search command and returns a new command with the required parameters. + * + * @param userInput The command input from the user in full. + * @return new SearchContactCommand with query and detailFlag + */ //@@author ng-andre private Command parseSearchCommand(String userInput) { try { From e38e1db21c5ebe9be97c715c710363a1f2fc47ba Mon Sep 17 00:00:00 2001 From: lezong Date: Sun, 7 Nov 2021 20:34:31 +0800 Subject: [PATCH 724/756] PPP --- docs/UserGuide.md | 3 ++- docs/team/lezongmun.md | 14 +++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 6cb76d5768..6f8775c41e 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -432,7 +432,8 @@ marcus,null,null,null,null,null - Additional input after the `import` command will be treated as erroneous input and discarded. - However, there is a limitation that duplicates will not be checked for when performing contact imports. Do import with caution. -- Coming Soon: Duplicate checks for importing contacts will be added in future versions, with more granular controls. + +:date: Coming Soon: Duplicate checks for importing contacts will be added in future versions, with more granular controls. Expected outcome of usage: diff --git a/docs/team/lezongmun.md b/docs/team/lezongmun.md index 68f522e388..86593203a9 100644 --- a/docs/team/lezongmun.md +++ b/docs/team/lezongmun.md @@ -17,7 +17,7 @@ The code written by me (`lezongmun`) can be found [here](https://nus-cs2113-ay21 1. `rm` feature - Feature to allow users to delete selected contacts or all contacts at once from the ConTech Book. 2. `me` feature - - Feature to allow users to view their saved personal contact details. + - Feature to allow users to view and edit their saved personal contact details. 3. Personal Contact System - Creation of personal contact for first time use - Saving of personal contact details using `ContactsEncoder.java` @@ -30,12 +30,20 @@ The code written by me (`lezongmun`) can be found [here](https://nus-cs2113-ay21 ### Contributions to UG - Added documentation for features `me` and `rm` -- Tweaked documentation (formatting, usages, examples) for features with `all` and `me` as inputs +- Updated documentation (command formats, usages, examples) for features with `all` and `me` as inputs ### Contributions to DG - Added implementation details and class diagram for `Storage` system +- Added implementation details for `Command` and `ContactList` system - Added implementation details and sequence diagrams for `rm` feature (delete selected contacts, delete all contacts and delete contact fields) +- Added implementation details for `Index Parser`. ### Team-based tasks - +- Attended weekly meeting sessions with team +- Updated User Guide (UG) and Developer Guide (DG) documentation that were not specific to any feature: + - UG: Reformatted descriptions of the `Command formats` and `Expected outcomes` to make them more consistent + - DG: Standardised descriptions for parts that are more similar +- Regular debugging and testing of the application to find bugs and make sure the app works +- Made general code enhancements by refactoring/abstracting code that was too lengthy to make them more readable +- Updated exceptions and error messages to make them more consistent From b5d8ef14330b904671a2ec7be6db5906dfda05cf Mon Sep 17 00:00:00 2001 From: ng-andre Date: Sun, 7 Nov 2021 20:53:36 +0800 Subject: [PATCH 725/756] Update javadoc for search parser --- .../seedu/parser/SearchContactParser.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/main/java/seedu/parser/SearchContactParser.java b/src/main/java/seedu/parser/SearchContactParser.java index db557a8c2a..71bf42009b 100644 --- a/src/main/java/seedu/parser/SearchContactParser.java +++ b/src/main/java/seedu/parser/SearchContactParser.java @@ -9,6 +9,13 @@ //@@author ng-andre public class SearchContactParser implements ContactDetails { + /** + * Takes in the searchInput and returns a String array of the contact's fields to be edited. + * + * @param searchInput The command input from the user without the command word 'search' + * @return String array of size 6 containing user details to be edited, or null if field is not specified. + * @throws MissingArgSearchException if the searchInput is missing parameters eg query + */ //return only search query as a String public String parseSearchQuery(String searchInput) throws MissingArgSearchException { String[] destructuredInputs = searchInput.trim().split(" ", NUMBER_OF_DETAILS); @@ -23,6 +30,14 @@ public String parseSearchQuery(String searchInput) throws MissingArgSearchExcept return searchInput; } + /** + * Parses the detail flag from searchInput and returns an int representing the flag index. + * + * @param searchInput The command input from the user without the command word 'search' + * @return Integer representing the flag index from the user input + * @throws MissingArgSearchException if the searchInput is missing parameters eg query + * @throws InvalidFlagException if the flag specified is not one of the six flags allowed. + */ public int getDetailFlag(String searchInput) throws MissingArgSearchException, InvalidFlagException { //userInput is not null since searchInput was obtained from getSearchInput if (searchInput.trim().charAt(FLAG_INDEX_IN_DETAILS) == '-') { @@ -39,6 +54,13 @@ public int getDetailFlag(String searchInput) throws MissingArgSearchException, I return DetailType.NAME.getIndex(); //search names } + /** + * Removes the search command word from the userInput. + * + * @param userInput The command input from the user in full. + * @return userInput without the search command word. + * @throws MissingArgSearchException if the searchInput is missing parameters eg query + */ public String getSearchInput(String userInput) throws MissingArgSearchException { //remove the search command String[] destructuredInputs = userInput.trim().split(" ", NUMBER_OF_DETAILS); From c31c7e1f26a643dada6c9c0f2bddfbc5771e40f3 Mon Sep 17 00:00:00 2001 From: lezong Date: Sun, 7 Nov 2021 21:27:15 +0800 Subject: [PATCH 726/756] Fix Storage name null issue --- data/import.txt | 15 +++++++++++++-- src/main/java/seedu/storage/ContactsDecoder.java | 7 +++++++ src/main/java/seedu/storage/Storage.java | 15 ++++++++++++--- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/data/import.txt b/data/import.txt index 3dda6a993b..20058b3084 100644 --- a/data/import.txt +++ b/data/import.txt @@ -1,6 +1,17 @@ ashraf,ashrafjfr,null,null,null,null -lezai,lezongmun,null,null,null,null +null,lezongmun,null,null,null,null andre,null + + marcus,null,null,null,null,null + + badgithub,@@github,null,null,null,null -Le Zong,lezongmun,null,lezongg,null,lezongmun@gmail.com \ No newline at end of file + + + + +Le Zong,lezongmun,null,lezongg,null,lezongmun@gmail.com + + + diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index e4f09a5ea5..d0dbf80e7c 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -149,6 +149,10 @@ private void decodeContact(ContactList contactList, String contactText, int line } } +// private void checkNameNotNull(String name) throws InvalidNameException { +// if (name.equalsIgnoreCase("null")) +// } + /** * Prints the relevant message for invalid details pertaining to the parsed contacts. * @param e Exception that was caught @@ -191,6 +195,9 @@ private String[] decodeDetails(String contactText) throws IndexOutOfBoundsExcept InvalidLinkedinUsernameException, InvalidEmailException { String[] destructuredInputs = contactText.split(SEPARATOR); String[] compiledDetails = new String[NUMBER_OF_FIELDS]; + if (destructuredInputs[0].equals("null")) { + throw new InvalidNameException(); + } for (int i = 0; i < NUMBER_OF_FIELDS; i++) { if (destructuredInputs[i].equals("null")) { compiledDetails[i] = null; diff --git a/src/main/java/seedu/storage/Storage.java b/src/main/java/seedu/storage/Storage.java index b57cd1dfab..20d35e4330 100644 --- a/src/main/java/seedu/storage/Storage.java +++ b/src/main/java/seedu/storage/Storage.java @@ -9,7 +9,9 @@ import seedu.ui.TextUi; import java.io.File; +import java.io.FileNotFoundException; import java.io.IOException; +import java.util.Scanner; public class Storage { public static final String SEPARATOR = ","; @@ -53,14 +55,21 @@ private boolean hasExistingPersonalContactFile() throws FileErrorException { } //@@author lezongmun - /** * Checks if there exists an empty local storage file. * * @return True if empty local storage file exists */ - private boolean hasEmptyExistingPersonalContactFile() { - return personalContactFile.exists() && personalContactFile.length() == 0; + private boolean hasEmptyExistingPersonalContactFile() throws FileErrorException { + try { + Scanner fileScanner = new Scanner(personalContactFile); + if (personalContactFile.exists() && fileScanner.nextLine().trim().isEmpty()) { + return true; + } + return false; + } catch (FileNotFoundException e) { + throw new FileErrorException(); + } } //@@author marcusbory From 7c6d3548ba3a3931d9009292c3c4611814b1a4c5 Mon Sep 17 00:00:00 2001 From: lezong Date: Sun, 7 Nov 2021 21:38:41 +0800 Subject: [PATCH 727/756] Minor edits --- src/main/java/seedu/storage/ContactsDecoder.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index d0dbf80e7c..060c743ceb 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -149,10 +149,6 @@ private void decodeContact(ContactList contactList, String contactText, int line } } -// private void checkNameNotNull(String name) throws InvalidNameException { -// if (name.equalsIgnoreCase("null")) -// } - /** * Prints the relevant message for invalid details pertaining to the parsed contacts. * @param e Exception that was caught From ae30c859c0e1875740db3406858f7ecd82f54b21 Mon Sep 17 00:00:00 2001 From: lezong Date: Sun, 7 Nov 2021 21:48:17 +0800 Subject: [PATCH 728/756] Fix null cases where null is uppercase --- data/import.txt | 2 +- src/main/java/seedu/parser/ContactParser.java | 2 +- src/main/java/seedu/storage/ContactsDecoder.java | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/data/import.txt b/data/import.txt index 20058b3084..f1d9e18042 100644 --- a/data/import.txt +++ b/data/import.txt @@ -11,7 +11,7 @@ badgithub,@@github,null,null,null,null -Le Zong,lezongmun,null,lezongg,null,lezongmun@gmail.com +NULL,lezongmun,null,lezongg,null,lezongmun@gmail.com diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index 46d137c556..df366164b6 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -54,7 +54,7 @@ public void parseDetail(String[] contactDetails, String detail) assert destructuredDetails.length == NUMBER_OF_DETAILS; String flag = destructuredDetails[FLAG_INDEX_IN_DETAILS]; String detailToStore = destructuredDetails[DETAIL_INDEX_IN_DETAILS].trim(); - if (detailToStore.equals("null")) { + if (detailToStore.equalsIgnoreCase("null")) { throw new ForbiddenDetailException(); } checkRegex(flag, detailToStore); diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index 060c743ceb..12bfb9f54f 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -191,11 +191,11 @@ private String[] decodeDetails(String contactText) throws IndexOutOfBoundsExcept InvalidLinkedinUsernameException, InvalidEmailException { String[] destructuredInputs = contactText.split(SEPARATOR); String[] compiledDetails = new String[NUMBER_OF_FIELDS]; - if (destructuredInputs[0].equals("null")) { + if (destructuredInputs[0].equalsIgnoreCase("null")) { throw new InvalidNameException(); } for (int i = 0; i < NUMBER_OF_FIELDS; i++) { - if (destructuredInputs[i].equals("null")) { + if (destructuredInputs[i].equalsIgnoreCase("null")) { compiledDetails[i] = null; } else { checkRegex(FLAG_SEQUENCE[i], destructuredInputs[i]); From 06e8c3f7e6ca74de9c87957d19bd0f1e6a133528 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Sun, 7 Nov 2021 21:48:19 +0800 Subject: [PATCH 729/756] Add design considerations --- docs/DeveloperGuide.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 3ffc48a9bb..73d9095fba 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -20,6 +20,7 @@ - [Listing all contacts](#List) - [Importing contacts](#Import) - [Contact index parser](#IndexParser) + - [Design Considerations](#DesignConsiderations) - [Product Scope](#scope) - [Target user profile](#target) - [Value proposition](#value) @@ -317,6 +318,29 @@ specified contact index given as an integer, which will then be used in the exec For example, if `edit 2 -n Marcus Bobo` is given as the input, the Index Parser will identify the contact index to be `2` and pass the contact index to the execution of the `edit` command accordingly. +### Design Considerations + +**Aspect: Implementation of removing fields of a contact** + +* **Alternative 1: Implement under `edit` feature** +
Specify empty flags while using the `edit` command and the program would + delete those fields from the contact
+ Example : `edit 2 -n Jim -e -g` would change the name field for contact and would remove the email + and github field from the contact. + + * Pros: Editing and removing fields can be done in one step. + * Cons: Difficult to implement and makes the program more error-prone as flag descriptions can now be empty. + +* **Alternative 2 (current choice): Implement under `rm` feature** +
Specify flags while using the `rm` command and the program would delete those fields from the contact
+ Example : `rm 2 -e -g` would remove the email and github field from the contact at index 2. + + * Pros: Easy to implement as rm is a much simpler feature which only takes an index. + Much easier exception handling also and thus less error-prone. + * Cons: Less user intuitive and takes two steps when the user wants to edit a contact and also delete fields + + + ## Product scope ### Target user profile From 66e2073420135f1499ed4d2f35ca56883f6f9fe4 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Sun, 7 Nov 2021 21:48:51 +0800 Subject: [PATCH 730/756] Update acknowledgements --- docs/DeveloperGuide.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 73d9095fba..5baf14d450 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -39,6 +39,8 @@ - Inspiration for App Idea and OOP Structure: [AddressBook (Level 2)](https://github.com/se-edu/addressbook-level2)
- Inspiration for User Guide and Developer Guide: AddressBook (Level 3) [[DG]](https://se-education.org/addressbook-level3/DeveloperGuide.html)
[[UG]](https://se-education.org/addressbook-level3/UserGuide.html) +- Inspiration for Regular expression for [GitHub username](https://github.com/shinnn/github-username-regex) validation +- Regular expression for [email](https://emailregex.com/) validation - [Converting text for ConTech](https://patorjk.com/software/taag/#p=display&f=Graffiti&t=Type%20Something%20)
- [GitHub Markdown Emoji Syntax](https://github.com/ikatyang/emoji-cheat-sheet/blob/master/README.md) for User Guide:
- [PlantUML Tutorial](https://se-education.org/guides/tutorials/plantUml.html)
From 1868de2db092097098eb5edaa10ea574bde7aa11 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Sun, 7 Nov 2021 21:49:26 +0800 Subject: [PATCH 731/756] Update list implementation --- docs/DeveloperGuide.md | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 5baf14d450..09fe3a81c9 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -274,12 +274,22 @@ diagram below shows how the `SearchContactCommand` is executed. ![Search Sequence Diagram](images/SearchContactCommandSequenceDiagram.png) ### Listing all contacts: `ls` -This feature is processed using `MainParser`. The control is sent to `ListContactsCommand` under `Command` to execute the -command which uses a loop to get the Contact object at every available index and print it using the `printContactWithIndex` -function in `TextUi` class. +This feature is processed under `ListContactsCommand`. The feature allows the user to list all their stored contacts +in an easy to understand manner, by entering the command `ls`. The output is the names of all the contacts stored +with their respective indexes. + +The user’s input is parsed in `MainParser` which invokes the `execute` method in `ListContactsCommand`. The sequence +diagram below shows the series of steps to obtain and print all the contacts. ![List Sequence Diagram](images/ListContactsCommandSequenceDiagram.png) +The `execute` method gets the list size from `ConatactList` class using the `getListSize` method. +If the `contactListSize` is `0` it prints an error message from the `TextUI` class using the method +`contactsEmptyListMessage`. +If the list is not empty the method `listAllContacts` uses a loop to get the `Contact` object at +every available index and print it using the `printContactWithIndex` +method in `TextUi` class. + ### Importing contacts: `import` This feature is processed using the `ImportContactCommand`. This feature allows a user to import contacts over from a text file containing comma-separated values (CSV). From 3700b2ca6a52ee8507fd56770d7e1c1906b3a1b1 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Sun, 7 Nov 2021 21:50:57 +0800 Subject: [PATCH 732/756] Update code block --- docs/DeveloperGuide.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 09fe3a81c9..bed1eb542a 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -551,7 +551,8 @@ exploratory testing. Rules for email id : * Lowercase letters only * Numbers, underscore, hyphen and dot allowed - * @ cannot be at the start or end + * Only one @ character allowed + * Email cannot start or end with a symbol ____________________________________________________________ ``` From 5613cd79fd993b3b95adc2c0118e4322ecb5ba1e Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Sun, 7 Nov 2021 22:31:57 +0800 Subject: [PATCH 733/756] Update UG with page breaks --- docs/UserGuide.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 6f8775c41e..d1641ff219 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -45,6 +45,7 @@ when learning how to use **ConTech**. * **[Command Summary](#summary)**
+

## Quick Start @@ -213,7 +214,6 @@ ____________________________________________________________ Name: Marcus Bo Github: github.com/marcusbohre Email: marcus.bo@contech.sg -Telegram: t.me/m4rcusb0 ____________________________________________________________ ``` @@ -235,7 +235,6 @@ ____________________________________________________________ Name: Marcus Bo Github: github.com/marcusbohre Email: marcus.bo@contech.sg -Telegram: t.me/m4rcusb0 ____________________________________________________________ ``` @@ -289,6 +288,8 @@ You now have 2 contact(s). ____________________________________________________________ ``` +
+ * Remove specific details of a contact: ``` From 210ad1ea7a80fa0f18d93d7536325ceeb83a03d8 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Sun, 7 Nov 2021 22:34:42 +0800 Subject: [PATCH 734/756] Update more page breaks for UG --- docs/UserGuide.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index d1641ff219..fb84a1db42 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -351,6 +351,7 @@ Command formats: - Additional input between the `edit` command and the first detail flag will be treated as erroneous input and discarded. +
Expected outcome of usage: @@ -412,6 +413,8 @@ Telegram: t.me/johnlee123 ____________________________________________________________ ``` +
+ ### Importing contacts: `import` Import contacts from a comma-separated value (CSV) text file into your contact list. @@ -457,6 +460,8 @@ ConTech has successfully imported 4 lines ____________________________________________________________ ``` +
+ ### Viewing help: `help` Displays a help message explaining what commands are available and each input format. @@ -519,6 +524,7 @@ import: Imports contacts from a CSV Text File. ____________________________________________________________ ``` +
### Exiting the program: `exit` @@ -558,6 +564,8 @@ a future revision with more granular controls to allow users to easily handle mu For more information on the implementation, please refer to the [Developer Guide](https://ay2122s1-cs2113t-t09-1.github.io/tp/DeveloperGuide.html#ComingSoon). +
+ ## Command Summary Below is a concise summary of frequently used commands in ConTech. From d728bbf6b0546e16c66ad6478a195ff377d8fd8f Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Sun, 7 Nov 2021 22:41:10 +0800 Subject: [PATCH 735/756] Add manual testing for search command in DG --- docs/DeveloperGuide.md | 55 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index ea41cf2693..40c6c419b5 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -33,6 +33,8 @@ - [Viewing a contact](#testing-view) - [Editing a contact](#testing-edit) - [Deleting a contact](#testing-delete) + - [Searching for a contact](#testing-search) + ## Acknowledgements @@ -780,3 +782,56 @@ exploratory testing. 3. Follow up: You can either input `y` which stands for **yes** allowing you to delete the field from the contact or `n` which stands for **no** to cancel deleting the field from the contact. +### Searching for a contact +1. Search for a contact that is in the contact list + 1. Test case: `search alex`
+ Expected: All contacts with `alex` in their name will be listed + ``` + ____________________________________________________________ + 1. + Name: Alex Lee + Github: github.com/alexlee + Email: alex.lee@email.com + Telegram: t.me/alexlee + LinkedIn: linkedin.com/in/alexlee + Twitter: twitter.com/alexl33 + ____________________________________________________________ + ``` + +2. Search for a contact with a specified field + 1. Test case: `search -g alexlee`
+ Expected: All contacts with the GitHub username containing `alexlee` will be listed. + ``` + ____________________________________________________________ + 1. + Name: Alex Lee + Github: github.com/alexlee + Email: alex.lee@email.com + Telegram: t.me/alexlee + LinkedIn: linkedin.com/in/alexlee + Twitter: twitter.com/alexl33 + ____________________________________________________________ + ``` + +3. Search for a contact that is not in the contact list + 1. Test case: `search mebe`
+ Expected: Error message will notify users that no contacts are found. + ``` + ____________________________________________________________ + No search results found. + ____________________________________________________________ + ``` + +4. Search with no parameters specified + 1. Test case: `search`
+ Expected: Error message will notify user that the command is invalid. + ``` + ____________________________________________________________ + There seems to be missing parameters in your request. + Please enter command in this format: + search {FLAG} + example : search Ashraf + search -g revflash + NOTE : Flag is optional and only one can be specified + ____________________________________________________________ + ``` From f31ab04aab0fda61d687154cab87a3f5a10ba17c Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Sun, 7 Nov 2021 22:47:06 +0800 Subject: [PATCH 736/756] Add manual testing for import command in DG --- docs/DeveloperGuide.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 40c6c419b5..b93dd2f2df 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -34,6 +34,7 @@ - [Editing a contact](#testing-edit) - [Deleting a contact](#testing-delete) - [Searching for a contact](#testing-search) + - [Importing contacts](#testing-import) ## Acknowledgements @@ -835,3 +836,43 @@ exploratory testing. NOTE : Flag is optional and only one can be specified ____________________________________________________________ ``` + +### Importing contacts +1. Importing contacts with all valid details + 1. Test case: `import`
+ Expected: All contacts will be imported successfully. + ``` + ____________________________________________________________ + ConTech has successfully imported 3 lines + ____________________________________________________________ + ``` + +2. Importing a contact with invalid fields + 1. Test case: `import`
+ Expected: Error message will notify the user that there is an invalid field. + ``` + data/import.txt:1 - There is an invalid field. + ____________________________________________________________ + The github username is not correctly formatted, + Rules for Github username : + * Only contain alphanumeric characters or hyphens + * Only lowercase allowed + * Maximum 39 characters allowed + * Cannot have multiple consecutive hyphens + * Cannot begin or end with a hyphen + ____________________________________________________________ + + ____________________________________________________________ + ConTech has successfully imported 0 lines + ____________________________________________________________ + ``` + +3. Importing a contact with missing fields + 1. Test case: `import`
+ Expected: Error message will notify the user that there are missing fields. + ``` + data/import.txt:1 - "ashraf,ashrafjfr,null,null" is corrupted and not loaded. + ____________________________________________________________ + ConTech has successfully imported 0 lines + ____________________________________________________________ + ``` \ No newline at end of file From 5cd8cdab3812b8625a3298819e649155d1d40f7c Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Sun, 7 Nov 2021 23:08:50 +0800 Subject: [PATCH 737/756] Update DG and UG for pdf conversion --- docs/DeveloperGuide.md | 35 ++++++++++++++++++++++++++++++----- docs/UserGuide.md | 5 +---- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index b93dd2f2df..bb21f8f18d 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -63,6 +63,8 @@ The common notations listed below will be used throughout the Developer Guide. - Items specified with a pipe `|` denote an either-or field. - e.g. For `{-n | -g | -l | -te | -tw | -e}`, only **up to** one `flag` is allowed, but there are **six** choices. +
+ ## Design ### System Architecture @@ -137,7 +139,7 @@ As the `Storage` component is also responsible for loading these data into their `Contact` objects, it is dependent on the classes, `ContactList` and `Contact`. - +
## Implementation @@ -175,6 +177,8 @@ executed in `ConTech`. The sequence diagram below illustrates the process of exe ![Add Sequence Diagram](images/AddContactCommandSequenceDiagram.png) +
+ ### Viewing a contact: `view` This feature is processed using `ViewContactCommand`. Whenever a user wants to view a specific contact from the contact list, user can input `view INDEX` with the index of the desired contact displayed from the `ls` feature. @@ -221,6 +225,8 @@ below depicts the execution of `EditContactCommand` for a contact in the contact ![Edit Sequence Diagram](images/EditContactCommandDetailedSequenceDiagram.png) +
+ ### Deleting contacts: `rm` This feature is processed using the `DeleteContactCommand`. Users can delete a specified contact, delete all contacts at once or delete specific details of a selected contact. In order to determine which contact or which @@ -261,6 +267,8 @@ cancelled. ![Delete Fields Sequence Diagram](images/DeleteContactFieldsSequenceDiagram.png) +
+ ### Searching a contact: `search` This feature is processed using `SearchContactParser` under `MainParser`. In order to edit a contact in the contact list, a user must enter a command in the form `search {-n | -g | -l | -te | -tw | -e} `. If no flag is specified, @@ -276,6 +284,8 @@ diagram below shows how the `SearchContactCommand` is executed. ![Search Sequence Diagram](images/SearchContactCommandSequenceDiagram.png) +
+ ### Listing all contacts: `ls` This feature is processed under `ListContactsCommand`. The feature allows the user to list all their stored contacts in an easy to understand manner, by entering the command `ls`. The output is the names of all the contacts stored @@ -353,7 +363,8 @@ and pass the contact index to the execution of the `edit` command accordingly. * Pros: Easy to implement as rm is a much simpler feature which only takes an index. Much easier exception handling also and thus less error-prone. * Cons: Less user intuitive and takes two steps when the user wants to edit a contact and also delete fields - + +
## Product scope @@ -396,6 +407,8 @@ additional devices or platforms. * **Mainstream Operating Systems** - Windows, macOS, *NIX * **LocalStorage** - Refers to user's hard disk storage +
+ ## Instructions for manual testing Given below are instructions to test the app manually. @@ -488,7 +501,9 @@ exploratory testing. Order of parameters do not matter ____________________________________________________________ ``` - + +
+ 4. Adding a contact with duplicates 1. Prerequisites: A contact with similar either similar name or details must already be in the contact list. For simplicity, we will re-use the same command from `1`. @@ -514,6 +529,7 @@ exploratory testing. 3. Follow up: You can either input `y` which stands for **yes** allowing you to still add the contact despite having a duplicate field or `n` which stands for **no** to disregard adding the contact. + 5. Adding a contact with a wrong flag 1. Test case: `add -n Ali -p alixpress`
@@ -577,7 +593,8 @@ exploratory testing. 2. Viewing user's own personal contact 1. Test case: `view me` 2. Expected: All personal details of the user will be displayed. - + +
3. Viewing a contact with a missing or invalid index 1. Prerequisites: List all contacts using the `ls` command to find the index of specific contact. @@ -650,6 +667,8 @@ exploratory testing. ____________________________________________________________ ``` +
+ 4. Editing a user's personal contact 1. Test case: `edit me -n Zack -g zackster -e zack@email.com`
2. Expected: User's personal detail will be edited and the personal details will be displayed including fields that @@ -711,6 +730,8 @@ exploratory testing. ____________________________________________________________ ``` +
+ ### Deleting a contact 1. Deleting a contact that is in the contact list 1. Prerequisites: List all contacts using the `ls` command to find the index of specific contact. @@ -783,6 +804,8 @@ exploratory testing. 3. Follow up: You can either input `y` which stands for **yes** allowing you to delete the field from the contact or `n` which stands for **no** to cancel deleting the field from the contact. +
+ ### Searching for a contact 1. Search for a contact that is in the contact list 1. Test case: `search alex`
@@ -836,7 +859,9 @@ exploratory testing. NOTE : Flag is optional and only one can be specified ____________________________________________________________ ``` - + +
+ ### Importing contacts 1. Importing contacts with all valid details 1. Test case: `import`
diff --git a/docs/UserGuide.md b/docs/UserGuide.md index fb84a1db42..d6d460f992 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -156,7 +156,7 @@ Expected outcome of usage: ``` ls ____________________________________________________________ -ConTech has 7 contacts stored. +ConTech has 5 contacts stored. Here's the list : ____________________________________________________________ @@ -165,8 +165,6 @@ ____________________________________________________________ 2. Le Zong 3. Ashraf 4. Mayank -5. Jim -6. Akshay ____________________________________________________________ ``` @@ -203,7 +201,6 @@ ____________________________________________________________ Name: Alex Lee Github: github.com/alexlee Email: alex.lee@contech.sg -Telegram: t.me/alexl33 ____________________________________________________________ ``` * View personal contact: From f89d66510d07b6286095c570fe54f7468247c023 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Sun, 7 Nov 2021 23:25:21 +0800 Subject: [PATCH 738/756] Update DG for pdf conversion --- docs/DeveloperGuide.md | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index bb21f8f18d..93bb784260 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -100,6 +100,8 @@ Methods for printing **error messages** have been separated from the main feature outputs. These methods have been placed in the `ExceptionTextUi` class within the same `ui` package as `TextUi`. +
+ ### MainParser The `MainParser` component is responsible for making sense of the user's inputs. It functions as the not only the identifier for commands, but also calls its relevant sub-parsers to further destructure @@ -172,13 +174,13 @@ The diagram below shows the process of parsing the user's input. ![Add Contact Parsing](images/AddContactParsingSequenceDiagram.png) +
+ Upon parsing the user's input, the details are passed to an `AddContactCommand`, and this command will be executed in `ConTech`. The sequence diagram below illustrates the process of executing `AddContactCommand`. ![Add Sequence Diagram](images/AddContactCommandSequenceDiagram.png) -
- ### Viewing a contact: `view` This feature is processed using `ViewContactCommand`. Whenever a user wants to view a specific contact from the contact list, user can input `view INDEX` with the index of the desired contact displayed from the `ls` feature. @@ -196,6 +198,8 @@ process of viewing a contact. ![View Sequence Diagram](images/ViewContactCommandSequenceDiagram.png) +
+ ### Editing a contact: `edit` This feature is processed using `EditContactCommand`. This feature allows the user to edit a contact in their contact list, by entering a command in the form `edit {-n } {-g } {-l } {-te } @@ -218,6 +222,8 @@ parameters will then be created and executed in `ConTech`. The sequence diagram ![Edit Sequence Diagram](images/EditContactCommandSequenceDiagram.png) +
+ If a valid contact index in the contact book is specified, the details to be edited will first be checked against the contact book for duplicates. If there are duplicates, ConTech will prompt the user for confirmation before editing the contact. If the user accepts or there are no duplicates, the `EditContactCommand` will be executed. The sequence diagram @@ -247,6 +253,8 @@ If user cancels deletion, a message is printed to show that the deletion has bee ![Delete All Sequence Diagram](images/DeleteAllContacts.png) +
+ To _delete a selected contact_, a user must enter a command in the form `rm `. The sequence diagram below shows how the removal of the selected contact works. Before any deletion, details of the @@ -314,6 +322,8 @@ class, as depicted below. ![ContactsDecoder Class Diagram](images/ContactsDecoderClassDiagram.png) +
+ With this implementation in place, the `ImportContactCommand` will firstly check if there exists a file `import.txt` stored in the `data/` directory (ie. stored in `data/import.txt`). Should the `import.txt` file exist, it will then attempt to import the contacts to a temporary `ContactList`, before adding them to the user's `ContactList`. The @@ -502,8 +512,6 @@ exploratory testing. ____________________________________________________________ ``` -
- 4. Adding a contact with duplicates 1. Prerequisites: A contact with similar either similar name or details must already be in the contact list. For simplicity, we will re-use the same command from `1`. @@ -529,7 +537,6 @@ exploratory testing. 3. Follow up: You can either input `y` which stands for **yes** allowing you to still add the contact despite having a duplicate field or `n` which stands for **no** to disregard adding the contact. - 5. Adding a contact with a wrong flag 1. Test case: `add -n Ali -p alixpress`
@@ -561,7 +568,7 @@ exploratory testing. 7. Adding a contact with an invalid field format 1. Test case: `add -n George -e george`
- 2. Expected: An error message will notify user on the field with the invalid format. For this test case, the email + Expected: An error message will notify user on the field with the invalid format. For this test case, the email has the wrong format. ``` ____________________________________________________________ @@ -574,6 +581,8 @@ exploratory testing. ____________________________________________________________ ``` +
+ ### Viewing a contact 1. Viewing a contact that is in the contact list 1. Prerequisites: List all contacts using the `ls` command to find the index of specific contact. @@ -592,9 +601,10 @@ exploratory testing. 2. Viewing user's own personal contact 1. Test case: `view me` - 2. Expected: All personal details of the user will be displayed. - -
+ Expected: All personal details of the user will be displayed. + 2. Test case: `me` + Expected: All personal details of the user will be displayed. + 3. Viewing a contact with a missing or invalid index 1. Prerequisites: List all contacts using the `ls` command to find the index of specific contact. @@ -616,7 +626,9 @@ exploratory testing. Enter between 0 and 2 or "me" (personal contact) ____________________________________________________________ ``` - + +
+ ### Editing a contact 1. Editing a contact with all fields 1. Prerequisites: List all contacts using the `ls` command to find the index of specific contact. @@ -666,8 +678,7 @@ exploratory testing. Otherwise, input index "me" if you wish to edit your Personal Contact details. ____________________________________________________________ ``` - -
+ 4. Editing a user's personal contact 1. Test case: `edit me -n Zack -g zackster -e zack@email.com`
From 962253547b028a7130a8ea3f4cb35fbe4ebfc1f9 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Sun, 7 Nov 2021 23:33:03 +0800 Subject: [PATCH 739/756] Update DG for pdf conversion --- docs/DeveloperGuide.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 93bb784260..789b1163f6 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -739,9 +739,7 @@ exploratory testing. ConTech is unable to understand your request. Please try again with a valid command. ____________________________________________________________ - ``` - -
+ ``` ### Deleting a contact 1. Deleting a contact that is in the contact list From 4ee56ce63dee02370a9e126a8b83cd9faf359a7e Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Sun, 7 Nov 2021 23:44:05 +0800 Subject: [PATCH 740/756] Update DG for formatting error --- docs/DeveloperGuide.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 789b1163f6..406a7a1f52 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -884,7 +884,8 @@ exploratory testing. 2. Importing a contact with invalid fields 1. Test case: `import`
Expected: Error message will notify the user that there is an invalid field. - ``` + + ``` data/import.txt:1 - There is an invalid field. ____________________________________________________________ The github username is not correctly formatted, From 5ef88e772a48413da00a643822062f53a7dc6271 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Sun, 7 Nov 2021 23:57:03 +0800 Subject: [PATCH 741/756] Add line break to marcusbory.md --- docs/team/marcusbory.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/team/marcusbory.md b/docs/team/marcusbory.md index 895426ce8f..668c10ac5f 100644 --- a/docs/team/marcusbory.md +++ b/docs/team/marcusbory.md @@ -36,6 +36,8 @@ The link to the User Guide (UG) can be found [here](https://ay2122s1-cs2113t-t09 - Added documentation for `import` function - Updated documentation formatting and overall readability +
+ ### Contributions to DG The link to the Developer Guide (DG) can be found [here](https://ay2122s1-cs2113t-t09-1.github.io/tp/DeveloperGuide.html). - Added documentation for `add` function From 6ab093807da0422aaac1091c3c325eaba45e2a54 Mon Sep 17 00:00:00 2001 From: lezong Date: Mon, 8 Nov 2021 00:03:19 +0800 Subject: [PATCH 742/756] Updated PPP --- docs/team/lezongmun.md | 8 ++++++++ docs/team/marcusbory.md | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/team/lezongmun.md b/docs/team/lezongmun.md index 86593203a9..121a9433ed 100644 --- a/docs/team/lezongmun.md +++ b/docs/team/lezongmun.md @@ -29,10 +29,12 @@ The code written by me (`lezongmun`) can be found [here](https://nus-cs2113-ay21 for commands involving `Contact` indexes like `rm`, `view` and `edit` commands. ### Contributions to UG +The link to the User Guide (UG) can be found [here](https://ay2122s1-cs2113t-t09-1.github.io/tp/UserGuide.html). - Added documentation for features `me` and `rm` - Updated documentation (command formats, usages, examples) for features with `all` and `me` as inputs ### Contributions to DG +The link to the Developer Guide (DG) can be found [here](https://ay2122s1-cs2113t-t09-1.github.io/tp/DeveloperGuide.html). - Added implementation details and class diagram for `Storage` system - Added implementation details for `Command` and `ContactList` system - Added implementation details and sequence diagrams for `rm` feature (delete selected contacts, delete all contacts and @@ -47,3 +49,9 @@ The code written by me (`lezongmun`) can be found [here](https://nus-cs2113-ay21 - Regular debugging and testing of the application to find bugs and make sure the app works - Made general code enhancements by refactoring/abstracting code that was too lengthy to make them more readable - Updated exceptions and error messages to make them more consistent + +### Review/mentoring contributions +- Reviewed PRs and provided suggestions to improve overall code quality/formatting + +### Community +- Reported Bugs during PE Dry Run \ No newline at end of file diff --git a/docs/team/marcusbory.md b/docs/team/marcusbory.md index 895426ce8f..a4079323b2 100644 --- a/docs/team/marcusbory.md +++ b/docs/team/marcusbory.md @@ -56,4 +56,4 @@ The link to the Developer Guide (DG) can be found [here](https://ay2122s1-cs2113 - Reviewed PRs and ensured overall code quality/formatting was up to standard ### Community -Reported Bugs during PE Dry Run. +- Reported Bugs during PE Dry Run. From 1483c6ee08ba8d0f2e58474873e41ffa57d8517f Mon Sep 17 00:00:00 2001 From: lezong Date: Mon, 8 Nov 2021 00:08:22 +0800 Subject: [PATCH 743/756] Updated PPP --- docs/team/lezongmun.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/team/lezongmun.md b/docs/team/lezongmun.md index 121a9433ed..e49b7e0b2f 100644 --- a/docs/team/lezongmun.md +++ b/docs/team/lezongmun.md @@ -33,6 +33,8 @@ The link to the User Guide (UG) can be found [here](https://ay2122s1-cs2113t-t09 - Added documentation for features `me` and `rm` - Updated documentation (command formats, usages, examples) for features with `all` and `me` as inputs +
+ ### Contributions to DG The link to the Developer Guide (DG) can be found [here](https://ay2122s1-cs2113t-t09-1.github.io/tp/DeveloperGuide.html). - Added implementation details and class diagram for `Storage` system From e354ffe64402eca4bfe07211fdde2eb2a6d46c9e Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Mon, 8 Nov 2021 00:22:27 +0800 Subject: [PATCH 744/756] Update to UG theme and ashraf PPP --- docs/UserGuide.md | 9 +++++++-- docs/_config.yml | 2 +- docs/team/ashrafjfr.md | 25 ++++++++++++++++++------- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index d6d460f992..7eba07ef4f 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -25,6 +25,8 @@ However, for first time users, you are highly encouraged to go through the user bottom. This is because the guide is also written in a specific order to allow you to maximise your understanding when learning how to use **ConTech**. +
+ ### Table Of Contents * **[Quick Start](#start)** @@ -45,7 +47,6 @@ when learning how to use **ConTech**. * **[Command Summary](#summary)**
-
## Quick Start @@ -67,7 +68,9 @@ This section aims to get you started with using **ConTech**. * `view 1`: Displays all the details of the contact at index `1`. * `rm 1`: Deletes the contact at index `1` in the list. * `exit`: Exits the program. - + +
+ If you have reached this step without any issues, congratulations! You have successfully set up **ConTech**. >:information_source: You are advised to go through the following two sections. @@ -111,6 +114,8 @@ Throughout the user guide, you will find the following notations: Do familiarise yourself with these notations to better utilise the user guide.
+
+ ## Features diff --git a/docs/_config.yml b/docs/_config.yml index 213386adf1..be854e8429 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -1,3 +1,3 @@ -theme: jekyll-theme-slate +theme: jekyll-theme-cayman plugins: - jemoji diff --git a/docs/team/ashrafjfr.md b/docs/team/ashrafjfr.md index d901139d09..0e357e811a 100644 --- a/docs/team/ashrafjfr.md +++ b/docs/team/ashrafjfr.md @@ -21,18 +21,27 @@ The code written by me (`ashrafjfr`) can be found [here](https://nus-cs2113-ay21 2. `help` feature - Feature to allow users to find out all available commands in the application. 3. Duplicate Checker - - Implemented the duplicate checker for `add` and `edit` features and asks for users confirmation if there is - already a similar field in the ConTech Book. The duplicate checker methods are within the `AddContactCommand.java` - for the `add` feature and `EditContactCommand` for the `edit` feature. - + - Implemented the duplicate checker for the `add` feature and asks for users confirmation if there is + already a similar field in the ConTech Book. The duplicate checker methods are within the `AddContactCommand.java`. + - Implemented the duplicate checker for the `edit` feature and asks for users confirmation if there is + already a similar field in the ConTech Book. The duplicate checker methods are within the `EditContactCommand.java`. + Duplicate checker for edit has an extra implementation compared to add as it only compares the fields that have + been edited. +4. Parser + - `MainParser.java`: Implemented method to handle user input and parse for index when `view` feature is called. +5. UI + - Split `ExceptionTextUI` from `TextUi` to separate error messages from main UI messages. + - Refactored messages for consistency across all features ### Contributions to UG +The link to the User Guide (UG) can be found [here](https://ay2122s1-cs2113t-t09-1.github.io/tp/UserGuide.html). - Implemented the structure with reference from [AddressBook Level 3 User Guide](https://se-education.org/addressbook-level3/UserGuide.html) - Added documentation for `view` feature - Added documentation for `help` feature ### Contributions to DG +The link to the Developer Guide (DG) can be found [here](https://ay2122s1-cs2113t-t09-1.github.io/tp/DeveloperGuide.html). - Added implementation details and sequence diagram for `view` feature ### Contributions to team-based tasks @@ -40,11 +49,13 @@ The code written by me (`ashrafjfr`) can be found [here](https://nus-cs2113-ay21 - Updated overall UG and fixed inconsistencies between UG and output from application - Added the `Table of Contents` with links to each feature in the UG - Added table of user stories for `User Stories` section in the DG + - Updated UML diagrams following proper diagram standards in the DG - Added `Instructions for Manual Testing` section in the DG -- Attended weekly meeting sessions with team to plan for product -- Updated UI of various features to ensure consistency across features + - Formatted UG and DG for PDF conversion +- Hosted weekly meeting sessions with team to plan for product ### Review/mentoring contributions - Reviewed PRs and ensured overall code quality/formatting was up to standard - +### Community +- Reported Bugs during PE Dry Run. From d2a28467845f969978133f42c6413a30b9df5c7e Mon Sep 17 00:00:00 2001 From: lezong Date: Mon, 8 Nov 2021 00:26:11 +0800 Subject: [PATCH 745/756] Updated README --- docs/README.md | 22 ++++++++++++++++------ docs/images/ConTechLogo.png | Bin 0 -> 45487 bytes 2 files changed, 16 insertions(+), 6 deletions(-) create mode 100644 docs/images/ConTechLogo.png diff --git a/docs/README.md b/docs/README.md index bbcc99c1e7..b912d0148c 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,8 +1,18 @@ -# Duke +![ConTechLogo](images/ConTechLogo.png) -{Give product intro here} +**ConTech** (pronounced as Contact) is a **Command Line Interface (CLI) application for managing computing-related +contacts**. Specially designed to be optimised for use on the CLI, **ConTech** allows you to seamlessly **add**, **edit**, +**view**, **list**, **search**, and **import** your contacts. -Useful links: -* [User Guide](UserGuide.md) -* [Developer Guide](DeveloperGuide.md) -* [About Us](AboutUs.md) +If you are a computing professional that often uses the command line for work, **ConTech** can get your contact +management tasks done faster than any traditional GUI app. + +**ConTech** aims to improve your efficiency at work, be it by cutting down the time required to look up for various +usernames when working with colleagues, or by importing hundreds of contacts with just one simple command. + +____ + +Here are some links that might help you out: +* [User Guide](UserGuide.md) :book: +* [Developer Guide](DeveloperGuide.md) :computer: +* [About Us](AboutUs.md) :family_man_boy::family_man_boy_boy: diff --git a/docs/images/ConTechLogo.png b/docs/images/ConTechLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..2637eed38aa3c3268685dde98e1be24d69a5b2ff GIT binary patch literal 45487 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
  • UoU_Y|5onS`es=PkI`g1zibx+ezvH$yPucj=vuP1t$||97G=5M-dvTuP5VkS z?WWN}z1jKpMF~qd0#jJw5 zu>}==dV{YbI_29~IBx-Up!A3`OS~a4sj+J%+qdWbtPpO5j-lN8s<3_Opo$VMd6JE% zjCJ;IYYZw|={Xr&cBQ$BdyrU<;q*IGmOE#8Lj`P<^IWBFs;*1ja*0s)wX}tAnL;XY zhl=3StsNQyg?yf3r8X8Fr62#2Vg69MedeFtnw6sPVS=11wl+cF7cgXhKN)Nn z>gVfYabhsbTrHbzX~`Q>*2|KAJzf*smKQwLMD3Dl&3J_tV!Go!x`NxUmAOjG#oYqU zpCExMRSIJRF9$Zuyf#JyqCf9@=bY?Ea!eH(%&;w_d3raxmWcu*eR*v48t!@m%WMeI zCy?!`EPb|50>Z!5=^pilhiXY~#q1$tZ#5xWB_~?gUDb7O+h9f`xZy2vN(W(^)83}k z&5C~;U)uG>S_r5Ogn##=`m`pC=2zx-WOvU;J?Ti~U#GI{0U=8V-`GB0FBN$?TX-a^7U+@l4+CoLM={k}2}Uifwczu(X+o3mzse+$(3 zJL=Q3eaXS2+G4^!K77VEB82D>?>0V_u$Prz?K2?ukF)mpY;0`s&;mDv2{C*GM~u6!M1H z$E&LVffXOG3Ovs=a0$#C2)xu_?V-xjiUa6TnkyOQinX7yS7f9))w?G^9qB$5qk|1@ zv3CtFh^i&B7*O0Ydj=u|AzfameUxV!0{oVGGd~LtakBV7OOuBkt%Pl~PpK0+7BgZ4 zsd+y${jMz45WS4V$lyn`_TG$pQl?tp%}HZ!$y#u){~pb?x@O&AqNYjKNX?V>#=Ab7 z>uMA60HhdHN)^#UHFtBzfP&!8>g|^OQW>gvIfb{Zw>|SR3__ogjCf@)_mf&WWv(7* zua$5rr*arSNq^XMb$LHegZTjsGUn6ohm9~rgJ!_8qJ=?8F756snH;?%_#)yRctjNlbNO=yVyQ^TKtb(@2Y>b5+tw3UACuDs^>QG3%`_i z5+{y)E|s_r=!dY&O_M2+?eR(?S-(Jz0JbvW!2>T~~%}ZiDtewSwOAk}-TiQ5TtfH>bC@kJ< zRrCYbV6#{uRag71%^ezA>MY4$wlSEc)ikE|cO-uCOW%o#s@Z&xE-zORyQIZDC&Yxn zV{&eyPyS(C04E=LG;;D;eCrbS6{m|k8J!C}eOdhGG4MTo(0nbu#;31fvUjO+waU&v zxkC>tn)Ya=LJEp3gDfVSRY&gsrrJUR>(|!(R{M>3zx+;trFJg8Ow~5E!vn5frTqDm zfK3MupS|()+^qH^+Cg`&URnHGcg#YXruH6yBCHJzKIQ+eH*o;_45n$(4S?cw^;_&`2E=LQG)4mJG?j(vo?v1dn@VoUXEA3bx*VDRe z+D>;a>}b@8+~weH7N3WFHe?1K4I_t@Oud4{J5vr+t3@T;B8K8X0+Y`l@(YS8pm}%5 z$?}RU>^tq;-1W-Ykw;MeZ%^8XYm~#cL5fVKhRJEUTaKmWez-Q$GjhSZ?f4OY*I9}V*EG% z5$GP@2lHFK1o>=imB))!2`+}Uo5vR=Y4GVU?Lvncr&LSo(l`(AH!P3R3QOc3ed5Fz zDs;X`t#u&^`?@Ap{HCnD3 z7MW_}9>C1q`^B|P{lb0zHe+?@V5)N#1^_dBe1elhqf=8NBr&{0LnA3qILwWCI>%JE zPWNVwjnf;x7zHz_r!MIm00vg8uY)6pT2AxG44N{geWz{``eQc z9m*5fzi~Y@DD*fLO+B%xlTTz7piLq4nyDKaKG`&4h>urW@8Ea+4$zagmH;-x;t;md21$S?f8ai+nP14_)scqc1RQhUFp{MhI?;2p&1rU{SeLj3ym z=KJ^SzHb7CeXX?gEfBLN@MJ{4r@HjFtfjzn7k(1i;x`6OFl1vXn+z{@U4eD=6XW5# z0f8#d3jOchKUS27ldSWix-(+*T(~X>O>i!e(}K1)iH+ZX%- zr#q94HsJn?-hS6+tS0l5niJ!KJenl!Dx}M=;YDl?Q;$|t^_)KCogBF@VIwGWMteCp>E8YuL4&JBe{sefNk!i zpTKr~q*+ViXQ`s9B3rovghyMG)nqA+05{B} zjIA)IDiry>F;dTO7R&umsK)Dhb;TEAd%Ig3M9ercC3DP+3fc+1R+s7TIp(@3B)ZkL zFG{>Kqh+9bJ~_oOv%QhJ8@PXjaX^huZ-X?x=4zW7iHS+k5Xr1_ zC+pV$F#2R;kKRixjh~cC_6NssUa-;K9PB*6#|1)KA1B#yjg1V0zvjO2(1@l&SI*-0 z|12MGdzgU2G)T@fVTUsk!Y;GFl;-{8mr_^QDP`yT-54etMptx9L$Ph$-PBo6IV@wj z!#?GGu{ZQPAy`-chMZ6p(_L>iXW=I7i9eJ@JyR(J=N7GlwMg4qVuY|0GAg#23 zAS|VHDvC&Vx0G~A$AS{l0>aWOAYC82LmHQm?(XicXZZeJ&;R;jXWn<_-h1vjXV8Uo z`>;kvvzsC35_)Nsk1rr^lpSqSP?i>w`)fs-$xoF?dZzon3b^$jIW%C}nqx1^lMF z<0Z*cGjr3vBZ5O^Delf2pb_+2DES$oh!(iu?thOwF*b zJr7Y7B}ak4ooO`PA&T5_6;y2@G5RuNy|+y#@LVFyD4r;$EM=ylwo#Y_um`)2YmxBF zfu`$$qp7L_XF*jZ;yBhQ(WvF;sKrYj=YC;_t_4N6DN!qO<5o_*A>Cti0dco4){cN2 z`IJJ8wNzD0>F{Q)>BziaL|r#NpQW_<$Ui%2s`0NVa_0d;GAct(+Ch zIe*?O;eP;4R=r`Eu|v2fmCxJxvaOTBvTD7FZW~;@&ZZXIUr*Cx&;C}iaDDf!_i_zfKi1?Z`)8kX4FeYhiheV@j#Y-2 z!e;l#x=O9({pmJ^JN_Q{JfzqVCv0vNJmYpD8XF40( zxPYPq^o9!qE4lowrHV?+&Q_c7!?k{4kIx$NE@p?6a6>H+2U1GA;1gbL(KIRQX}y59 zJpamH%21n}i^v30q>FldTg#&ngsEBm{_&GY8SnFqj5!9Vmu=-)b86w^pm3UWyXM5A z$Vi3gXA$Y7k%2Nf?r+H@L8+g6G#JgG{*xpo%t-~+P6NH&;?Sq2q<$Uk7W05^cx1@+ zR=Lb}%AFgOlc88=Hl7DHouEN$@vIE?d4t|+EHyZLNau_0S!Fv@9=Ehh<>)B*bB}T& zX60zIWc_+c0z%6=2#yL6o_2CLqoL4g{n4EMbmva2Y?{kXn49tb8}*5~){=nuK9>QR z|6;2N@L>`!84Bzff?HCll3eztzceY_wBqyx;1VrKtjrmOef!f@*htsP+11HK2Vu`% zYF}$S8ln+3P*;vmPEv$Gf>`)?RqsY3k#ql5zKzSoY=|K6Es(YIv5oWA_)HXG3_on$ z1Hwn)c`FD+xKrd{+;4Ev>ne*-B92<5ye_RWWW0rfjuJbdSl^EBHKl~eeHvQDG^PxV zLa`gs<>#@8gvHEqb~wm2O%Bfv3H`RJ4UfHy6Nf#!yFO1yi;}v!bQOo1N=?={&mcw4 z+>CtKQKfBhmC!VMe#Z;T&@4u~f0m*ULsbb;M|%x#n-xA+#Rsjb8nMN;IZxbXcL^Ti zq~(1SswzTt*+0QS0K{fMla^e+;}SX?E%Tdc`hWRV{8a@|OVNS;N#wF?*F2T~XKX^0 zu+}5juLLY1!9JS-vBbJUwn^VXh6a8Yz;+EDo1ZJZ@x9%dai%@BGuy#=L zQ8MbQdXXkP9Q%eDI-QzA;Z*v1hhl|2%c3KA%qk;C;vN9d=j=$d{jsHiMh>OZ^itzt z!KC#!zxi{7DC+OI4Cc|(=5FQAHb*aRa)v!C6MA->?IgzvBCjh@Q7XZSgPA8I;c7X}eSKUGoPE*E!eo=RmM^h}`to}cW zI9gxun$mJ4gdKGP5fs|QiA&m++f^@ zl3(}|y(*=1BDp4hPf_LHcdQDlk4l%XRZjnq1u0c z<2k4^%_Kb*zMJX;r~P=IOz;11$MHI7Po%_j$x^D`jxC!30|Hj=N;B1DcSdSTo$Uy! zq!Q;3rMxq$0MIK^*$@;l3~j>Qy(ZA3@0TCL5IY zCsU~0&@t9ml(JHEDY_ZRhKS+{k@ra>?fW1iyiNKW^^#H|+-(jygd&V(LJoaJ5ZL5q z4hmluJ|1tkTlo_;LLdqH{YMHk6aQ7}69zEA_>K(kp+_(KxyoLOv3<%j-@H4B?{+~? z%G78m8dC5{TAc$7AP}NAGw%ch8tX)@f_bBO)J#nh3*JJ@yk^1Z<~vm#P5}Mw8_p3Y z?c8z%nhI@&c;mlTO`hPa4+ILr#96A1NhtiaP|0|x{dT!Vw+mB&;f|o#A zGfW6g8_E^EIQIiML04%!VOo(L8f4kTRP?GX?Qh87l{54qEGpNk`<||- zt$gk(=6&GVFRZSu+~okfpup)Y1t_ruW{pXzjw~wV{U?hfY~@;`$B)A=*1nQH|5CN= zZtMK67a)uxyH{~YS$W?FycN5*f;=WhG^}9*!(ni<7jH`66gNA8<2K!BI^!i@%J4eE zxIzCcBgntJZk{k_`npQv9oIR2ohxbdvKo;aH8JvN)Zo$f9zH(yha zF3zCc2OA+s*)~YWrd{VR?UT#>M41(8_HmT#*GK7}c#R``+^=JFN%S8;zBUU{<_&FB z-yrf>qK}y>1or#WSb*Cg06?q5%i zID-j@($6}4rI4?R%0KT~UP}s7OFp~)-J@ZO@~6@ny$L&|;eiMnmqT2H2U&63Z#MU$3g2KDw(ANMKYt}p-O^_E~==!%` zEtRL3^IS$j*yq3c@;9=7Q~%)ma&jn34F_} ztE{D8Y9zNKBJ_npz~7#exWrIUh%1)eg8=xXQ)hzh(rTFto_`r_^3!Am^`t+yd8 zH0QI^P1!j4{fY6rrm)ZDwOW$4_4%s?+qIU*-n3z2H`m-HJ|AE>I7d!=cGf>lU-o{5 z0(fVpel?VX!!S%uVxrVyXEuc*H1u#>RS3olhvBG6u(Nh^u=RZ-h(>;Qa(b2Wn1?uo zfEtk=O@xO~Jc=G)d@-txOJA_{q6PXYx2jV@#Md-)mh0(p%%hSLn2zd?DhKbS9Vbfi*W~n&T`Ea= z-m)?$8!8dr0GVX@puE3FO>4$sQ2~AW)#CFQrf8jxR?nBNmi2Y4HU*a5<>B(ay_^XFV`*7=u_u@d_#4!e|T5-vZNp^OK zurrdVe9guB_vL0W*32s5?{{%%D7KTUwbohN5*9z{t5Cs|Kli+ZXa+)`ugol6T0@$y zi^G_8$P_|+3lZJ10@J&d7RCGD+<;6(iyI9wqab}{8q884c`F}ZcVv>fxV$nFueR(Q4 z$?TNnaJy4VmIX8<@;6&D#g*k}Z9F0gb9Hg1z=6x4X7pL`d&ITi z1JJP4=&>~Y*w)tLE8=q{Wc>#acH_ux2f?4J!V)|*lsHx_GNonpFw~&tqX#e)i-ksg zSUPF=eY^Jnq-y3Lo2+J9>imQm0IyQuC#0gJrY~D?p@4)vmtkbYgr8)P<^2t%vXpkw zTy}4y)~1_*thWvd+^G%r`WK_MCclnNQrv53(@DB&=Z=pjXDD`p4CMiVn* zqXS2Sc60S3V$b4np0M)O(UOXnRF95MOij+(#LLW)VsVBsV_(!vpf&l1BxPCj_6B^n zxiB#|EwU(B8LW!u2EdM6oLpHRObQzk7_gtzoAlDMJza*+QXgXI=0~q*E8^~2mLmaZ zH%?A;EenLug+S;0+b#HIF6w2rt)~P8jFmh#Qa*@AmFa%g#iFxp;_Z?HO@Q$yX~VsG2Ts zbp9xgN9^I#{$Nm2Gp+v7k{)Q$hxzV%*9{RwQAu6*2SN^?Lq!I&^xwkA{%?B370~|+ zd*8KlyJO7?95ZrRn&Ck(VKEz}fksa`8Iyk?I3LNkM0#$1A4-UpVss_MNXyFWk@$@P zX8U!s(~k$MPMS+Up19IV;C6%=EdoZw; z3~pC@aS%G`C2rBlF%nQof_^gQ$VW@cg%F(LX73pzy%l*u!+H^uc69@8( z*-=Z%5BBKzRGf{3R6LftBQ2*mbMphM#O%#v!Q`LPg6@rp>MQ{ZH=%IDuy;|_Aar5G z9S+G;E7!YG-U3=r+a?XCf{Z5uYxAb33xabkl31S2nvr)5AH&4SVUlTa-0w4*hFc6< zxy^4LpjI!*AP^-2$I{m+5n_*+UB8@StbPr?3NuYp&_ z*L8h(5B7j*T>hBO+}-+e+cJ0M&N^tL1tt=xBdy-T0gkSzTXx0X%ZcmXoXawcd-gTj zfO+!|1Y$Ag`8|C#a#lY#fVP5v(0S>D3|1j`f)DOYIV@DO`n}rnw<{O!VKst$Woy>B zfM^CVW5bXhH4a;H=%s-U5{j3-j|Y5(|MLYPmZ0tkv(P4=qBj3VU}91|#yvVyK}85A z-2>w(XO?)H17$J*716j})0$;cW9-_t-gtdl+Nd-B5e zM70k|-4993kaX%)i$vq47!2)v$it7(@f#=8w|vmFX5G)0myJ~JwY8o=HOHabc#tA_ zh9F(3O=j`;_o%Z>q{fzH*R>GwIh;OUE;l;b3o_M8U9+-cAyqxbHWq%pg-pUB%o)Ud zuwShgBHk~jNGvhI=$-nU8O<{9FQZgg`yxgQ<9&T+nMf)Jm8B@r^s;yR*`o=0gBYrD z(0i9P79-z4^1yJKJt&VkO>ulT1?8rjbb|HcrgQIQNNuQ5{7wp>g4`~W5vcwo33c^< z|3v(@dHTG~``uJx(N^FS>qkI}8;2mZnF4y=(&-%+s8>3etk2m!0Svp%`vKMva9aV* zzmE621I_7O%|~FW%}hC7mty?qYecPKAQ#&Ua_pEccE9=VPW{Lu#m*NJW#9k6=R6s&*N+x6PFv_8k3 zG7o5(SYL}VIi;zo21~?i#l@OF`K@%xAfcp6n0`+Rfq+lWRD$sUPD_q0DQwG>u#i*! zfNoh}w}uIyBS+LAZ{96Jwv!nL%u%#ndHyDrn87p(ED@-|fzU$hpX1;UXQM{b^g5`uYF^BH~KI1aL!( zu-+|fY)lw-onnt3VE}ON0K}knn*bTAyk+4#m4-8!5&;YA-?-(94DbtgnedQ|%vaF* zc~lQ=?DL+s#e+Ar-?>U|+kb|0n!U)*>i(^aimtZnul%C--ccBVMBvfA@7gtZ@c|lT zM=Y)MGi&3IV%P3aCXd0-5pOHRem%?{? zJEd{==xZ};=`rWVN;fWA4)ZIB@0+iW^g>mJOTSAP`!wyOe16ahdB`w*LK9~>S^+cB zk|M@Rz<)arO72L?NjCOtekL&O*BrtVV&7)>{qw~E*lwFv9eXAJvPRR2Pl{bQsE(^w znHSlp<>Fb299)7}pmlz7kX_FFB0!bi9OaIP#)71IvEH*Haa(`AB?@^iJ9MJRZ+$h5 z6>mq1jp=Jd=Wmgi!bbzZNM!lGyq_7Fl;sV-2wtxSRub375*@H~tiJ4ZMJZ%XM z=RSqE0WAjLoVJi?nWUH+#r4;@j;+cTo2TJ9*rG$Gi}C&qe$s+=hk<>p_&@eA%mg&A z{K^Z2t=u}3wXF-xB9DJO)cnZo|8|a52F=(yJ}WEf_)JR4-^jn)#M%4EfQ(NEhoB@eOe4##5dzdB#$a(tv*?r zeX{J}-f-|$#WK+f^qqB5mU{k4{97!s#Iszc1y7%9u5V6GUh>(s>Ca!JGZz>P{b%0k zp%z7UBL^|0^+ju%e^wIe%k^$IT>O8ZXU60#M~2HRJybYV*eZZe(%((%1zX611t~=~Pk>={Z7gA!HinU*2+>!BCg0Oq86mHqH`(oehq==Yx5lyCo+UofdG%# zSOA`5;vk%z_l{J7bNDb}S|t1M*9Xl7Iy1kRUzMo+%(9T{rShvGu=y;d%N%Z^J!KMdE5A6GSc1@$KQ5{@jZ*YKr@LLY zyxQ|ti7u@T|ZS z(OY6P5StwrRs1xhM$E7M3y}_uA$dvPdOAo44ijt@iIZ+O4Td`*u$_sTfi#v4kLUQH zj6KXc30Huh{mT2eJ(xm*iTlp5vJP%bAOS+dWc_)(Hf|6L$g^|_85E)INji2NJSpSf zhojMbm6kIn8a+9i;I^L}AJV-ygdM_Ai3xay*S%QDj1M7-CIWm+TXZ-y%ET3l>9n=U zmF5Uq|LfZtEqGVyu0z!_rq9l1Enqu1=srvBLib$|*p0dox?Ai=I_3N&?2smZSOz1; zoPt|)iG%XyG{HBW+0ry4)X~ZC)T^obWGa&+2HOUmDj8XII!qHnw}hu7rd; zMh7S_0~0E(KDKfONiscBJxBL7(jpa)_fe20j$PIyC5$)X>WB+SFF6+}Bc_FvGVD$_ zrg4ff^%Ba``hy#+D@{*9w9$a@BJ*Yg0(q=<=r-*lS;sBc<=v$*#;l&3TrjjSQj2MvC zgZiNjT29gqe!}pqt!IOrxOz-KjX?{Km!PQn>>W8@l}pE`vzeeD3?-F$%Qe{%Zqw}1 zWM*K%hlAsIcPPmrd~xm*#Nu>%TxqTqxAuquiwhV1vpFSLzs~*oKSnc*sw0BYY7#HV zmo#Aj`57q*wix=&=BSKsNba}Bpj7Vpd{6OwGoRIq$Of=l65mizgYu(NvnRve7OxU;9vniW)pn3CaT&sMk9Rx7Iesg_h>7 zVsQaqZx#pxjW|0rk|vEys%OxFvs9tx7b;n{=;k9UjWP3!dImCuK%>*?%_fhAaCJ^8 z2?!^36+Ji$L^HLvz~C_iP;!3_OR!UV(*8D?taQ^XL;&nq72c7yQb%^9@gT>4RME)~^)QHDZ}VOt!cgg1svH zWq!@$h_4@Cu$E(sN+|vGzLyIyq^|u%g@lA223x~#l=um+7Ew59_AoZ2{}2VFc|%c6 z+2&;@Q`Qj29}Ht*ZsDvaT9jq5q?nzh9k^iz^Cmkb%GCSO7pNJo|R<>yRdUbne>l*}wW^qe<2A<+m#?<8FNDHy$4q}jLa`hl=f zhk?-%HChM77@uG=OE(uA>KRqa`Th`x`Hd4pryP1oJg=bWYhgjDg2Q$`sp$2}CZQLt zoTTD_(oYeZtp-YUE^%3fJxGH6Ba<{kIEQRVdgG&eEeyoB8H@7?*Q1^Q>S-^k`vIA! zi}m@RvsC7nf7jgmc9pa60UtX=+(-Wu@UbuX#4ct7c}_}Au9W^^K>e7Z1mmJZbpBvw z^{#cv1^+&?egaW;!fEepYN7NXc=SIwC82REw*s=kYv)5y))sfCi70`16cA|D?KRyU zam)$1czL`qBu5Q-{LB3tfGGf4s4j6p3R?Ksv+MWq6`Pge=Py8`z!1%|q!?SDY~8Y9 zOe_IH8bZIXYg-xlM#MSHp})}Y&jQ!hEr~3lW}LI&$cfdK&+)fxzCwc?N1>S4_Z>GZ z7+l3kd<7TzH1NHBzm)a>_h<%!{I)hnYf}j>zXi^YfzR7I@AU3-L^|V=uw*8I1nH&~ zOQKG&Oa5Ev|IsBhwe(e0e@K=JDTEB-9UYF0-gDzVyIC84#(=E0o6`UyRkt19q43(5 z$yxmk4*=_+ z@2lP|eAI9?P?PBPYN5${UaY02qp$6?I2_O)fux{9%I10F0Kx!jYix9HrXsT>EzlT2 zhxuXt;!v5e5S^=IK(iih&rQllto5tg7c4|3!VIB^FF_bkk#8kzOLh@2ao61C*(vYe z@}xHR5JGMYr#)XuU2nmPXAipiNALvcDFTmdl3q}Xn%4T8*ns3wBn#9 zbB1A8mq8sJ*@MOEWT1z7^=pE0_??j!uMn!reQ9%Ot%$&Omm<^(QN%l@8oM)H*|$Nf zEyk!8pT#4xB<6j)$%I5EfXUyY^nEWrIy`-FdWEDCt)_3?VVJn|Um8#UstbtdaTU%s zL0l1?6{$Mteum>)4ro{XKc;%iL35k?zLN&6H8>p*PC|aP54Q3XS5QI>L$DoH)gA@5 zxI~%)`hKHd)WORjme6!gq!l^@@Y3VjrYYyZya;gd^qK}l1$go;YKyj@#%M2@3?!Z1 zwc-vP%f-soFfb`VhC6qH6i?d+ z6x`4c863h#Ih{KUE@}`+oN<-4w$n8VrzE~1@`ij#rvcq~X~;HP`j>Xd40mt!fX8df z;Ap9AWfD_0Z@lnW#o^Kizrf6AXzM8jvfPu||Gy#%pdaPv=}%CoUgnK6B}rfdKtD?t z7^FKnS*`WzeCxH*^MM0i2B$&0Y#hs%==k-fO9}`(f}U@xDyxK-gU_lrPa9+gVVnn$ zH#W`zd4Dk`M}c}FgT}kWX-iw__u75)8AlFsBfiXhO-23|Xo7D1ei;$i)O_Vi#R&v_ z+E*M*b@c^r=G~(+m|lk+SkoS(=IRHA2Xkk(wjXwcnQEE$8K|hOddS-{Y36n2Wz42KwGb*|{HZhM4icSBk~rmush z@-=YK1{~XBzKWfhibvuuZ}Dd!oPdd8V!Az1W3iRR6Se+lwKB04Og?4`8 z@~1wXZ5L;jiq8A{wYk`$0M&h}7E5;ds-cv@QMl6yr_QYI0fay9B?lWdGQQFi7IrYL zyWW;76S+NClvg^_dY=uM0T3esgQhY20{5>|{KrJLyP;gXa#kkRhlOXN7e{2suHJ)3 zEz*(kw16r}Nu2-^fJ(2;%t5tFlLO6NR@l?Cuu?@G7gpuQt<;@aNj)#Z*elSzC5g^!stk6-b{r+(!0h~ z_DZ)?b7jx!kno25XWkTcZ08+wo=cbd{>;~_5msN~cnozm^ z^EtOQV*|4f#@-|eaX%oC?00~yVr6Mtb@dc-PfA0W7yTq9BPCrP7mV|kZMC-8vb1V? z8X3cUnCQ0MjXHVMg64SmGDO=Et>3eOS|Tn(CMxBi5awTNd#Y!*J6-2Qk7B=F!iNCC z3^AtNL%^PtQ{!rd+?z>cgKMp20V+Pu+1s7F@tNB;F)l!HG5Z^VJtZr4J!)g$O&8b~ z-_s~omd{JeynO$VFR3OhK7gS0o11zNO9a1v?!plcLp>vZW@FK$r5lfOu+F=VyDuzh zz~Pahf8E+(-Wiy+>N3Rrs9ce3tW(I$U8+QD2`l z>8l-Xm;rtM1^GNU-mnu$i3!Nc2HT-XPw@k6E;DPma&&U=4p3|ghU<$PJ9hp!FB*riAa zzHY;c`C6$$+nT5*h8Knz5TAu3@dj}EEVcYW*gSn_uom-uJH&&MhFqLJ;+sOL&g zrXL3ySth&NZiSz$~nqyE<<$?p*u2pz6h`PwD@k zEqRqk5YW_SxJLMhatQ!-Od2bm+>oco)!j~}2D;M|G!zUH57;{)rO(kq4a1)LE6RAD z*%`R=6>Ti5AW7MtbX!_(T+e54aL>>V5dh)R+xe|L6y;;>wb=AHWV6%O=rB>faR}Ea z&&}}!s~lU(YD+fZCOdnOwuYWOY>fU{xSoxrkkf6Vyvdre1!LZT^Ov*Ky5ZkM$%i0X zslxzx%SgX}eaUkIpdb@z!|9kT3Z$3MW>s-LA3t{`;qw=9rUCQ=M~K9`9gSiho~k7L zC||>8tMmWX;dg5WVPOjJSV9}7pgiGHI8zCmirmoDq@8~4 zpFlKDXBh6;X(0szmm2GmvZ~;Mdl9WzXVL;)oRJ^rb4F+qon8spR;!Q87T28aHl z-mlF>Qy&JMZ^oIJglauh*ryH2%_Lp-SnVjUW?1)p&Nns`-GYyjz&c2S?$?1%H!n~P zm|=E-<~2nRfGoD7NY~1J18isAz!SL?^QC~6_~7=6)W!v|`rALn@Vn9RbAUtQmyvu2 zYF?+$CfBaT^;0uLc4xE1oh9x9jkSr=!5>?n0kt?ad~bY>jY_1XI_^5SvDP*$Os?@_ zm#NAFONyGE2qW!xH7y5UXtTgeP|%b3|4Wk&&$kSY)t6tc2oIB^yje#5N#lCO#61Lv zA%p=ZR^1h5WiW0ouA2ig^A096mGzJE!bK<~QiAe-xKvIOLJS-WKfS^0(cI z={e<+WNpKPX!)D0uC`Onr6{d<5yEgFcfP%?z}KGiTmOuN-m?ih4l0{g6{ZXKreCgWKqC;Uu z+1d@hf^7e9*^%tFUchrPuPI)M)PzzC)sHPXL_K{B06a4ptFeCgjR$`owQCWbBez?@%4{&p0>`O)B*tq-VPa47r_@A0O2D(2Lwv*dM60&$+ z3EmzVG@K6Z&88-#$YgJ*-!lep@Al?=?)I8|3aj9syPKM_Huw^Sn)uzhILWjR?R=O> zTk0w8OeJy)Gp0@L-HriEyDYy>Vd!Idf+hy)p6FKGaI=t^-jDSU3(M5lFQyEnoaleenIN1ja4MH6+AI8qTPMO$Yh6?k+WX#?!oQVk^gwEBw z7v{1N22TvIVbcAkxLjlE^YK}1DS-DiHoS!RqBe4JVGe@bJVpb~#-B~L!(GKT)^|hO zD@;6vfSR%Jc42JxGAFl2W#~(^odyKrZ?C2ooBpxwVJ7pY&V%Nhyn34>ZM7(=(|mDq zt6HDc=@pH+>;I0-;M~&OLpEuE>+ag$e18l4+aLhf9f|W z5yuYRe|e8mKyw)esDE!v-b1*Ufrhxv<;dRL<>7WLkh!SBs%(MPoQEO%mkrA)8887Y zJQD*N@sLiQD<1-Xdqei)iQqDGcJB7YMAQB^_rM5WfsR@{Ql>!pVFy3;7?1)s9(D}e z{sGjGnB^N^f(Wb0!p4QUrpwzEE4DOy|NX%q0sjyQN*XFJg8ii#6p49g?pb2_EYhHs z>mnn;4xnFS*Y~_Q!M8nqv6`~%VJ1h}9Nc~actIRDw}mo@qz|3<`m;qKWRLkx@(l8Z z;5=~hFWT4FR53Z@B)|b;`ndn@aH=TjrbJU%YEiOhtXP|$u;EML3Vt#C--P#8s@k~R z5P$`f`JE3|_#)(Gd*icWb?rm}4Ds+jV5m{zky9tGVmFQbh?42C7C@;Zc!rGkSP9P% zyX#FFOA<16dH5`jvO|`WT-38<jS_W!|rZh>}EStMnk(LYGv+KJ2{x@FB#}xuh`9PZ#PPmR&Lou!*-_{Drm(J zscmUF3_mxV$HvqNt)x7eS~)@OdE424XP=o1`k6(O#5Zg>;R=0}H|HqOVVT`Ee|%m| z6Kb{RwZAcOq~V04vI^}VfY!$;?&U$m2%4=Qy+nszAAuRy2>SxUa6H< z``2)3fu^kIPOq`H?o^#sOx{Nq2Ex#<`)$ToAQ1tV4DJ+NktajkH-7W1cGPtvV#n)g zGf!=?`kfevW{5aD01U({;I!GZ5|hpG-Z+s8tDsTsd0UP1(6dBsaiwl4!hjheKBNF# zVoZwWwG{DE@(C9FB591T$e_ZrGYjYeS~AV|oOLo+TmC;6Kx$N%d3w_2sOKUd2xb8J zUvK*n9f}6(b3T!~Z9SKFDNS06qQ;1Of6$dS1E4*;A%#+A5@7IRX2^ctA%p}DrF-L* zq9x~AakJ)7qoG&kW@vgM=mrgz2j^9`__Y3?9CrSms1KE=dT-iGXwhMmlM6^FEdyPz zDd12o7C7rjDoC0~o@PrbBP14?i?cRpybo7a@_V<`$LwZ?HPyA-oG3d>mXR@g-K9TF zwX!S%=%ZBDiYh8y&+xoAmP&EqN%2qLV28j&Gbxc`Y}kWttZ@jwfUM3>F!iq~sJxVYhj?COq8 zN(7_aqa-A&KjyA~Gh2$frJ@ep^H@-;Ul%-6b^l8;BKNDAKj7d1l-8+A_Z`5bl}c}R zpzJQ)1w#B^?}tvJN^*f#%F1$g|L$&QW(;BKYP5b))*2k^q~WTzR?sJvHWE_!ox%S- zZwD{uX#>hCe5X#>HFeeE)-NF_f#LtUKZ{gZNHG5VyY|~Eo_SSh zu<{Pt(ZK{iU+P2+T}!=8k>}9o_8QqVtdb2y0OQW5bzanzSuu9U9Gkg@9ta~C%;AyH#aI9Ag9Xz$ttHS%!S+fMR3-=cXa_%oz3qlTS$xF?JU(4Z>q4fOP+ha zqiX)hr$U$c`KYF=%_{I}LpgZ-c10$L3=hAuoVYZhhY`7=#1fmGCB4=cnJf(6Tk&i4 zJf)s4+nXOhfA3IwKHGHnA>L=_M8x23^&QRK`VLMIR+49MXp8;A{`_UW`mT_DwI)pe z*7P&Q*)PiqkImznV)#~CcB;EkcX}F6KBAXqeP?5XWw{KoulClMbFb!zEFy*9d;ebv zh=<0*Nu8MX#h|C}FHRqM8}}ocE_W2B;cIy$p&b3|eX*l$ad+8<`p{*014?>HfXMAJW2!-Aar5 zbvUSract|Pf zSl#@axlHdjkG|5T$lK{wZ8Ajy-v!>;f?OS?Bk?dp(U)ygT9g zpSsoLM!qUbMn){c!21YX8#M66gg<_b3u%9nisnTB0UBASgWzN3Tu$5!X56p)2K|OD zQ|3kBR^PNkmZ^%2xK-z>=7YdpyFkneJ07={5M{r3@glT6SH^L(_yDLpM zf2#t6u!@^pbUbye;0CU6J6FM!$1Swj-&FHbQD%$$R2aG1h3bXs+0rYjB5Del;XBsP z9o;)Q4L}&coeVbhI4DHNO`SfapD!1u?(J??AC0D@r0gKhb@n|s zw{~iG;!-3Vz0#F)d2iSi*)`a8$tkF)Je~S)!3}6a9+0mNn`v}@$DU;Ia(NB!xUzhC z$UzVaU)ohv$W#s|sb*PP0{e=jKr*Xaofvn@3*Yn{G0CU8uYGCoUSvNpLY!@j?89%y zihXWh)95vP>JHN@qlu?jCd|?!e|Y09Leq5D2Xd?)IaN|Z`|^$-Bv*B5rE93kX94_v zD?6K=ZR>uM!Pa-*X7s3lPyAZxJDi7tlR6X}-Cvgvx9ytPJlBe2rBBumV$Ay@ezJ~e zS9n~vZGbPJkr(T<#t{}47Kd6I%=Mg@QW|ycV`wcNG`#?kL+LOPT!Pgsj({ zNR{`B)ttrX@NQs-HMq#M^VQ&|q1njW6CCe`nL@UJ(YQFqP*U(nIx}`zf~=&DjJdgv zl?)wjt7DC$(U4lVY@HO~~E@O4aQBvM#}Xg8aT^#i>ljj-D>1rtq3OHLVZ?cd4#r92^< zRao(FVjz`c`I#|6mUQL;s7rzu&rM3SbF-9lJ&e27+LkY(a8~Yb9Pr0vN>wx)^noMQ z^?(9=Vra&>_Y|*pW{4?8es8??wua2W6U5nz7m4-Z-lcEUzDe&-Zh4;Wh!JDFWk>96 zg6)2#MEvlsZ#`P|CS^h-Q`rI(110=w3L~f$X>e8U-po8Jb9_uGe7OQYKa~`7-0C>V z$G)(bsKKXYMA*A8mnJZVuHLO6@4D}9;kR(}{uE@wksLd?liC+mOZa(Sz4BP^Dxrny zgB}f_R-9q!|5a2lBKt9ORS5z&_~o;gm~mC!Zt8st${(>T1#1oW>`&5A6|imU`PrMG@=#}qHS1%Jo+A!4a&=u> z6Z1B(l1Y1+B#lP%hEkGhrx1P^gnvtO*FTpc;OUd4XC%GixFqlDv)s~t_X_tLa|lJu zGnKu>9L>T}%Zf?Ub2e3$*rDuxpA(8Xl*yomoet8Xqw)YxiFma%A#&QM^iCFjL!-rOg< z0y9kx9_Gi7@W0U_Q8Ug{c;AjL>wkWmU`&b7VAm->N-Ug%pAR_JBqUijC{$=Ss9RaT z9<2U!J9V|R;;_1X0iF)=WDC$Wo;pX}tjs;>99RrEs?$Fmv5q8v#uEECDud~E z?(Vi?61?Mh73a)`$!h-qk(zD79@Bxf2lzeu@ZLCUUZE{gX}7b(=M~yZb9;sQ`MnVm zQa(wXxMdUDmAzZk)n}EMM^_o^js-u+F#d#?hVC|*yV4<>gbfbPl#7|*gtsR_X}1)K z-UWLvV|sNPyq7B3wifwQZQ!H}(qtHKMUf3=ogLs(Fdv{ean%z``X{ZNtJZX{AW&pkzj2$)@Q?tU`yRa5IE@x-~(yRxb-241;*<6pSCf(m?d{VpGrE^v6V)`bOtgqi}c8@TdMqd;;Q|r)6 zRW7? z(Z#5%?m$^pQFS{(CR$-Sq?QHg(R@qL=HN9G(TltqZfIzjLAXy`&_WLbrc>%%i}Xw0 zt0X-ZnbAYu_1uI8V%ac5$~0u?;3uOeWBLt@NhuwSnXB;~o4+~gk1sVEZyR2lOD6Jj z@W)8GI)f)W`gcLmZbsFbtW-SKpF(lL0Y8e2yjdKJX;&@-FNCXj>908AeEU_Fu@gg6 z=hXW*Gu-r5lJ|Rt_e$~oYrEqOTeqIBt}f+)z5H*D2);O%doLQh_9Mq=x-Aj%E+Wcb2%B*;tr%acQt*r;kjGy&{{i^fZ~VPKh9Cl?{7Mv9BVph#mO+1OKyyk&#tno zv0S9E5O? zgf<~#W)vmm&OtK_!(29(VZ%1QPv@`r{&0Tb2eZBRx;&qc%k%YmKHr|FdPHuDCTP!` z?3mRqn-fELgX{?nA4{Y8EvO{xgPEbSHU|NQM6I(Fov7Yn2J%#8{6*6zFyAL#&;5Pf zLU!cY6ALebrSecOeX$U=`ZpM;ZC}%WicxBwsHhq$U;2;)SJ(Fapc`QvshO5;(iyyI zM5WdY7+r|I8+cFyMP9uoJxHf_^>N(4)4Z>AF&14N@}*NO81&wm%(SRnBqKzY~!f;+WW@GHjE!DUHlX%8WH29v}C>bW!r)uS!iE55NGP>$zU6Y z&cmi_`+B>^QrSqabQ8atpTrDhkor<1_qYC$@T+oiT{vSstKS#v@3XRIZ>n9L#|mHAs}ppiwD=9;zfn{u;s-<<%DZ(29FU^ zlPiKq{sBSj(YHjQME`IfzrbXD9J*ta_l^HY^F;rx4CUQ1dXK`XhMR@;s|^I=(E*0@ zIn^^3nrW^zcUPBk)}~r@}!~wIe&X^Cv zc{(k?3qi;`929il;%BMG^FQIZghbp>v^z3WVLd`MO`YAI7|G3qTiq9?#yx^D6FW?w ze0d4?a7QtRsz6OxQCb%6iBU>x@f&!H5f4mIT$*(ESHE+)=2Z?;NblPCj9)18!TGjh zx-lpeCei-9gC>ecw;l{`<0ondUrHdglaq$15sb;uRBh2VphCAQU~5Jl?I)goEIIiS zAtkxSAwr9pmc9M2+)HkV6fRHj77r9|@YR_ExRHxJ{2%wh8VqK&bK&32kw{77g-tg& zgfTTsaTly?7aP5L`CZxz_0w%KTeB!EG>I0lO@w6x0zbsSkN;oS6ER9&{ysE!0cmsL zlQq$~?5=Vtp|8(*b&Rc88_sCzOFdtabW7*^#(<5H_s~p4i-@G2%i_y@AM6x?Y>C1# z-w9J^f#A0pr_x_Kl+4p{3%QC$(UY8umCo2c^vj;ErWN(gRcYfsM$avaYQc%*FUu=; zwoo{lK9-A7ltk#Rxm;d?jc8^HZ%CRYzax_)#hKCo{Jp)4|K_kVT8?Pv)=&-oXwx+e ze>#2OSpw^D)Y(5+uW7`Ir5sxQ)#fcMp8Tmu+4%4FLxFPA`d&tehY*?m#?M$%&5kjm&duJdVi>Cpv6}e_)7?o)H!MU=D!$`dFa*Lyh{#~X7tIa|psC$vy@6%nH}H9s3ZGCY(eFVEaaQ_M2K=hDs3>B3x;};9e8n~>R@_aCmFl*F&T-^v~bR61lYuVv<`s*MNd+#MkuEoG)&LcWoB zenBBWJ+Pc^iF5o+!wr9X*0CXah*H$Q(;zIf_<1)B>JX!+a%rZG3af$9V|+9RF{U>& zjdNL#DiwCAzV%tdhLsoTVW#TP7YA z{*?e9$(^nVhNwbfIy85DT$#R4`Ark8{D}3MS|UD%8?N@9Zt#y5nETJ^!+~LYVz|TV zNCU#MkY&~=X&l5(ge^Yf<)1~fmNnfUa_8Orw;+2wssq|YZjLs0u_l5(soV$I&kSv0 zF`Al5q6*2gRI1_0L%SW{=sg->>=6uxx%*qQnRu?@v19oumwQ8bc}=7M*DNl6SwfnG zqWZq#+A_bXvj@0GK~bz*}lka`>6i)qvT8+rs6Q;#D99OXrd>- zVov)wY9SHdHW!Z7M{?NKIsZV_Ge{@}08|q`+azHUj`TD~o>RF%!kkXOl^`SP&DrcS zi4u+i=SK4$;s2D1`Kz>w&4=#6;?!9l#ZtEQO(A}S*K(`JkW8AL@fFVK*459yNBg`+ z{n>_zi{G^=vfd1MTkrF#@)?Y(b6vkM4>{J0KlXHF8R>R&j(L~+Dr=uRw@R@d zs=7&UaM9G3$o9CGZVk^23Q)2Yw89#S=)YodNMrRwQZ#w~{nIZu%Unojgq@f~#O^(@ zqW8bd1H{1&ysfFAVcR)9a&e}zO-t($3Zf}2M9HLc{EvXC)t4H7aW{!ANQj@WV>R`* z$W#vedJsh9B0Jf**vPr!vn}<@pL0a*0z6M7S(=!b?{lU+XoBh0=RRTrCI$Z z`8c~RRf*6uy_zgNcozS5a}i}6Jkr@!RMh?Bs-Mzs+cg(I&^S9H$Ff1I3w9#zsJ5JJ zmQa~2R=T*;v~#$xJgUV$;ZQq%bV9ctvb9x?K2p=s_pM;K0r5Eh_0?wPo!J#b@*8B0 zhnJOA8^~vpyCi_}PNuZT;JG=9kQu&au!g>Ur;^s@20&Q8%B}wHs0cC==fQt4PY_bt zfC?64I-+>PW{pem2{{BpqHFqr;3G1vzB_HwS)F(|4f?qdJ67kA% zOpJ7NqGR8^votXBcVlKz{lA5+G@btmic%_)c0YgEpfm+ahmZ{0ROa0Bf;(V8XG+i~ zjkSYjT?;W`f~fI6VrJi=JrsKPn$h$TNFWB&5d98<2Q#B87(6zGladRS&oamoJ^*;s< zf;d=pXHDZD0L%+f&JLAng*Vgl!+!5iTb$YXAgcZ@kCNsV#u7DqRT_9o?D=H#r`EWx zOQrW`^43ZLg+=>L%HbRPKyteRSQ67sw_IW1HJq=w2Aq!K`L&YlD(Tj%6%|Iahg2_qHE0fz! z9?9N(Z$5v$#w!}7h_;u^EUiM5w zG)fu_TM9MQ3BiT7&e#AGB3D)VGRytw&qmWw3?UJ)I|!SJ=6_)n2MR#RP|othY79ot zl3e?-ho@%$d-)#bsm1e@JXH>Nx-O7SmPhKITPu-Kh!Pd)3OHIRU)zjHuO8;TF0G0X z+p8;9&+`F#>FsHx^Jh5EcE{KqgsG+p2FrYU;?8dJ9++o`@h89~&|kWwv^yqu=Msrt zHcdd5Y8@eEDlN2L<5ua#>>rh;w@1qBg!SsO*Sq|p6kby|$?7u*0CM}#1_eoOb-Mewm{*MtiCcRoYUMGIf>??JKbkJI%Wh87U5lYLYpFG5VpAg^l zjKsxaeH=8X0Qy6H9LePIp6O+m8t5b~8;3qOsKqz@$b&b)Ei zNj~-E9g!I7^`RCLe%+nkZdhmOwf_GNh^@{uaX2Nh!}Mx1`_NwLeQk=>b2Duc`?6MH zJNP};)O1wq^~PG=N#4?-TVM9b%VQZ;euGgCKT zkrC3H<6SDl1JwG(2R5K66x?{A1Yq#gv&jB-E|oOY-81yG1w-@RZVZY3XmId)xIvY_ zli=&D5YL;^+9z-9pq5sWG6NHKLh6AYp@MFSN6l}AQ)u`*N8%%-*xoMt8vmjZZ?zR4 zw~*1Q4(um*qV96zO*ZI&DT0c+t9#B0w=vTYQayn$zPtiBHAkE6t1L-f=7+Sco$bFz zKd*^~>ZM{1$IAzRxOZFkF>~vU1(l?E27YznDbUB{ip8@n5xZmlDtMykjCkwE{mSqM zcGz`f*L{furZOQPbb#zR5;P&LU+mk6$McpPQOsa;NUbwbN7xx1-!#r0%?;a{s`wdfVlV;74&vza(pR?SnKnuuMdPdX+XPNHf`6~M5{Cwkh4^OT|CgtrtzW!crji{tR{)?_PBG`j8m5dwH^*LAcv%l;k-mQen(fs>H#|wj3x!+ zps@l+=3v#<<)!16NETv?%rS?0%Y45y!19!8o6j*Rt?zs$5bd^1ZW8q&qzny_{x#7I z@VGc80plyW0!6)$<@dSAK7A>&rJQr`xx~t#GZ{3G#f1TT3mAxQ#!!08tJ2ryk%4hR za=m^7l~Fx$y&$R$;TOJT`g39EIw4@YXgZc?PXHisd7CO)i1`2vn0Vcw*6VJxqocWI zW@!F)%n{1(`l`uR&|sWQPK|AR(C^E*>*ulDN|9u)&o#y;$>n6IomDte46cDrFk7(8 zwDTKBnUEJ^&^`g;_~Z}-z1%f1AU*w*aRKl;oy>IIP6o4|c3V6HNiX}HHm^CqKGJ9Y z{!MtEB0IHSXQFe7>zv}lreVmmaKS{I2ZUv8)toaNpNaXf!6&C89%F>s_$PZ}5YOju zwWG`UhtfrhDh7`lZqsId^H2IEW5VPN2=|_or+se%=h?rjh`uQ=T!>Nn(cI=mQXG#G zww;!#OVT$vO~!3LjaP_X{`jRQG5v8$P=Ny;xkRW4YKWv8g$0>d$=cdP!tw5>!6i+(n`GSX{`X0KUJ0tMu$9H`%%WaGN$T{#oqSu zajFgY07GPWXWskvi8Bh*5A+wEUOxnG1ww3mOn!KG+i}>P6F$XQW{OZe7q~ z9*9GGdPYR6=@J!fcoY{4^uCkZiiit>xz}804N<`i8h>d`$Hbj}obASX$4{ zz|MAL9}N?wb;ucqiz;>biAmOv6RppjO8X7{t*fh#*~NyPkoqpZ5} zT`{MQ?)2Pe!sNK$YXNgzCgIwrqHaLkU0sVT6>CM4z)2uI68q#eQobHIaNt_Oq%T}A zV`?BT!&?h6n46z{6979ANBPk9hN!hyj%juzkGbgN3i4 z*seWG@$liphCv*-vE^^DBBkXGoQv($CN7uht^A~WNGe82{&TvoG882A1cKx-WjGDoOXjdyfmh|OcyA2gl&eFTLHrx`U=oO-4w)jb`enUI@0>w3TNuuU6z59W|~iBI2aN3KE2K?%$jjL z0@Oe6LB*rmFHggRXYS4aE1!mCpGAUImEBPwx#sI`P~73Dc%7x`K(d3vfR7$!wnbq3 zK#~ZXi*+Q(8QG|%!IKtj*}>p^ITL$lDsc+;Y>S$PxLMO`iQmTs%6+!^`}w<5rS-Up zM+LK`&RH$DW-Glt&3#y5%7mfGdrp@$M=#^bB4K^m?f=_nrGI!3H{QIsBy+*yT7kQY zRg#OWddk!@Hc-A^_}QVH@G1LqhWO?2Do9#CzrD zFOo;}PliW)N(Xw-&#+e=hl8jbucK~=YLCUMaD}16G($j^IeZy-g ztEG9)SKgdTx-)HfRR=0QmX77a8dabm3{Kgcw7QbglG4X+kBu9g;lO$n;B#h#4Qfee$T){Ap6J9<>HJ^)>7 zN2(QfbF%t1{7n#bM!&yYOtX7(`4c40j{r1NQ_r&$<7}Q2SWSOCLrCSRUM_SOZtDmD zR%~13P~6*OL4mIXo1homveMq!`RI{IVHU$MAskad*CRk9vobY+_zH6ODTRRvwX3-` z4y9KP6+#^2a?8H2XKgCfR#f{N0NM`$_C{e9j=NwIoN5os zxnNB9|7QB+wCj;=+isASzCbgDZAzw^-@&hoPb}c)wjai!dCsf;c43?GppZ7=WoRPAJhO5cmMzZ literal 0 HcmV?d00001 From 762e5f45f8bbfdc1fbdd0ab4c0ab6cfd5803889a Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Mon, 8 Nov 2021 00:36:03 +0800 Subject: [PATCH 746/756] Update UG with new theme --- docs/UserGuide.md | 44 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 7eba07ef4f..1b89590db5 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -27,6 +27,7 @@ when learning how to use **ConTech**.
    + ### Table Of Contents * **[Quick Start](#start)** @@ -48,6 +49,8 @@ when learning how to use **ConTech**.
    +
    + ## Quick Start @@ -68,9 +71,7 @@ This section aims to get you started with using **ConTech**. * `view 1`: Displays all the details of the contact at index `1`. * `rm 1`: Deletes the contact at index `1` in the list. * `exit`: Exits the program. - -
    - + If you have reached this step without any issues, congratulations! You have successfully set up **ConTech**. >:information_source: You are advised to go through the following two sections. @@ -95,6 +96,8 @@ fulfilled. These `flags` include: - `-tw`: for your contact's Twitter handle - `-e`: for your contact's email address +
    + ### Common notations used Throughout the user guide, you will find the following notations: @@ -147,6 +150,10 @@ You now have 1 contact(s). ____________________________________________________________ ``` +**[Back to Table of Contents](#toc)** + +
    + ### Listing all contacts: `ls` @@ -173,6 +180,10 @@ ____________________________________________________________ ____________________________________________________________ ``` +**[Back to Table of Contents](#toc)** + +
    + ### Viewing a contact: `view` Displays all the details saved to a contact in the ConTech Book. @@ -219,6 +230,10 @@ Email: marcus.bo@contech.sg ____________________________________________________________ ``` +**[Back to Table of Contents](#toc)** + +
    + ### Viewing personal contact: `me` Displays all your details saved to the personal contact in the ConTech Book. @@ -240,6 +255,8 @@ Email: marcus.bo@contech.sg ____________________________________________________________ ``` +**[Back to Table of Contents](#toc)** + ### Deleting a contact: `rm` Removes the contact with a specified index from the ConTech Book. The `rm` command can also be used to delete @@ -264,6 +281,8 @@ Command formats: * The `NAME` (denoted by `-n`) *cannot* be deleted. To delete entire contacts, please use `rm `. * If the specified detail is already empty, no deletion will take place for that detail. +
    + `rm all` * Deletes all contacts in the ConTech Book. @@ -324,6 +343,10 @@ ConTech has removed all 2 of your contact(s). ____________________________________________________________ ``` +**[Back to Table of Contents](#toc)** + +
    + ### Editing a contact : `edit` @@ -383,6 +406,10 @@ Telegram: t.me/boryy ____________________________________________________________ ``` +**[Back to Table of Contents](#toc)** + +
    + ### Searching for a contact: `search` @@ -415,6 +442,8 @@ Telegram: t.me/johnlee123 ____________________________________________________________ ``` +**[Back to Table of Contents](#toc)** +
    @@ -462,6 +491,8 @@ ConTech has successfully imported 4 lines ____________________________________________________________ ``` +**[Back to Table of Contents](#toc)** +
    @@ -526,6 +557,8 @@ import: Imports contacts from a CSV Text File. ____________________________________________________________ ``` +**[Back to Table of Contents](#toc)** +
    @@ -544,6 +577,8 @@ We hope you have enjoyed using it. ____________________________________________________________ ``` +**[Back to Table of Contents](#toc)** + ## FAQ **Q**: How do I transfer my data to another computer? @@ -565,6 +600,7 @@ editing the save data files. For adding a large number of contacts at once, the a future revision with more granular controls to allow users to easily handle multiple duplicate contacts when importing. For more information on the implementation, please refer to the [Developer Guide](https://ay2122s1-cs2113t-t09-1.github.io/tp/DeveloperGuide.html#ComingSoon). +**[Back to Table of Contents](#toc)**
    @@ -589,3 +625,5 @@ Delete a contact | `rm ` | `rm 1` Search for a contact | search {-n | -g | -l | -te | -tw | -e} <QUERY> | `search Ashraf`
    `search -g revflash`
    Import contacts from .txt file |`import` | `import` Exit ConTech | `exit` | `exit` + +**[Back to Table of Contents](#toc)** From 08dac1c791a9a65f622d1f558d33f191b689799b Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Mon, 8 Nov 2021 00:49:10 +0800 Subject: [PATCH 747/756] Update to UG and ashraf PPP --- docs/UserGuide.md | 10 ++++------ docs/team/ashrafjfr.md | 2 -- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 1b89590db5..6b53237e1b 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -257,6 +257,8 @@ ____________________________________________________________ **[Back to Table of Contents](#toc)** +
    + ### Deleting a contact: `rm` Removes the contact with a specified index from the ConTech Book. The `rm` command can also be used to delete @@ -281,11 +283,12 @@ Command formats: * The `NAME` (denoted by `-n`) *cannot* be deleted. To delete entire contacts, please use `rm `. * If the specified detail is already empty, no deletion will take place for that detail. -
    `rm all` * Deletes all contacts in the ConTech Book. +
    + Expected outcome of usages: * Remove selected contact: @@ -298,8 +301,6 @@ Delete this contact? (y/n) 0. Name: Alex Lee Github: github.com/alexlee -Email: alex.lee@contech.sg -Telegram: t.me/alex133 ____________________________________________________________ y @@ -309,8 +310,6 @@ You now have 2 contact(s). ____________________________________________________________ ``` -
    - * Remove specific details of a contact: ``` @@ -577,7 +576,6 @@ We hope you have enjoyed using it. ____________________________________________________________ ``` -**[Back to Table of Contents](#toc)** ## FAQ diff --git a/docs/team/ashrafjfr.md b/docs/team/ashrafjfr.md index 0e357e811a..be4291717d 100644 --- a/docs/team/ashrafjfr.md +++ b/docs/team/ashrafjfr.md @@ -57,5 +57,3 @@ The link to the Developer Guide (DG) can be found [here](https://ay2122s1-cs2113 ### Review/mentoring contributions - Reviewed PRs and ensured overall code quality/formatting was up to standard -### Community -- Reported Bugs during PE Dry Run. From 0044343bc9b0043e90925b37f5f3811a9c0de179 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Mon, 8 Nov 2021 01:00:40 +0800 Subject: [PATCH 748/756] Update to UG and DG for pdf conversion --- docs/DeveloperGuide.md | 25 +++++++++++++++++++++++-- docs/UserGuide.md | 1 - 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 406a7a1f52..78d347547b 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -1,4 +1,4 @@ -# Developer Guide +## Developer Guide ### Table of Content - [Acknowledgements](#acknowledgements) @@ -36,6 +36,7 @@ - [Searching for a contact](#testing-search) - [Importing contacts](#testing-import) +
    ## Acknowledgements @@ -83,6 +84,8 @@ ConTech comprises five main components, namely: - `ContactList`: Data structure to store `Contact`s while running ConTech. - `Storage`: Reads from and writes to [`LocalStorage`](#local-storage). +
    + **How the architecture components interact with each other** The five main components interact with each other, as shown in the sequence diagram below @@ -157,6 +160,8 @@ The currently supported contact details are provided in the table below: |`-tw`|Twitter handle| |`-e`|Email| +
    + ### Adding a contact: `add` This feature is processed using `AddContactCommand`. This feature allows a user to add a contact to their contact list. The user is able to add a contact by entering a command in the form of `add <-n> {-g } {-l } @@ -181,6 +186,8 @@ executed in `ConTech`. The sequence diagram below illustrates the process of exe ![Add Sequence Diagram](images/AddContactCommandSequenceDiagram.png) +
    + ### Viewing a contact: `view` This feature is processed using `ViewContactCommand`. Whenever a user wants to view a specific contact from the contact list, user can input `view INDEX` with the index of the desired contact displayed from the `ls` feature. @@ -216,6 +223,8 @@ contact list to be edited.The sequence diagram below shows how the String array ![Edit Sequence Diagram](images/EditContactParserSequenceDiagram.png) +
    + Once the user's input is parsed and the index specified is obtained, an `EditContactCommand` with the specified parameters will then be created and executed in `ConTech`. The sequence diagram below depicts the execution of `EditContactCommand` for the index `me` as well as an invalid index `all`. @@ -244,6 +253,8 @@ A `DeleteContactCommand` with the specified parameters will then be created in t ![Delete Sequence Diagram](images/DeleteContactCommandSequenceDiagram.png) +
    + To _delete all contacts_, a user must enter the command `rm all`. The sequence diagram below shows how the removal of all contacts works. Before any deletion, the user will be @@ -264,6 +275,8 @@ been executed. If user cancels deletion, a message is printed to show that the d ![Delete Selected Sequence Diagram](images/DeleteSelectedContact.png) +
    + To _delete specific details_ of a selected contact, a user must enter a command in the form `rm {-g} {-l} {-te} {-tw} {-e}`. @@ -287,6 +300,8 @@ methods respectively. The sequence diagram below shows how the required paramete ![Search Sequence Diagram](images/SearchContactParserSequenceDiagram.png) +
    + A `SearchContactCommand` with the specified parameters will then be created and executed in `ConTech`. The sequence diagram below shows how the `SearchContactCommand` is executed. @@ -311,6 +326,8 @@ If the list is not empty the method `listAllContacts` uses a loop to get the `Co every available index and print it using the `printContactWithIndex` method in `TextUi` class. +
    + ### Importing contacts: `import` This feature is processed using the `ImportContactCommand`. This feature allows a user to import contacts over from a text file containing comma-separated values (CSV). @@ -342,7 +359,7 @@ Current implementation ideas include: - allow Windows-style duplicate handling (Ignore, Ignore all, Cancel) - summarise every single duplicate and give user a one time confirmation to add/discard (no granularity) - +
    ### Index Parser @@ -464,6 +481,8 @@ exploratory testing. ____________________________________________________________ ``` +
    + ### Adding a contact 1. Adding a contact with all fields 1. Test case: `add -n Alex Lee -g alexlee -te alexlee -tw alexl33 -e alex.lee@email.com -l alexlee`
    @@ -741,6 +760,8 @@ exploratory testing. ____________________________________________________________ ``` +
    + ### Deleting a contact 1. Deleting a contact that is in the contact list 1. Prerequisites: List all contacts using the `ls` command to find the index of specific contact. diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 6b53237e1b..46c02d61ec 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -319,7 +319,6 @@ Delete the following fields for Le Zong? (y/n) Github: github.com/lezongmun Telegram: t.me/lezongg -Email: lezongmun@gmail.com ____________________________________________________________ y From 22feab5e8721cc885b1162d8e5fb89777c154c12 Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Mon, 8 Nov 2021 01:07:37 +0800 Subject: [PATCH 749/756] Update DG for pdf conversion --- docs/DeveloperGuide.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 78d347547b..99a138fa75 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -1,5 +1,3 @@ -## Developer Guide - ### Table of Content - [Acknowledgements](#acknowledgements) - [Common Notations In DG](#notations) @@ -847,8 +845,6 @@ exploratory testing. Github: github.com/alexlee Email: alex.lee@email.com Telegram: t.me/alexlee - LinkedIn: linkedin.com/in/alexlee - Twitter: twitter.com/alexl33 ____________________________________________________________ ``` @@ -862,8 +858,6 @@ exploratory testing. Github: github.com/alexlee Email: alex.lee@email.com Telegram: t.me/alexlee - LinkedIn: linkedin.com/in/alexlee - Twitter: twitter.com/alexl33 ____________________________________________________________ ``` From fe6f2d5ca2e7edc07266a129b80926bb492efc8c Mon Sep 17 00:00:00 2001 From: Ashraf Jaffar Date: Mon, 8 Nov 2021 01:12:22 +0800 Subject: [PATCH 750/756] Update Dg for pdf --- docs/DeveloperGuide.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 99a138fa75..9f3ffa3cbd 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -1,3 +1,4 @@ +### Developer Guide ### Table of Content - [Acknowledgements](#acknowledgements) - [Common Notations In DG](#notations) From 145dfc30676584d905d31e2a7472720697a83628 Mon Sep 17 00:00:00 2001 From: lezong Date: Mon, 8 Nov 2021 01:18:19 +0800 Subject: [PATCH 751/756] Update PPP --- docs/team/lezongmun.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/team/lezongmun.md b/docs/team/lezongmun.md index e49b7e0b2f..80eba36059 100644 --- a/docs/team/lezongmun.md +++ b/docs/team/lezongmun.md @@ -26,15 +26,13 @@ The code written by me (`lezongmun`) can be found [here](https://nus-cs2113-ay21 - `AddPersonalContactParser.java`: Parser that is responsible for prompting users to input their personal contact details and parsing them into `Contact` details for their personal contact - `IndexParser`: Parser that is responsible for obtaining the `Contact` index from a user input command string. Used - for commands involving `Contact` indexes like `rm`, `view` and `edit` commands. + for commands involving `Contact` ### Contributions to UG The link to the User Guide (UG) can be found [here](https://ay2122s1-cs2113t-t09-1.github.io/tp/UserGuide.html). - Added documentation for features `me` and `rm` - Updated documentation (command formats, usages, examples) for features with `all` and `me` as inputs -
    - ### Contributions to DG The link to the Developer Guide (DG) can be found [here](https://ay2122s1-cs2113t-t09-1.github.io/tp/DeveloperGuide.html). - Added implementation details and class diagram for `Storage` system From dc4b41f21509bdef806f9990a278fa33d649a711 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Mon, 8 Nov 2021 01:36:35 +0800 Subject: [PATCH 752/756] Update marcusbory.md --- docs/team/marcusbory.md | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/docs/team/marcusbory.md b/docs/team/marcusbory.md index 368e35ecea..1471c5fdf7 100644 --- a/docs/team/marcusbory.md +++ b/docs/team/marcusbory.md @@ -36,8 +36,6 @@ The link to the User Guide (UG) can be found [here](https://ay2122s1-cs2113t-t09 - Added documentation for `import` function - Updated documentation formatting and overall readability -
    - ### Contributions to DG The link to the Developer Guide (DG) can be found [here](https://ay2122s1-cs2113t-t09-1.github.io/tp/DeveloperGuide.html). - Added documentation for `add` function @@ -45,17 +43,14 @@ The link to the Developer Guide (DG) can be found [here](https://ay2122s1-cs2113 - Added UML diagrams for all the above-mentioned features ### Team-based tasks -- Hosted and conducted weekly brainstorming session during ideation phases (V1.0, V2.0, V2.1) +- Conducted weekly brainstorming session during ideation phases (V1.0, V2.0, V2.1) - Set up the Github team organisation and repository -- Maintained issue tracker (ensured that PRs were tagged to according Milestones and labels) -- Updated User Guide (UG) and Developer Guide (DG) documentation that were not specific to any feature: - - UG: Added sections "How to use the User Guide", "Common Notations used" - - DG: Set up DG with System Architecture diagram, Product Scope, Non-functional Requirements +- Maintained issue tracker (tagged PRs according to Milestones and labels) +- Updated User Guide (UG) and Developer Guide (DG) generic documentation: + - UG: Added "How to use the User Guide", "Common Notations used" + - DG: Set up DG, System Architecture diagram, Product Scope, Non-functional Requirements - Refactored entire codebase (on 27/10/21) to improve code quality (apply SLAP) and fix any coding standard violations - Updated `runtest.bat` and `runtest.sh` to automatically delete data files, and work with `import` feature ### Review/mentoring contributions - Reviewed PRs and ensured overall code quality/formatting was up to standard - -### Community -- Reported Bugs during PE Dry Run. From b106517ee626da194678c3259ff4eb431876404d Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Mon, 8 Nov 2021 01:42:06 +0800 Subject: [PATCH 753/756] Update PPP --- docs/team/marcusbory.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/team/marcusbory.md b/docs/team/marcusbory.md index 1471c5fdf7..edd5e8cdb0 100644 --- a/docs/team/marcusbory.md +++ b/docs/team/marcusbory.md @@ -10,7 +10,6 @@ iteration so that we were able to comfortably deliver our features. ## Summary of contributions ### Code contributed The code written by me (`marcusbory`) can be found [here](https://nus-cs2113-ay2122s1.github.io/tp-dashboard/?search=marcusbory&sort=groupTitle&sortWithin=title&timeframe=commit&mergegroup=&groupSelect=groupByRepos&breakdown=true&checkedFileTypes=docs~functional-code~test-code~other&since=2021-09-25&tabOpen=true&tabType=authorship&tabAuthor=marcusbory&tabRepo=AY2122S1-CS2113T-T09-1%2Ftp%5Bmaster%5D&authorshipIsMergeGroup=false&authorshipFileTypes=docs~functional-code~test-code~other&authorshipIsBinaryFileTypeChecked=false). -
    ### Enhancements implemented 1. Application System Architecture From f94f319ccc8563dac58e82e6dd185a8a6ee111cf Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Mon, 8 Nov 2021 10:01:11 +0800 Subject: [PATCH 754/756] Update PPP --- docs/team/ng-andre.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/docs/team/ng-andre.md b/docs/team/ng-andre.md index 45aacd81cc..bbfe377185 100644 --- a/docs/team/ng-andre.md +++ b/docs/team/ng-andre.md @@ -11,8 +11,7 @@ iteration so that we were able to comfortably deliver our features. ## Summary of Contributions ### Code Contributed -The code written by me (`ng-andre`) can be found [here](https://nus-cs2113-ay2122s1.github.io/tp-dashboard/?search=ng-andre&sort=groupTitle&sortWithin=title&since=2021-09-25&timeframe=commit&mergegroup=&groupSelect=groupByRepos&breakdown=falsehttps://nus-cs2113-ay2122s1.github.io/tp-dashboard/?search=ng-andre&sort=groupTitle&sortWithin=title&since=2021-09-25&timeframe=commit&mergegroup=&groupSelect=groupByRepos&breakdown=false). - +The code written by me (`ng-andre`) can be found [here](https://nus-cs2113-ay2122s1.github.io/tp-dashboard/?search=ng-andre&sort=groupTitle&sortWithin=title&since=2021-09-25&timeframe=commit&mergegroup=&groupSelect=groupByRepos&breakdown=falsehttps://nus-cs2113-ay2122s1.github.io/tp-dashboard/?search=ng-andre&sort=groupTitle&sortWithin=title&since=2021-09-25&timeframe=commit&mergegroup=&groupSelect=groupByRepos&breakdown=false). ### Enhancements Implemented @@ -29,12 +28,12 @@ The code written by me (`ng-andre`) can be found [here](https://nus-cs2113-ay212 - `EditContactParser.java`: Parses user input, specified index and specified flags, and creates a syntactically valid `EditContactCommand` to be executed - `SearchContactParser.java`: Parses user input for search query and optional flag, and creates a syntactically valid `SearchContactCommand` to be executed - `IndexParser.java`: Parses the index specified by the user input for all commands and returns the corresponding `int` value - - + ### Contributions to the UG - Added documentation for `edit` function - Added documentation for `search` function - Updated documentation formatting and overall readability +- Fix formatting errors and ensured overall consistency for UG ### Contributions to the DG - Added documentation for `edit` function @@ -42,7 +41,9 @@ The code written by me (`ng-andre`) can be found [here](https://nus-cs2113-ay212 - Added UML diagrams for all the above-mentioned features ### Contributions to team-based tasks -- Handled release management and published v1.0 and v2.0 releases +- Handled release management and published v1.0, v2.0 and v2.1 releases +- Hosted and attended weekly team meetings for issue review and work allocation +- Regular debugging and testing of application to ensure basic functionality is present - Updated User Guide (UG) and Developer Guide (DG) documentation that were not specific to any feature: - Reviewed and updated overall User Guide and fixed inconsistencies between UG and error messages in application @@ -50,3 +51,5 @@ The code written by me (`ng-andre`) can be found [here](https://nus-cs2113-ay212 - Reviewed PRs and ensured overall code quality/formatting was up to standard ### Contributions beyond the project team +- Reported bugs during PE Dry Run +- Discussed with other teams and gave suggestions for code improvements \ No newline at end of file From 09f3fd9f3d255731b9755a6c518c6841ca2b99d0 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Mon, 8 Nov 2021 18:14:49 +0800 Subject: [PATCH 755/756] Update PPP --- docs/team/mayankp291.md | 46 +++++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/docs/team/mayankp291.md b/docs/team/mayankp291.md index 564fc465cc..59546d0c0b 100644 --- a/docs/team/mayankp291.md +++ b/docs/team/mayankp291.md @@ -19,35 +19,51 @@ found [here](https://nus-cs2113-ay2122s1.github.io/tp-dashboard/?search=mayank&s ### Enhancements implemented -1. `list` feature - - Added the feature to list all contacts with their index and name. -2. Parsers +1. Parsers - `RegexParser.java`: Add Input Validation for contact fields added to ConTech. Covers fields - Name, GitHub, Email, - Twitter and Telegram. The usernames are checked against requirements from the respectable companies. + Twitter and Telegram. The fields for GitHub, Twitter and Telegram are checked against requirements from the + respective companies. For Email it is checked against the [RFC 5322](https://www.ietf.org/rfc/rfc5322.txt) + standard. + - `MainParser.java` : Update exception handling and implement method to handle regex exceptions. +2. `ls` feature + - Feature to list all contacts with their index and name. 3. Exception handling - - Add exceptions to cover more test cases and provide clear error messages. -4. Sorting of contacts + - Update exception handling for command executions and regex checks. + - Streamline exceptions to cover more test cases and provide clearer and helpful error messages. +5. Sorting of contacts - Store contacts sorted in ascending order in the `ContactList` structure. - - Sort after every contact is added, edited, or imported. -5. System testing and writing tests - - Written tests for various functions and increase test coverage. - - Tested every component and made sure the program worked as expected + - Sorted after contacts are added, edited, or imported. +6. System testing and writing tests + - Write JUnit and IO tests for various commands to increase stability and test coverage. + - Stress test every component to make sure the program does not fail under unexpected circumstances. ### Contributions to UG -The link to the User Guide (UG) can be found [here](https://ay2122s1-cs2113t-t09-1.github.io/tp/UserGuide.html). +The link to the User Guide (UG) can be found [here](https://ay2122s1-cs2113t-t09-1.github.io/tp/UserGuide.html) +- Added documentation for `ls` and `exit` features +- Added Command Summary +- Ensured overall consistency for UG ### Contributions to DG -The link to the Developer Guide (DG) can be found [here](https://ay2122s1-cs2113t-t09-1.github.io/tp/DeveloperGuide. -html). +The link to the Developer Guide (DG) can be found [here](https://ay2122s1-cs2113t-t09-1.github.io/tp/DeveloperGuide.html) +- Added documentation for `ls` +- Added Sequence Diagrams for `ls` and System Architecture +- Added Design Considerations ### Team-based tasks -- Attended and contributed to weekly brainstorming session during ideation phases (V1.0, V2.0, V2.1) +- Conducted weekly team meetings for issue review and work allocation - Maintained issue tracker (ensured that PRs were tagged to according Milestones and labels) +- Conducted regular system testing and debugging to find bugs and ensure system worked as expected +- Consistently updated exceptions and error messages for a better user experience +- Solved bugs from PE Dry Run - Updated gradle and testing scripts +### Review/mentoring contributions + +- Reviewed PRs and provided suggestions to improve overall code quality/formatting + ### Community -Reported 13 Bugs during PE Dry Run and suggested ways to solve them. +- Reported 13 Bugs during PE Dry Run and suggested ways to solve them From 8b45a001edc151fc6aead66a7e63004706aed2cc Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Mon, 8 Nov 2021 18:28:33 +0800 Subject: [PATCH 756/756] Add author tags --- docs/UserGuide.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 46c02d61ec..117ea640d6 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -154,6 +154,8 @@ ____________________________________________________________
    + + ### Listing all contacts: `ls` @@ -179,7 +181,7 @@ ____________________________________________________________ 4. Mayank ____________________________________________________________ ``` - + **[Back to Table of Contents](#toc)**
    @@ -601,6 +603,8 @@ For more information on the implementation, please refer to the [Developer Guide
    + + ## Command Summary Below is a concise summary of frequently used commands in ConTech.
  • 8t~{aLUrQwTXbYHGg8ka@X2q+|CibJ6hN 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 tB4Ok3qS>?fMnq+k92V9QCHRjT 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 From 3981242dab83af346b75a420c81ffbb5c7beb04a Mon Sep 17 00:00:00 2001 From: lezong Date: Mon, 25 Oct 2021 20:01:22 +0800 Subject: [PATCH 445/756] Add rm feature in user guide --- docs/UserGuide.md | 93 ++++++++++++++++++++++++++++-- src/main/java/seedu/ui/TextUi.java | 10 +++- 2 files changed, 96 insertions(+), 7 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index c0077e3e7c..fe657b16e3 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -16,6 +16,7 @@ time required to look up for various usernames when working with colleagues. * **[Adding a contact : `add`](#add)** * **[Listing all contacts : `list`](#list)** * **[Viewing a contact : `view`](#view)** + * **[Viewing personal contact : `me`](#me)** * **[Deleting a contact : `rm`](#delete)** * **[Editing a contact : `edit`](#edit)** * **[Searching for a contact : `search`](#search)** @@ -70,17 +71,24 @@ list: Displays the name of all saved contacts. edit: Edit any parameter in an existing contact. Parameters: INDEX -n NAME -g GITHUB -e EMAIL -te TELEGRAM -l LINKEDIN -tw TWITTER Note: Parameters need not be in order and are optional except for INDEX. - Example: edit 1 -e john.doe@email.com + "me" is used as the INDEX for personal contact. + Examples: edit 1 -e john.doe@email.com + edit me -e john.doe@email.com view: Displays all details for index specified contact. Parameter: INDEX Note: Index starts from 0. Example: view 2 +me: Displays all details for personal contact. + Example: me + rm: Deletes the index specified contact. Parameter: INDEX Note: Index starts from 0. - Example: rm 0 + "-rf" is used as the INDEX to delete all contacts. + Examples: rm 0 + rm -rf search: Search for a contact containing a specified query. Note: Flags may be used to specify a detail type to search. @@ -121,9 +129,73 @@ ____________________________________________________________ Telegram: t.me/alexl33 ____________________________________________________________ ``` + +### Viewing personal contact: `me` +Displays all the details saved to the personal contact in the ConTech Book. + +Usage: `me` +* Displays all the details of the personal contact. + +Expected outcome of usage: +``` +me +____________________________________________________________ +Name: Marcus Bo +Github: github.com/marcusboreee +Email: marcus.bo@contech.sg +Telegram: t.me/m4rcusb0 +____________________________________________________________ +``` ### Deleting a contact: `rm` +Removes the contact with a specified index from the ConTech Book. Before any deletion, ConTech Book will +display the details of the specified contact to be deleted, and prompt user to confirm deletion. + +Usages: + +`rm INDEX` +* Deletes the contact with the specified `INDEX`. +* The index refers to the index number shown in the displayed contact list. +* The index must be within the range of indexes displayed in the contact list _(zero-based)_. + +`rm -rf` +* Deletes all contacts in the ConTech Book + +Expected outcome of usages: +* Remove selected contact: +``` +rm 0 +____________________________________________________________ +Delete this contact? (y/n) +0. Alex Lee +Github: github.com/alexlee +Email: alex.lee@contech.sg +Telegram: t.me/alex133 +____________________________________________________________ +``` +``` +y +____________________________________________________________ +ConTech has removed the specified contact: Alex Lee +You now have 2 contact(s). +____________________________________________________________ +``` + +* Remove all contacts: + +``` +rm -rf +____________________________________________________________ +Delete all of your contacts? (y/n) +____________________________________________________________ +``` +``` +y +____________________________________________________________ +ConTech has removed all 2 of your contact(s). +____________________________________________________________ +``` ### Editing a contact : `edit` @@ -131,6 +203,9 @@ ____________________________________________________________ ### Searching for a contact: `search` + +### Searching for a contact: `search` + ### Importing contacts: `import` @@ -143,8 +218,16 @@ ____________________________________________________________ **A**: {your answer here} -## Command Summary -{Give a 'cheat sheet' of commands here} +## Command Summary + +Action | Format | Examples +--------|------------|--------- +| | +| | +| | + + + +-------------------------------------------------------------------------------------------------------------------- -* Add todo `todo n/TODO_NAME d/DEADLINE` diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 0b8339b4e5..c398a9f115 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -228,15 +228,21 @@ public static void helpMessage() { + "edit: Edit any parameter in an existing contact.\n" + " Parameters: INDEX -n NAME -g GITHUB -e EMAIL -te TELEGRAM -l LINKEDIN -tw TWITTER\n" + " Note: Parameters need not be in order and are optional except for INDEX.\n" - + " Example: edit 1 -e john.doe@email.com\n\n" + + " \"me\" is used as the INDEX for personal contact.\n" + + " Examples: edit 1 -e john.doe@email.com\n" + + " edit me -e john.doe@email.com\n\n" + "view: Displays all details for index specified contact.\n" + " Parameter: INDEX\n" + " Note: Index starts from 0.\n" + " Example: view 2\n\n" + + "me: Displays all details for personal contact.\n" + + " Example: me\n\n" + "rm: Deletes the index specified contact.\n" + " Parameter: INDEX\n" + " Note: Index starts from 0.\n" - + " Example: rm 0\n\n" + + " \"-rf\" is used as the INDEX to delete all contacts.\n" + + " Examples: rm 0\n" + + " rm -rf\n\n" + "search: Search for a contact containing a specified query.\n" + " Note: Flags may be used to specify a detail type to search.\n" + " If no flag is specified, contact name is searched by default.\n" From 6c160707e82539bd84e7d099259b39bf21e59a4e Mon Sep 17 00:00:00 2001 From: lezong Date: Mon, 25 Oct 2021 20:04:00 +0800 Subject: [PATCH 446/756] Add me feature in user guide --- docs/UserGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index fe657b16e3..9e33dd8a1a 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -141,7 +141,7 @@ Expected outcome of usage: me ____________________________________________________________ Name: Marcus Bo -Github: github.com/marcusboreee +Github: github.com/marcusbohre Email: marcus.bo@contech.sg Telegram: t.me/m4rcusb0 ____________________________________________________________ From f52b13c2cc9a27070553b54fa4120104c79377b7 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Mon, 25 Oct 2021 20:20:40 +0800 Subject: [PATCH 447/756] Update user guide for search and edit --- docs/UserGuide.md | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index c0077e3e7c..ea934d5145 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -128,9 +128,55 @@ ____________________________________________________________ ### Editing a contact : `edit` +Edits the details of a specified contact in the ConTech Book. + +Usage: `edit INDEX -FLAG DETAIL` + +- Up to six `FLAGS` and `DETAILS` can be specified in any order +- The index refers to the index number shown in the displayed contact list. +- The index must be within the range of indexes displayed in the contact list (zero-based). + +Expected outcome of usage: +``` +edit 0 -n John Lee -g johnlee -te johnlee123 -e john.lee@contech.sg +____________________________________________________________ +0. John Lee + Github: github.com/johnlee + Email: john.lee@contech.sg + Telegram: t.me/johnlee123 +____________________________________________________________ +``` + ### Searching for a contact: `search` +Search the ConTech Book for a contact whose details contain the specified query. + +Usage: `search [-FLAG] QUERY` + +- Only one flag can be specified. +- If no flag is specified, the default search field is contact name. +- The search query is not case-sensitive. +- All contacts with the specified field containing the search query will be displayed in view format. + +Expected outcome of usage: +``` +search -g lee +____________________________________________________________ +0. Alex Lee + Github: github.com/alexlee + Email: alex.lee@contech.sg + Telegram: t.me/alexl33 +____________________________________________________________ + +____________________________________________________________ +1. John Lee + Github: github.com/johnlee + Email: john.lee@contech.sg + Telegram: t.me/johnlee123 +____________________________________________________________ +``` + ### Importing contacts: `import` From 19f549497d94f0218e7928d0c815404ee6916921 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Mon, 25 Oct 2021 20:20:46 +0800 Subject: [PATCH 448/756] Update list command to ls --- src/main/java/seedu/parser/MainParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index e2ac58d6a7..1f5aca1805 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -34,7 +34,7 @@ public class MainParser { private static final String DELETE_CONTACT_COMD = "rm"; private static final String VIEW_CONTACT_COMD = "view"; private static final String EXIT_COMD = "exit"; - private static final String LIST_COMD = "list"; + private static final String LIST_COMD = "ls"; private static final String HELP_COMD = "help"; private static final String SEARCH_COMD = "search"; private static final String IMPORT_COMD = "import"; From 660861b734191223243c5f432b59a025f697b945 Mon Sep 17 00:00:00 2001 From: lezong Date: Mon, 25 Oct 2021 20:48:15 +0800 Subject: [PATCH 449/756] Change rm -rf to rm all --- docs/UserGuide.md | 12 ++++++------ src/main/java/seedu/parser/IndexParser.java | 2 +- src/main/java/seedu/ui/TextUi.java | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 9e33dd8a1a..4c849082bf 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -86,9 +86,9 @@ me: Displays all details for personal contact. rm: Deletes the index specified contact. Parameter: INDEX Note: Index starts from 0. - "-rf" is used as the INDEX to delete all contacts. + "all" is used as the INDEX to delete all contacts. Examples: rm 0 - rm -rf + rm all search: Search for a contact containing a specified query. Note: Flags may be used to specify a detail type to search. @@ -159,7 +159,7 @@ Usages: * The index refers to the index number shown in the displayed contact list. * The index must be within the range of indexes displayed in the contact list _(zero-based)_. -`rm -rf` +`rm all` * Deletes all contacts in the ConTech Book Expected outcome of usages: @@ -185,7 +185,7 @@ ____________________________________________________________ * Remove all contacts: ``` -rm -rf +rm all ____________________________________________________________ Delete all of your contacts? (y/n) ____________________________________________________________ @@ -223,8 +223,8 @@ ____________________________________________________________ Action | Format | Examples --------|------------|--------- -| | -| | +View personal contact|`me`| `me` +Delete contact|`rm INDEX`
    `rm all`| `rm 0`
    `rm all` | | diff --git a/src/main/java/seedu/parser/IndexParser.java b/src/main/java/seedu/parser/IndexParser.java index cc470b84e9..eb1d15e333 100644 --- a/src/main/java/seedu/parser/IndexParser.java +++ b/src/main/java/seedu/parser/IndexParser.java @@ -14,7 +14,7 @@ public class IndexParser { private static final int COMD_INDEX_LENGTH = 2; private static final String PERSONAL_CONTACT_INDEX = "me"; private static final int PERSONAL_CONTACT_ID = -1; - private static final String REMOVE_ALL_INDEX = "-rf"; + private static final String REMOVE_ALL_INDEX = "all"; private static final int REMOVE_ALL_ID = -2; diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index c398a9f115..47d8c958d2 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -240,9 +240,9 @@ public static void helpMessage() { + "rm: Deletes the index specified contact.\n" + " Parameter: INDEX\n" + " Note: Index starts from 0.\n" - + " \"-rf\" is used as the INDEX to delete all contacts.\n" + + " \"all\" is used as the INDEX to delete all contacts.\n" + " Examples: rm 0\n" - + " rm -rf\n\n" + + " rm all\n\n" + "search: Search for a contact containing a specified query.\n" + " Note: Flags may be used to specify a detail type to search.\n" + " If no flag is specified, contact name is searched by default.\n" From 7a5a2289b6139fa4ccca63dc882281b33b8f25ab Mon Sep 17 00:00:00 2001 From: lezong Date: Tue, 26 Oct 2021 00:02:29 +0800 Subject: [PATCH 450/756] Fix JUnit tests --- src/test/java/seedu/parser/MainParserTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/seedu/parser/MainParserTest.java b/src/test/java/seedu/parser/MainParserTest.java index 29e2d85ca1..512a5f376a 100644 --- a/src/test/java/seedu/parser/MainParserTest.java +++ b/src/test/java/seedu/parser/MainParserTest.java @@ -55,7 +55,7 @@ public void parseDeleteCommand_validIndex_expectDeleteContactIndexMatch() { @Test public void parseDeleteCommand_validDeleteAllIndex_expectDeleteAddIdMatch() { - String testIndex = "-rf"; + String testIndex = "all"; int testId = -2; testUserInput = "rm " + testIndex; final DeleteContactCommand testResultCommand = getParsedCommand(testUserInput, DeleteContactCommand.class); From ae98fc7a2225a8894076c2bc7dabb81daa8d6c4d Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 26 Oct 2021 00:07:46 +0800 Subject: [PATCH 451/756] Replace all occurences of list with ls --- docs/UserGuide.md | 10 +++++----- src/main/java/seedu/ui/TextUi.java | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index ea934d5145..9e0607a816 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -14,7 +14,7 @@ time required to look up for various usernames when working with colleagues. * **[Features](#features)** * **[Viewing help : `help`](#help)** * **[Adding a contact : `add`](#add)** - * **[Listing all contacts : `list`](#list)** + * **[Listing all contacts : `ls`](#list)** * **[Viewing a contact : `view`](#view)** * **[Deleting a contact : `rm`](#delete)** * **[Editing a contact : `edit`](#edit)** @@ -38,7 +38,7 @@ time required to look up for various usernames when working with colleagues. Some example commands you can try: * `add -n Alex Lee -g alexlee -e alex.lee@contech.sg -te alexl33`: Adds a contact named `Alex Lee` to the ConTech Book. - * `list`: Lists all contacts. + * `ls`: Lists all contacts. * `view 1`: Displays all the details of the contact at index `1`. * `rm 1`: Deletes the contact at index `1` in the list. * `exit`: Exits the program. @@ -64,8 +64,8 @@ add: ConTech adds the specified contact with provided parameters. Note: Parameters need not be in order and are optional except for NAME. Example: add -n John Doe -g johndoecoder -e john@email.com -te johndoe -list: Displays the name of all saved contacts. - Example: list +ls: Displays the name of all saved contacts. + Example: ls edit: Edit any parameter in an existing contact. Parameters: INDEX -n NAME -g GITHUB -e EMAIL -te TELEGRAM -l LINKEDIN -tw TWITTER @@ -100,7 +100,7 @@ ____________________________________________________________ ### Adding a contact: `add` -### Listing all contacts: `list` +### Listing all contacts: `ls` ### Viewing a contact: `view` diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index f20229d2e5..9db8216b7d 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -212,8 +212,8 @@ public static void helpMessage() { + " Parameters: -n NAME -g GITHUB -e EMAIL -te TELEGRAM -l LINKEDIN -tw TWITTER\n" + " Note: Parameters need not be in order and are optional except for NAME.\n" + " Example: add -n John Doe -g johndoecoder -e john@email.com -te johndoe\n\n" - + "list: Displays the name of all saved contacts.\n" - + " Example: list\n\n" + + "ls: Displays the name of all saved contacts.\n" + + " Example: ls\n\n" + "edit: Edit any parameter in an existing contact.\n" + " Parameters: INDEX -n NAME -g GITHUB -e EMAIL -te TELEGRAM -l LINKEDIN -tw TWITTER\n" + " Note: Parameters need not be in order and are optional except for INDEX.\n" From 5b572cb70440d0069e53d99f1bd23bd1f0151497 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 26 Oct 2021 00:26:54 +0800 Subject: [PATCH 452/756] Update UG list command --- docs/UserGuide.md | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index c0077e3e7c..4b498d6525 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -102,6 +102,30 @@ ____________________________________________________________ ### Listing all contacts: `list` +Lists all the saved contacts with the index and contact name. + +Usage: `list` +* The indexes start from 0, this is done as computing professionals + are more familiar with index start from 0. + +Expected outcome of usage: + +``` +____________________________________________________________ +ConTech has 7 contacts stored. +Here's the list : +____________________________________________________________ + +0. Andre +1. Marcus +2. Le Zong +3. Mayank +4. George +5. Jim +6. Akshay +____________________________________________________________ +``` + ### Viewing a contact: `view` Displays all the details saved to a contact in the ConTech Book. @@ -141,7 +165,7 @@ ____________________________________________________________ **Q**: How do I transfer my data to another computer? -**A**: {your answer here} +**A**: ## Command Summary From a957cae3416082be6feb228b75abc7d90caf008c Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 26 Oct 2021 00:38:56 +0800 Subject: [PATCH 453/756] Add Command Summary --- docs/UserGuide.md | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 4b498d6525..5fda90fa98 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -169,6 +169,16 @@ ____________________________________________________________ ## Command Summary -{Give a 'cheat sheet' of commands here} - -* Add todo `todo n/TODO_NAME d/DEADLINE` +Action | Command Format | Example +--- | --- | --- | +List all valid commands and usage | `help` | `help` +Add a new contact| `add -n -g -e +-te -l -tw ` | `add -n John Doe +-g johndoecoder -e john@email.com -te johndoe` +List all contacts | `deadline /by ` | `deadline submit ip jar /by 2021-10-02 22:20` +View a contact| `list` | `list` +Edit a contact| `event /at ` | `event graduation party /at 2021-11-01 18:10` +Delete a contact | `done ` | `done 2` +Search for a contact| `find ` | `find homework` +Import contacts from .txt file|`import` | `import` +Exit duke | `bye` | `bye` From f587d525c64e293f10d3dd5f2b41716c2a209a57 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 26 Oct 2021 00:40:36 +0800 Subject: [PATCH 454/756] Fix table formatting --- docs/UserGuide.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 5fda90fa98..a3820de1ee 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -172,9 +172,7 @@ ____________________________________________________________ Action | Command Format | Example --- | --- | --- | List all valid commands and usage | `help` | `help` -Add a new contact| `add -n -g -e --te -l -tw ` | `add -n John Doe --g johndoecoder -e john@email.com -te johndoe` +Add a new contact| `add -n -g -e -te -l -tw ` | `add -n John Doe -g johndoecoder -e john@email.com -te johndoe` List all contacts | `deadline /by ` | `deadline submit ip jar /by 2021-10-02 22:20` View a contact| `list` | `list` Edit a contact| `event /at ` | `event graduation party /at 2021-11-01 18:10` From a04537e1c8648ab8ed25b2644d00140ac3bc1c8f Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 26 Oct 2021 00:44:46 +0800 Subject: [PATCH 455/756] Add more commands in summary --- docs/UserGuide.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index a3820de1ee..bf336fcada 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -173,10 +173,10 @@ Action | Command Format | Example --- | --- | --- | List all valid commands and usage | `help` | `help` Add a new contact| `add -n -g -e -te -l -tw ` | `add -n John Doe -g johndoecoder -e john@email.com -te johndoe` -List all contacts | `deadline /by ` | `deadline submit ip jar /by 2021-10-02 22:20` -View a contact| `list` | `list` -Edit a contact| `event /at ` | `event graduation party /at 2021-11-01 18:10` -Delete a contact | `done ` | `done 2` -Search for a contact| `find ` | `find homework` +List all contacts | `list` | `list` +View a contact| `view ` | `view 2` +Edit a contact| `edit -n -g -e -te -l -tw ` | `edit 1 -e john.doe@email.com` +Delete a contact | `rm ` | `rm 1` +Search for a contact| `search ` | `search -g revflash` Import contacts from .txt file|`import` | `import` -Exit duke | `bye` | `bye` +Exit ConTech | `exit` | `exit` From 9aad26c7af98b2805260b18357e53722b3237ba2 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 26 Oct 2021 00:46:19 +0800 Subject: [PATCH 456/756] Add more examples for search --- docs/UserGuide.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index bf336fcada..5844912cdd 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -177,6 +177,7 @@ List all contacts | `list` | `list` View a contact| `view ` | `view 2` Edit a contact| `edit -n -g -e -te -l -tw ` | `edit 1 -e john.doe@email.com` Delete a contact | `rm ` | `rm 1` -Search for a contact| `search ` | `search -g revflash` +Search for a contact| `search ` | `search Ashraf` +||`search -g revflash` Import contacts from .txt file|`import` | `import` Exit ConTech | `exit` | `exit` From 41101b7c5596f6524d3781e1cf1b765b573cd839 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 26 Oct 2021 00:51:45 +0800 Subject: [PATCH 457/756] Update table for multiline examples --- docs/UserGuide.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 5844912cdd..cece622922 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -172,12 +172,11 @@ ____________________________________________________________ Action | Command Format | Example --- | --- | --- | List all valid commands and usage | `help` | `help` -Add a new contact| `add -n -g -e -te -l -tw ` | `add -n John Doe -g johndoecoder -e john@email.com -te johndoe` +Add a new contact| `add -n -g -e -te -l -tw ` | `add -n John Doe -g johndoecoder -e john@email.com -te johndoe`
    `add -n Marcus`
    List all contacts | `list` | `list` View a contact| `view ` | `view 2` -Edit a contact| `edit -n -g -e -te -l -tw ` | `edit 1 -e john.doe@email.com` +Edit a contact| `edit -n -g -e -te -l -tw ` | `edit 1 -e john.doe@email.com`
    `edit 0 -n Tan -g tanned -te tantan`
    Delete a contact | `rm ` | `rm 1` -Search for a contact| `search ` | `search Ashraf` -||`search -g revflash` +Search for a contact| `search ` | `search Ashraf`
    `search -g revflash`
    Import contacts from .txt file|`import` | `import` Exit ConTech | `exit` | `exit` From b2e9abb206c6609e9c5499e50e05bb6618737eaa Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 26 Oct 2021 00:53:32 +0800 Subject: [PATCH 458/756] Fix table formatting for clarity --- docs/UserGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index cece622922..4bb7e27dcc 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -172,7 +172,7 @@ ____________________________________________________________ Action | Command Format | Example --- | --- | --- | List all valid commands and usage | `help` | `help` -Add a new contact| `add -n -g -e -te -l -tw ` | `add -n John Doe -g johndoecoder -e john@email.com -te johndoe`
    `add -n Marcus`
    +Add a new contact| `add -n -g -e -te -l -tw ` | `add -n Marcus`
    `add -n John Doe -g johndoecoder -e john@email.com -te johndoe`
    List all contacts | `list` | `list` View a contact| `view ` | `view 2` Edit a contact| `edit -n -g -e -te -l -tw ` | `edit 1 -e john.doe@email.com`
    `edit 0 -n Tan -g tanned -te tantan`
    From dce9a0bbdd6e4dbdc81af4d4179e065dc8a4830d Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 26 Oct 2021 00:55:09 +0800 Subject: [PATCH 459/756] Add cell for upcoming feature --- docs/UserGuide.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 4bb7e27dcc..fd04759a2f 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -176,6 +176,7 @@ Add a new contact| `add -n -g -e -te List all contacts | `list` | `list` View a contact| `view ` | `view 2` Edit a contact| `edit -n -g -e -te -l -tw ` | `edit 1 -e john.doe@email.com`
    `edit 0 -n Tan -g tanned -te tantan`
    +Delete contact fields| `` | `` Delete a contact | `rm ` | `rm 1` Search for a contact| `search ` | `search Ashraf`
    `search -g revflash`
    Import contacts from .txt file|`import` | `import` From 1207bc712880cc7a78df670140cad6160de26c7b Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 26 Oct 2021 00:58:32 +0800 Subject: [PATCH 460/756] Add description for command summary --- docs/UserGuide.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index fd04759a2f..594fe699f6 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -119,8 +119,8 @@ ____________________________________________________________ 0. Andre 1. Marcus 2. Le Zong -3. Mayank -4. George +3. Ashraf +4. Mayank 5. Jim 6. Akshay ____________________________________________________________ @@ -169,6 +169,10 @@ ____________________________________________________________ ## Command Summary +Below is a concise summary of frequently used commands in ConTech. +The command format and examples are provided for each command for +a quick view when using the application. + Action | Command Format | Example --- | --- | --- | List all valid commands and usage | `help` | `help` From 8dd14c30afb5e0afe27b14eb6e933060a1e75643 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 26 Oct 2021 01:05:26 +0800 Subject: [PATCH 461/756] Update exit command description --- docs/UserGuide.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 594fe699f6..f1cbc64b7d 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -111,6 +111,7 @@ Usage: `list` Expected outcome of usage: ``` +list ____________________________________________________________ ConTech has 7 contacts stored. Here's the list : @@ -160,6 +161,19 @@ ____________________________________________________________ ### Exiting the program: `exit` +Duke bids farewell and closes the application. + +Usage: `exit` + +Excepted outcome of usage: `exit` + +``` +exit +____________________________________________________________ +ConTech will now shutdown. +We hope you have enjoyed using it. +____________________________________________________________ +``` ## FAQ From 968aa187dd6e0df309f263cb7d67967684ebaba6 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 26 Oct 2021 01:08:37 +0800 Subject: [PATCH 462/756] Update formatting --- docs/UserGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index f1cbc64b7d..71b32b18e6 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -161,7 +161,7 @@ ____________________________________________________________ ### Exiting the program: `exit` -Duke bids farewell and closes the application. +Exits the application. Usage: `exit` From 7f44843ac759d12b8ec938169166d8028f04cf07 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Tue, 26 Oct 2021 03:19:47 +0800 Subject: [PATCH 463/756] Update userguide.md for add feature --- docs/UserGuide.md | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 8dbfafa288..f094e1617a 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -99,7 +99,38 @@ ____________________________________________________________ ### Adding a contact: `add` - +Adds a specified contact to the ConTech Book. + +Usage: `add -n NAME -g GITHUB -l LINKEDIN -te TELEGRAM -tw TWITTER -e EMAIL` + +- ConTech currently supports six `FLAGS` and has in built checkers to check if the format of the `DETAILS` fulfill +the fields. These `flags` include: + - `-n`: for your contact's name + - `-g`: for your contact's GitHub account username + - `-l`: for your contact's LinkedIn handle + - `-te`: for your contact's Telegram handle + - `-tw`: for your contact's Twitter handle + - `-e`: for your contact's email +- ConTech is robust and allows you to specify your fields in any order. +- The `-n` name field is the only compulsory field required to add a contact, the rest are optional. +- ConTech also has built-in duplicate checkers, in case you accidentally add the same contact twice. + +Expected outcome of usage: + +``` +add -n Le Zong -g lezongmun -e lezongmun@gmail.com -te lezongg +____________________________________________________________ +ConTech has added the specified contact: +Name: Le Zong +Github: github.com/lezongmun +Email: lezongmun@gmail.com +Telegram: t.me/lezongg + +You now have 1 contact(s). +____________________________________________________________ +``` + + ### Listing all contacts: `ls` Lists all the saved contacts with the index and contact name. @@ -111,7 +142,7 @@ Usage: `list` Expected outcome of usage: ``` -list +ls ____________________________________________________________ ConTech has 7 contacts stored. Here's the list : From 2078e8accff322ea518aafbe376071dc808d5169 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Tue, 26 Oct 2021 08:12:58 +0800 Subject: [PATCH 464/756] Change input list to ls --- text-ui-test/input.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index 208550231c..c25e86d761 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -24,13 +24,13 @@ rm 9909 add -n bory -g marcus add -n andre -g ng-andre y -list +ls view 1 add -n bory -g rm abc add -g lezongmun -n lezong add -g github -list +ls view 3 rm 0 y @@ -47,7 +47,7 @@ n n rm 1 y -list +ls view abc add -n yusdhsdsd -g -sdj11222 add -n yusdhsdsd -g sdj0-11222 @@ -78,7 +78,7 @@ search boris search -n bory search -g lezong search -zxca lezong -list +ls add -n ashraf -g ashrafjfr add -n ashraf -te ashrafjfr y @@ -89,11 +89,11 @@ view 0 import search -n lezai search -n badgithub -list +ls rm -rf asdsad -list +ls rm -rf y -list +ls exit \ No newline at end of file From bd04d6b1438cfd2e2ef4fd0f6dde5e4ccbef6b08 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Tue, 26 Oct 2021 08:13:07 +0800 Subject: [PATCH 465/756] Update runtest.sh --- text-ui-test/runtest.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/text-ui-test/runtest.sh b/text-ui-test/runtest.sh index 04d6b8e9c2..3e3a9d43a3 100755 --- a/text-ui-test/runtest.sh +++ b/text-ui-test/runtest.sh @@ -13,13 +13,15 @@ java -jar $(find ../build/libs/ -mindepth 1 -print -quit) < input.txt > ACTUAL. cp EXPECTED.TXT EXPECTED-UNIX.TXT dos2unix EXPECTED-UNIX.TXT ACTUAL.TXT diff EXPECTED-UNIX.TXT ACTUAL.TXT -rm data/contacts.txt -rm data/me.txt if [ $? -eq 0 ] then + rm data/contacts.txt + rm data/me.txt echo "Test passed!" exit 0 else + rm data/contacts.txt + rm data/me.txt echo "Test failed!" exit 1 fi From 4be94d22638cffd70087dad2e13e05ef78e6f0c0 Mon Sep 17 00:00:00 2001 From: lezong Date: Tue, 26 Oct 2021 09:01:08 +0800 Subject: [PATCH 466/756] Update input.txt --- text-ui-test/input.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index c25e86d761..811e881f7b 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -90,10 +90,10 @@ import search -n lezai search -n badgithub ls -rm -rf +rm all asdsad ls -rm -rf +rm all y ls exit \ No newline at end of file From 4fbbc418e5732b339ed1487c4d3c641a24d5c818 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 26 Oct 2021 12:46:12 +0800 Subject: [PATCH 467/756] Update product description and overview with more details --- docs/UserGuide.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index f094e1617a..aef3525975 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -6,9 +6,10 @@ If you are a computing professional that often uses the command line for work, **ConTech** can get your contact management tasks done faster than any traditional GUI app. -With our `add`, `edit`, `view`, and many more [features](#features) specifically set for computing-related contacts -such as saving a colleague's GitHub username, **ConTech** aims to improve your efficiency at work by cutting down the -time required to look up for various usernames when working with colleagues. +With our various [features](#features) such as `add`, `edit`, `view`, and other commands, you can easily perform such +actions on your **ConTech** Book in a quick and efficient manner. **ConTech** is optimised for computing-related contacts +such as saving a colleague's GitHub username or even mass-loading from a list of contacts. **ConTech** aims to improve your +efficiency at work by cutting down the time required to look up for various usernames when working with colleagues. * **[Quick Start](#start)** * **[Features](#features)** From 4ed1f5ec4cf1ae541df24e9624b917874f30b4a1 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 26 Oct 2021 12:46:56 +0800 Subject: [PATCH 468/756] Move flag descriptors to a separate section --- docs/UserGuide.md | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index aef3525975..0387e9ddc4 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -13,6 +13,7 @@ efficiency at work by cutting down the time required to look up for various user * **[Quick Start](#start)** * **[Features](#features)** + * **[Contact flags : `-flag`](#flag)** * **[Viewing help : `help`](#help)** * **[Adding a contact : `add`](#add)** * **[Listing all contacts : `ls`](#list)** @@ -49,6 +50,20 @@ efficiency at work by cutting down the time required to look up for various user ## Features + +### Contact flags: `-flag` +When using commands such as `add`,`edit` and `search`, the user can specify details with the use of flags in the form `-FLAG`. + +ConTech currently supports six `FLAGS` and has in built checkers to check if the format of the `DETAILS` fulfill +the fields. These `flags` include: +- `-n`: for your contact's name +- `-g`: for your contact's GitHub account username +- `-l`: for your contact's LinkedIn handle +- `-te`: for your contact's Telegram handle +- `-tw`: for your contact's Twitter handle +- `-e`: for your contact's email address + + ### Viewing help: `help` Displays a help message explaining what commands are available and each input format. @@ -104,16 +119,9 @@ Adds a specified contact to the ConTech Book. Usage: `add -n NAME -g GITHUB -l LINKEDIN -te TELEGRAM -tw TWITTER -e EMAIL` -- ConTech currently supports six `FLAGS` and has in built checkers to check if the format of the `DETAILS` fulfill -the fields. These `flags` include: - - `-n`: for your contact's name - - `-g`: for your contact's GitHub account username - - `-l`: for your contact's LinkedIn handle - - `-te`: for your contact's Telegram handle - - `-tw`: for your contact's Twitter handle - - `-e`: for your contact's email - ConTech is robust and allows you to specify your fields in any order. - The `-n` name field is the only compulsory field required to add a contact, the rest are optional. +- Up to five other `FLAGS` and `DETAILS` can be specified - ConTech also has built-in duplicate checkers, in case you accidentally add the same contact twice. Expected outcome of usage: @@ -136,7 +144,7 @@ ____________________________________________________________ Lists all the saved contacts with the index and contact name. -Usage: `list` +Usage: `ls` * The indexes start from 0, this is done as computing professionals are more familiar with index start from 0. @@ -192,6 +200,8 @@ Usage: `edit INDEX -FLAG DETAIL` - Up to six `FLAGS` and `DETAILS` can be specified in any order - The index refers to the index number shown in the displayed contact list. - The index must be within the range of indexes displayed in the contact list (zero-based). +- ConTech also has built-in duplicate checkers and will alert you if there is already a contact with the same details when editing. + Expected outcome of usage: ``` @@ -269,7 +279,7 @@ Action | Command Format | Example --- | --- | --- | List all valid commands and usage | `help` | `help` Add a new contact| `add -n -g -e -te -l -tw ` | `add -n Marcus`
    `add -n John Doe -g johndoecoder -e john@email.com -te johndoe`
    -List all contacts | `list` | `list` +List all contacts | `ls` | `ls` View a contact| `view ` | `view 2` Edit a contact| `edit -n -g -e -te -l -tw ` | `edit 1 -e john.doe@email.com`
    `edit 0 -n Tan -g tanned -te tantan`
    Delete contact fields| `` | `` From 599c6d68dd7639f9e96789616372246dae191144 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 26 Oct 2021 12:48:44 +0800 Subject: [PATCH 469/756] Move help command to the bottom --- docs/UserGuide.md | 97 ++++++++++++++++++++++++----------------------- 1 file changed, 49 insertions(+), 48 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 0387e9ddc4..25dcf93395 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -64,54 +64,6 @@ the fields. These `flags` include: - `-e`: for your contact's email address - -### Viewing help: `help` -Displays a help message explaining what commands are available and each input format. - -Usage: `help` - -Expected outcome of usage: - -``` -help -____________________________________________________________ -add: ConTech adds the specified contact with provided parameters. - Parameters: -n NAME -g GITHUB -e EMAIL -te TELEGRAM -l LINKEDIN -tw TWITTER - Note: Parameters need not be in order and are optional except for NAME. - Example: add -n John Doe -g johndoecoder -e john@email.com -te johndoe - -ls: Displays the name of all saved contacts. - Example: ls - -edit: Edit any parameter in an existing contact. - Parameters: INDEX -n NAME -g GITHUB -e EMAIL -te TELEGRAM -l LINKEDIN -tw TWITTER - Note: Parameters need not be in order and are optional except for INDEX. - Example: edit 1 -e john.doe@email.com - -view: Displays all details for index specified contact. - Parameter: INDEX - Note: Index starts from 0. - Example: view 2 - -rm: Deletes the index specified contact. - Parameter: INDEX - Note: Index starts from 0. - Example: rm 0 - -search: Search for a contact containing a specified query. - Note: Flags may be used to specify a detail type to search. - If no flag is specified, contact name is searched by default. - Example: search -g QUERY - -help: Displays application usage instructions. - Example: help - -import: Imports contacts from a CSV Text File. - Note: Please ensure that data is saved in data/import.txt - Example: import -____________________________________________________________ -``` - ### Adding a contact: `add` @@ -247,6 +199,55 @@ ____________________________________________________________ ### Importing contacts: `import` + +### Viewing help: `help` +Displays a help message explaining what commands are available and each input format. + +Usage: `help` + +Expected outcome of usage: + +``` +help +____________________________________________________________ +add: ConTech adds the specified contact with provided parameters. + Parameters: -n NAME -g GITHUB -e EMAIL -te TELEGRAM -l LINKEDIN -tw TWITTER + Note: Parameters need not be in order and are optional except for NAME. + Example: add -n John Doe -g johndoecoder -e john@email.com -te johndoe + +ls: Displays the name of all saved contacts. + Example: ls + +edit: Edit any parameter in an existing contact. + Parameters: INDEX -n NAME -g GITHUB -e EMAIL -te TELEGRAM -l LINKEDIN -tw TWITTER + Note: Parameters need not be in order and are optional except for INDEX. + Example: edit 1 -e john.doe@email.com + +view: Displays all details for index specified contact. + Parameter: INDEX + Note: Index starts from 0. + Example: view 2 + +rm: Deletes the index specified contact. + Parameter: INDEX + Note: Index starts from 0. + Example: rm 0 + +search: Search for a contact containing a specified query. + Note: Flags may be used to specify a detail type to search. + If no flag is specified, contact name is searched by default. + Example: search -g QUERY + +help: Displays application usage instructions. + Example: help + +import: Imports contacts from a CSV Text File. + Note: Please ensure that data is saved in data/import.txt + Example: import +____________________________________________________________ +``` + + ### Exiting the program: `exit` Exits the application. From 4f116736f51a3eee5e8d3547a081f8cdc7401d0c Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 26 Oct 2021 13:10:51 +0800 Subject: [PATCH 470/756] Add UG for import command --- docs/UserGuide.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 25dcf93395..9684180959 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -198,6 +198,17 @@ ____________________________________________________________ ### Importing contacts: `import` +Import contacts from a CSV text file into your contact list. + +Usage: `import` + +- Data to be imported should be stored in the file `data/import.txt`. +- Invalid or corrupt data will not be imported into the contact list and will be discarded. +- Duplicate contacts will trigger a confirmation message, allowing the user to choose if the duplicate contact should be added. + +Expected outcome of usage: + +{to be added} ### Viewing help: `help` From 2d7c8b66cf35d251d233b6a623ab76eab0201a7b Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 26 Oct 2021 17:34:47 +0800 Subject: [PATCH 471/756] Bug fix for illegal index in IndexParser --- src/main/java/seedu/parser/IndexParser.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/parser/IndexParser.java b/src/main/java/seedu/parser/IndexParser.java index eb1d15e333..c90eb25b31 100644 --- a/src/main/java/seedu/parser/IndexParser.java +++ b/src/main/java/seedu/parser/IndexParser.java @@ -38,9 +38,12 @@ public static int getIndexFromInput(String userInput) if (significantIndex.equalsIgnoreCase(REMOVE_ALL_INDEX)) { return REMOVE_ALL_ID; } - // takes only the first word/ element as given user input, and throws NumberFormatExcept if it is not integer - return Integer.parseInt(significantIndex); + int index = Integer.parseInt(significantIndex); + if (index < 0) { + throw new ArrayIndexOutOfBoundsException(); + } + return index; } public static Contact getContactFromIndex(int index, ContactList contactList) throws IndexOutOfBoundsException { From c3f3ee5c0944c532fb4a319fb437628d038c7446 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 26 Oct 2021 18:27:06 +0800 Subject: [PATCH 472/756] Add class for MissingIndexException --- src/main/java/seedu/exception/MissingIndexException.java | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 src/main/java/seedu/exception/MissingIndexException.java diff --git a/src/main/java/seedu/exception/MissingIndexException.java b/src/main/java/seedu/exception/MissingIndexException.java new file mode 100644 index 0000000000..c0e391f89c --- /dev/null +++ b/src/main/java/seedu/exception/MissingIndexException.java @@ -0,0 +1,2 @@ +package seedu.exception;public class MissingIndexException { +} From cfcfc918947e00ebbe5cb2c663aa55503f7f4e12 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 26 Oct 2021 18:27:33 +0800 Subject: [PATCH 473/756] Add missing index error message --- src/main/java/seedu/ui/ExceptionTextUi.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index cf16b9d1de..d54b1bfa79 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -132,6 +132,13 @@ public static void missingArgMessage() { printDoubleLineMessage(message); } + public static void missingIndexMessage() { + String message = "There seems to be missing index in your request.\n" + + "Please enter index in the following way: \n" + + " "; + printDoubleLineMessage(message); + } + public static void invalidNumMessage() { String message = "That does not seem to be a number.\n" + "Please provide a number instead."; printDoubleLineMessage(message); From 960afeae9444274347ab4981c4c03a147c97e9ff Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 26 Oct 2021 18:28:33 +0800 Subject: [PATCH 474/756] Update index out of bounds message --- src/main/java/seedu/ui/ExceptionTextUi.java | 24 ++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index d54b1bfa79..aea70e871b 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -162,11 +162,29 @@ public static void numOutOfRangeMessage(int listSize) { if (listSize == 0) { message = "There are no contacts stored in ConTech."; } else if (listSize == 1) { - message = "The number you have input is out of range.\n" + message = "The index you have input is out of range.\n" + "You only have 1 contact stored."; } else { - message = "The number you have input is out of range.\n" - + "Please input a number between 0 and " + maxIndex + "."; + message = "The index you have input is out of range.\n" + + "Please input a index between 0 and " + maxIndex; + } + printDoubleLineMessage(message); + } + + public static void numOutOfRangeEditMessage(int listSize) { + String message; + int maxIndex = listSize - 1; + if (listSize == 0) { + message = "There are no contacts stored in ConTech.\n" + + "Please input index -1 if you wish to edit your Personal Contact details."; + } else if (listSize == 1) { + message = "The index you have input is out of range.\n" + + "You only have 1 contact stored.\n" + + "Please input index -1 if you wish to edit your Personal Contact details."; + } else { + message = "The index you have input is out of range.\n" + + "Please input a number between 0 and " + maxIndex + "to edit saved contacts.\n" + + "Otherwise, input index -1 if you wish to edit your Personal Contact details."; } printDoubleLineMessage(message); } From 85e629c01d935d42ab685417444bb223db497111 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 26 Oct 2021 18:29:20 +0800 Subject: [PATCH 475/756] Update MissingIndexException class --- src/main/java/seedu/exception/MissingIndexException.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/exception/MissingIndexException.java b/src/main/java/seedu/exception/MissingIndexException.java index c0e391f89c..e8097aa10e 100644 --- a/src/main/java/seedu/exception/MissingIndexException.java +++ b/src/main/java/seedu/exception/MissingIndexException.java @@ -1,2 +1,4 @@ -package seedu.exception;public class MissingIndexException { +package seedu.exception; + +public class MissingIndexException extends Exception { } From 280a68f8c1215b48243b28dc38387d6e6410ebf1 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 26 Oct 2021 18:29:46 +0800 Subject: [PATCH 476/756] Update failed commands --- src/main/java/seedu/parser/FailedCommandType.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/parser/FailedCommandType.java b/src/main/java/seedu/parser/FailedCommandType.java index a2121c4748..04ed4390b5 100644 --- a/src/main/java/seedu/parser/FailedCommandType.java +++ b/src/main/java/seedu/parser/FailedCommandType.java @@ -1,8 +1,8 @@ package seedu.parser; public enum FailedCommandType { - GENERAL, INVALID_FLAG, MISSING_ARG, MISSING_DETAIL, INVALID_NUM, + GENERAL, INVALID_FLAG, MISSING_ARG, MISSING_DETAIL, MISSING_INDEX, INVALID_NUM, INVALID_FORMAT, NUM_OUT_OF_BOUND, INVALID_INDEX, MISSING_NAME, FORBIDDEN_DETAIL, INVALID_NAME, INVALID_GITHUB_USERNAME, - INVALID_LINKEDIN, INVALID_TELEGRAM, INVALID_MAIL, INVALID_TWITTER + INVALID_LINKEDIN, INVALID_TELEGRAM, INVALID_MAIL, INVALID_TWITTER; } From e2208b1fd001a59c48645c151cd94961c831666d Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 26 Oct 2021 18:31:12 +0800 Subject: [PATCH 477/756] Update exception handling --- src/main/java/seedu/parser/IndexParser.java | 5 +++-- src/main/java/seedu/parser/MainParser.java | 13 ++++++++----- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/main/java/seedu/parser/IndexParser.java b/src/main/java/seedu/parser/IndexParser.java index eb1d15e333..ea6e5ebc77 100644 --- a/src/main/java/seedu/parser/IndexParser.java +++ b/src/main/java/seedu/parser/IndexParser.java @@ -5,6 +5,7 @@ import seedu.contact.Contact; import seedu.contact.ContactList; import seedu.exception.MissingArgException; +import seedu.exception.MissingIndexException; public class IndexParser { @@ -19,11 +20,11 @@ public class IndexParser { public static int getIndexFromInput(String userInput) - throws NumberFormatException, MissingArgException { + throws NumberFormatException, MissingIndexException { //split user input into 2 strings: command word string and index string String[] destructuredInputs = userInput.split(" ", COMD_INDEX_LENGTH); if (destructuredInputs.length <= COMD_WORD_LENGTH) { - throw new MissingArgException(); + throw new MissingIndexException(); } assert destructuredInputs.length == 2; // split index string into words diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 3aafecbd4c..06b9449295 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -24,6 +24,7 @@ import seedu.exception.InvalidTwitterUsernameException; import seedu.exception.MissingArgException; import seedu.exception.MissingDetailException; +import seedu.exception.MissingIndexException; import seedu.exception.MissingNameException; import static seedu.parser.ContactParser.NUMBER_OF_FIELDS; @@ -189,9 +190,9 @@ private Command parseAddContact(String userInput) { private Command parseEditContact(String userInput) { // userInput is raw user input contactParser = editContactParser; try { + int userIndex = IndexParser.getIndexFromInput(userInput); //throws MissingIndexException String[] details = editContactParser.parseContactDetails(userInput); //throws InvalidFlagException, MissingDetailException, MissingArgException - int userIndex = IndexParser.getIndexFromInput(userInput); //throws MissingArgException return new EditContactCommand(details, userIndex); } catch (InvalidFlagException e) { return new FailedCommand(FailedCommandType.INVALID_FLAG); @@ -201,6 +202,8 @@ private Command parseEditContact(String userInput) { // userInput is raw user in return new FailedCommand(FailedCommandType.INVALID_INDEX); } catch (MissingDetailException e) { return new FailedCommand(FailedCommandType.MISSING_DETAIL); + } catch (MissingIndexException e) { + return new FailedCommand(FailedCommandType.MISSING_INDEX); } catch (InvalidNameException | InvalidGithubUsernameException | InvalidEmailException | InvalidLinkedinUsernameException | InvalidTelegramUsernameException | InvalidTwitterUsernameException | ForbiddenDetailException e) { @@ -240,10 +243,10 @@ private Command parseViewContact(String userInput) { try { int viewedIndex = IndexParser.getIndexFromInput(userInput); return new ViewContactCommand(viewedIndex); - } catch (MissingArgException e) { - return new FailedCommand(FailedCommandType.MISSING_ARG); } catch (NumberFormatException e) { return new FailedCommand(FailedCommandType.INVALID_INDEX); + } catch (MissingIndexException e) { + return new FailedCommand(FailedCommandType.MISSING_INDEX); } } @@ -252,10 +255,10 @@ private Command parseDeleteContact(String userInput) { try { int deletedIndex = IndexParser.getIndexFromInput(userInput); return new DeleteContactCommand(deletedIndex); - } catch (MissingArgException e) { - return new FailedCommand(FailedCommandType.MISSING_ARG); } catch (NumberFormatException e) { return new FailedCommand(FailedCommandType.INVALID_INDEX); + } catch (MissingIndexException e) { + return new FailedCommand(FailedCommandType.MISSING_INDEX); } } From 52cce7ec3231a3b1811a36cdb72b7cd7c57f2810 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 26 Oct 2021 18:47:27 +0800 Subject: [PATCH 478/756] Update TextUI with confirmation messages for delete fields --- src/main/java/seedu/ui/TextUi.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 48c9442818..2f70a29fdd 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -195,6 +195,17 @@ public static void confirmDeleteAllMessage() { printDoubleLineMessage(message); } + public static void confirmDeleteFieldMessage() { + String message = "Delete the specified fields? (y/n)"; + printDoubleLineMessage(message); + } + + public static void deleteFieldsMessage() { + String message = "The specified fields have been deleted."; + printDoubleLineMessage(message); + } + + public static void deleteContactMessage(String contactName, int listSize) { String message = "ConTech has removed the specified contact: " + contactName + "\n" + "You now have " + listSize + " contact(s)."; From e438c846357ae91fe4e2b2cbbcbd26c6f27dda07 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 26 Oct 2021 18:48:54 +0800 Subject: [PATCH 479/756] Update constants for DeleteContactCommand --- src/main/java/seedu/command/DeleteContactCommand.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/command/DeleteContactCommand.java b/src/main/java/seedu/command/DeleteContactCommand.java index 33d7d46a80..09b6598124 100644 --- a/src/main/java/seedu/command/DeleteContactCommand.java +++ b/src/main/java/seedu/command/DeleteContactCommand.java @@ -10,8 +10,13 @@ public class DeleteContactCommand extends Command { - private static String ACKNOWLEDGE_DELETE = "y"; - private static int DELETE_ALL_CONTACTS = -2; + private static final String ACKNOWLEDGE_DELETE = "y"; + private static final int DELETE_ALL_CONTACTS = -2; + public static final int GITHUB_INDEX = 1; + public static final int LINKEDIN_INDEX = 2; + public static final int TELEGRAM_INDEX = 3; + public static final int TWITTER_INDEX = 4; + public static final int EMAIL_INDEX = 5; private final int contactIndex; From fe3ac2dd4aece28e48caf7f7f258a94f14335d5e Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 26 Oct 2021 18:49:20 +0800 Subject: [PATCH 480/756] Implement delete fields for DeleteContactCommand --- .../seedu/command/DeleteContactCommand.java | 36 +++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/command/DeleteContactCommand.java b/src/main/java/seedu/command/DeleteContactCommand.java index 09b6598124..e963173f50 100644 --- a/src/main/java/seedu/command/DeleteContactCommand.java +++ b/src/main/java/seedu/command/DeleteContactCommand.java @@ -19,9 +19,11 @@ public class DeleteContactCommand extends Command { public static final int EMAIL_INDEX = 5; private final int contactIndex; + private final boolean[] deleteDetails; - public DeleteContactCommand(int contactIndex) { + public DeleteContactCommand(int contactIndex, boolean[] deleteDetails) { this.contactIndex = contactIndex; + this.deleteDetails = deleteDetails; } public int getContactIndex() { @@ -61,12 +63,42 @@ private void deleteAllContacts() { } } + private void deleteFields() { + Contact deletedContact = IndexParser.getContactFromIndex(contactIndex, contactList); + assert contactIndex >= 0 && contactIndex < contactList.getListSize(); + TextUi.confirmDeleteFieldMessage(); + String userConfirmation = UserInputTextUi.getUserConfirmation(); + if (userConfirmation.equalsIgnoreCase(ACKNOWLEDGE_DELETE)) { + if (deleteDetails[GITHUB_INDEX]) { + deletedContact.setGithub(null); + } + if (deleteDetails[LINKEDIN_INDEX]) { + deletedContact.setLinkedin(null); + } + if (deleteDetails[TELEGRAM_INDEX]) { + deletedContact.setTelegram(null); + } + if (deleteDetails[TWITTER_INDEX]) { + deletedContact.setTwitter(null); + } + if (deleteDetails[EMAIL_INDEX]) { + deletedContact.setEmail(null); + } + TextUi.deleteFieldsMessage(); + } else { + assert !userConfirmation.equalsIgnoreCase(ACKNOWLEDGE_DELETE); + TextUi.cancelDeleteContactMessage(); + } + } + public void execute() { try { if (contactIndex == DELETE_ALL_CONTACTS) { deleteAllContacts(); - } else { + } else if (deleteDetails[6]) { //delete entire contact deleteSelectedContact(); + } else { + deleteFields(); } } catch (IndexOutOfBoundsException e) { ExceptionTextUi.numOutOfRangeMessage(contactList.getListSize()); From 4b1343defebeff52b3e3bfbec666a5c1310f77d0 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 26 Oct 2021 18:49:39 +0800 Subject: [PATCH 481/756] Add error message for invalid field when deleting (delete name) --- src/main/java/seedu/command/FailedCommand.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/seedu/command/FailedCommand.java b/src/main/java/seedu/command/FailedCommand.java index 225875c3ef..034886353a 100644 --- a/src/main/java/seedu/command/FailedCommand.java +++ b/src/main/java/seedu/command/FailedCommand.java @@ -24,6 +24,7 @@ public void execute() { case INVALID_NUM: // Fallthrough case INVALID_FORMAT: // Fallthrough case NUM_OUT_OF_BOUND: // Fallthrough + case INVALID_DELETE: //Fallthrough invalidUserInputExecute(); break; case MISSING_ARG: // Fallthrough @@ -53,6 +54,9 @@ private void invalidUserInputExecute() { case NUM_OUT_OF_BOUND: ExceptionTextUi.numOutOfRangeMessage(contactList.getListSize() - 1); break; + case INVALID_DELETE: + ExceptionTextUi.invalidDeleteFlag(); + break; default: return; } From 26a4a91521802229d2212754547fdc122efbf70c Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 26 Oct 2021 18:49:53 +0800 Subject: [PATCH 482/756] Update enum for invalid delete --- src/main/java/seedu/parser/FailedCommandType.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/FailedCommandType.java b/src/main/java/seedu/parser/FailedCommandType.java index a2121c4748..15bb277696 100644 --- a/src/main/java/seedu/parser/FailedCommandType.java +++ b/src/main/java/seedu/parser/FailedCommandType.java @@ -4,5 +4,5 @@ public enum FailedCommandType { GENERAL, INVALID_FLAG, MISSING_ARG, MISSING_DETAIL, INVALID_NUM, INVALID_FORMAT, NUM_OUT_OF_BOUND, INVALID_INDEX, MISSING_NAME, FORBIDDEN_DETAIL, INVALID_NAME, INVALID_GITHUB_USERNAME, - INVALID_LINKEDIN, INVALID_TELEGRAM, INVALID_MAIL, INVALID_TWITTER + INVALID_LINKEDIN, INVALID_TELEGRAM, INVALID_MAIL, INVALID_TWITTER, INVALID_DELETE } From 8d9ea88f55474354b4e592c49eee4212d1a91345 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 26 Oct 2021 18:50:19 +0800 Subject: [PATCH 483/756] Update IndexParser with index out of bounds exception --- src/main/java/seedu/parser/IndexParser.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/parser/IndexParser.java b/src/main/java/seedu/parser/IndexParser.java index c90eb25b31..8df30d45de 100644 --- a/src/main/java/seedu/parser/IndexParser.java +++ b/src/main/java/seedu/parser/IndexParser.java @@ -19,7 +19,7 @@ public class IndexParser { public static int getIndexFromInput(String userInput) - throws NumberFormatException, MissingArgException { + throws NumberFormatException, MissingArgException, IndexOutOfBoundsException { //split user input into 2 strings: command word string and index string String[] destructuredInputs = userInput.split(" ", COMD_INDEX_LENGTH); if (destructuredInputs.length <= COMD_WORD_LENGTH) { @@ -41,7 +41,7 @@ public static int getIndexFromInput(String userInput) // takes only the first word/ element as given user input, and throws NumberFormatExcept if it is not integer int index = Integer.parseInt(significantIndex); if (index < 0) { - throw new ArrayIndexOutOfBoundsException(); + throw new IndexOutOfBoundsException(); } return index; } From 42be59a0432e9cfcf180d388402363c8f033fa41 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 26 Oct 2021 18:52:23 +0800 Subject: [PATCH 484/756] Add new exception for invalid delete --- .../java/seedu/exception/InvalidDeleteDetailException.java | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/main/java/seedu/exception/InvalidDeleteDetailException.java diff --git a/src/main/java/seedu/exception/InvalidDeleteDetailException.java b/src/main/java/seedu/exception/InvalidDeleteDetailException.java new file mode 100644 index 0000000000..8238232681 --- /dev/null +++ b/src/main/java/seedu/exception/InvalidDeleteDetailException.java @@ -0,0 +1,4 @@ +package seedu.exception; + +public class InvalidDeleteDetailException extends Exception{ +} From 3d42320b277dba63f79ceff30fb62e31f8436224 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 26 Oct 2021 18:52:50 +0800 Subject: [PATCH 485/756] Update Main Parser to allow parsing of fields to be deleted --- src/main/java/seedu/parser/MainParser.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 3aafecbd4c..9ffc176027 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -15,6 +15,7 @@ import seedu.command.SearchContactCommand; import seedu.command.ViewContactCommand; import seedu.exception.ForbiddenDetailException; +import seedu.exception.InvalidDeleteDetailException; import seedu.exception.InvalidEmailException; import seedu.exception.InvalidFlagException; import seedu.exception.InvalidGithubUsernameException; @@ -48,6 +49,7 @@ public class MainParser { private final AddContactParser addContactParser = new AddContactParser(); private final EditContactParser editContactParser = new EditContactParser(); private final SearchContactParser searchContactParser = new SearchContactParser(); + private final DeleteContactParser deleteContactParser = new DeleteContactParser(); public Command parseCommand(String userInput) { CommandType commandType = getCommandType(userInput); @@ -251,11 +253,18 @@ private Command parseViewContact(String userInput) { private Command parseDeleteContact(String userInput) { try { int deletedIndex = IndexParser.getIndexFromInput(userInput); - return new DeleteContactCommand(deletedIndex); + boolean[] deleteDetails = deleteContactParser.getDeleteDetails(userInput); + return new DeleteContactCommand(deletedIndex, deleteDetails); } catch (MissingArgException e) { return new FailedCommand(FailedCommandType.MISSING_ARG); } catch (NumberFormatException e) { return new FailedCommand(FailedCommandType.INVALID_INDEX); + } catch (InvalidFlagException e) { + return new FailedCommand(FailedCommandType.INVALID_FLAG); + } catch (InvalidDeleteDetailException e) { + return new FailedCommand(FailedCommandType.INVALID_DELETE); + } catch (IndexOutOfBoundsException e) { + return new FailedCommand(FailedCommandType.NUM_OUT_OF_BOUND); } } From 6d3dbca85120cd05f2cfce173893865da7e4a9d1 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 26 Oct 2021 18:53:06 +0800 Subject: [PATCH 486/756] Update output for invalid delete error --- src/main/java/seedu/ui/ExceptionTextUi.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index cf16b9d1de..f5976a7745 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -269,4 +269,10 @@ public static void invalidLinkedinUsernameInput() { + " * Length between 3 to 100 characters"; printDoubleLineMessage(message); } + + public static void invalidDeleteFlag() { + String message = "Contact name cannot be deleted. \n" + + "Please delete the entire contact instead."; + printDoubleLineMessage(message); + } } From 3953a336b4bd357df36d1361c89adbf7463fa434 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 26 Oct 2021 18:53:35 +0800 Subject: [PATCH 487/756] Implement delete contact parser to get deleted fields --- .../seedu/parser/DeleteContactParser.java | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 src/main/java/seedu/parser/DeleteContactParser.java diff --git a/src/main/java/seedu/parser/DeleteContactParser.java b/src/main/java/seedu/parser/DeleteContactParser.java new file mode 100644 index 0000000000..8a0cb16b26 --- /dev/null +++ b/src/main/java/seedu/parser/DeleteContactParser.java @@ -0,0 +1,43 @@ +package seedu.parser; + +import seedu.exception.InvalidDeleteDetailException; +import seedu.exception.InvalidFlagException; + +import static seedu.parser.ContactParser.DETAIL_SEPARATOR; +import static seedu.parser.ContactParser.USER_INFO_INDEX; + +//@@author ng-andre +public class DeleteContactParser implements ContactDetails { + private static final int DELETE_CONTACT_INDEX = 6; + public static final int NUMBER_OF_DELETE_ARGS = 3; + public static final String BUFFER = " "; + + boolean[] getDeleteDetails(String userInput) throws InvalidFlagException, InvalidDeleteDetailException { + boolean[] deleteDetails = new boolean[7]; //all false by default + //deleteDetails[6] is true if delete entire contact + String[] inputDetails = userInput.trim().split(" ", NUMBER_OF_DELETE_ARGS); + if (inputDetails.length < NUMBER_OF_DELETE_ARGS) { //no flags specified, delete entire contact + deleteDetails[DELETE_CONTACT_INDEX] = true; + return deleteDetails; + } + assert inputDetails.length == NUMBER_OF_DELETE_ARGS; //flags may be specified + String[] destructuredInputs = (BUFFER + inputDetails[USER_INFO_INDEX]).split(DETAIL_SEPARATOR); + //handles illegal input "delete 0 -" and "delete 0 [invalid string]" + //valid input will take the form of [, -flag input] so min length should be 2 + if (destructuredInputs.length < NUMBER_OF_DELETE_ARGS - 1) { + //input is in the form delete INDEX [invalid string] so delete entire contact + deleteDetails[DELETE_CONTACT_INDEX] = true; + return deleteDetails; + } + for (int i = 1; i < destructuredInputs.length; i++) { + int flag = getIndexToStore(destructuredInputs[i].trim()); + //if invalid flag, this will not be executed + if (flag == 0) { //cannot delete -n + throw new InvalidDeleteDetailException(); + } else { + deleteDetails[flag] = true; + } + } + return deleteDetails; + } +} From b3ba3dc30049bd42febd323d7dd0313fa2fd3745 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 26 Oct 2021 19:13:32 +0800 Subject: [PATCH 488/756] Add MissingArgEditException class --- src/main/java/seedu/exception/MissingArgEditException.java | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/main/java/seedu/exception/MissingArgEditException.java diff --git a/src/main/java/seedu/exception/MissingArgEditException.java b/src/main/java/seedu/exception/MissingArgEditException.java new file mode 100644 index 0000000000..7dc08fedd8 --- /dev/null +++ b/src/main/java/seedu/exception/MissingArgEditException.java @@ -0,0 +1,4 @@ +package seedu.exception; + +public class MissingArgEditException extends Exception { +} From 0f49f19e3e9e5f45d6ca88c68b9dc29ca5e3c0ca Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 26 Oct 2021 19:17:00 +0800 Subject: [PATCH 489/756] Implement edit error exception --- src/main/java/seedu/command/EditContactCommand.java | 3 ++- src/main/java/seedu/command/FailedCommand.java | 8 ++++++++ src/main/java/seedu/parser/ContactParser.java | 13 ++----------- src/main/java/seedu/parser/EditContactParser.java | 12 ++++++------ src/main/java/seedu/parser/FailedCommandType.java | 2 +- src/main/java/seedu/parser/MainParser.java | 7 +++++-- .../java/seedu/parser/EditContactParserTest.java | 13 ++----------- 7 files changed, 26 insertions(+), 32 deletions(-) diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index d917da1db3..ebb0ad4c5b 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -38,7 +38,8 @@ public void execute() { handleDuplicates(editedContact); } } catch (IndexOutOfBoundsException | InvalidFlagException e) { - ExceptionTextUi.numOutOfRangeMessage(contactList.getListSize()); + //triggerred when inputs are "edit " + ExceptionTextUi.numOutOfRangeEditMessage(contactList.getListSize()); } } diff --git a/src/main/java/seedu/command/FailedCommand.java b/src/main/java/seedu/command/FailedCommand.java index 225875c3ef..df07d8f70e 100644 --- a/src/main/java/seedu/command/FailedCommand.java +++ b/src/main/java/seedu/command/FailedCommand.java @@ -27,8 +27,10 @@ public void execute() { invalidUserInputExecute(); break; case MISSING_ARG: // Fallthrough + case MISSING_ARGS_EDIT: // Fallthrough case MISSING_DETAIL: // Fallthrough case MISSING_NAME: // Fallthrough + case MISSING_INDEX: // Fallthrough missingUserInputExecute(); break; default: @@ -63,12 +65,18 @@ private void missingUserInputExecute() { case MISSING_ARG: ExceptionTextUi.missingArgMessage(); break; + case MISSING_ARGS_EDIT: + ExceptionTextUi.missingArgEditMessage(); + break; case MISSING_DETAIL: ExceptionTextUi.missingDetailMessage(); break; case MISSING_NAME: ExceptionTextUi.missingNameMessage(); break; + case MISSING_INDEX: + ExceptionTextUi.missingIndexMessage(); + break; default: return; } diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index b73eb5b258..959bc28c77 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -1,15 +1,6 @@ package seedu.parser; -import seedu.exception.ForbiddenDetailException; -import seedu.exception.InvalidEmailException; -import seedu.exception.InvalidFlagException; -import seedu.exception.InvalidGithubUsernameException; -import seedu.exception.InvalidLinkedinUsernameException; -import seedu.exception.InvalidNameException; -import seedu.exception.InvalidTelegramUsernameException; -import seedu.exception.InvalidTwitterUsernameException; -import seedu.exception.MissingArgException; -import seedu.exception.MissingDetailException; +import seedu.exception.*; import java.util.logging.Logger; @@ -30,7 +21,7 @@ public abstract class ContactParser extends RegexParser implements ContactDetail public abstract String[] parseContactDetails(String userInput) throws InvalidFlagException, MissingArgException, MissingDetailException, ForbiddenDetailException, InvalidNameException, InvalidGithubUsernameException, InvalidTelegramUsernameException, - InvalidLinkedinUsernameException, InvalidTwitterUsernameException, InvalidEmailException; + InvalidLinkedinUsernameException, InvalidTwitterUsernameException, InvalidEmailException, MissingArgEditException; /** * This method takes in the contactDetails array and populates it with contact diff --git a/src/main/java/seedu/parser/EditContactParser.java b/src/main/java/seedu/parser/EditContactParser.java index d1b07d4051..61c4f98ddc 100644 --- a/src/main/java/seedu/parser/EditContactParser.java +++ b/src/main/java/seedu/parser/EditContactParser.java @@ -8,21 +8,21 @@ import seedu.exception.InvalidNameException; import seedu.exception.InvalidTelegramUsernameException; import seedu.exception.InvalidTwitterUsernameException; -import seedu.exception.MissingArgException; +import seedu.exception.MissingArgEditException; import seedu.exception.MissingDetailException; public class EditContactParser extends ContactParser { public static final String BUFFER = " "; public String[] parseContactDetails(String userInput) - throws InvalidFlagException, MissingDetailException, MissingArgException, ForbiddenDetailException, - InvalidNameException, InvalidGithubUsernameException, InvalidTelegramUsernameException, - InvalidLinkedinUsernameException, InvalidTwitterUsernameException, InvalidEmailException { + throws InvalidFlagException, MissingDetailException, ForbiddenDetailException, InvalidNameException, + InvalidGithubUsernameException, InvalidTelegramUsernameException, InvalidLinkedinUsernameException, + InvalidTwitterUsernameException, InvalidEmailException, MissingArgEditException { String[] inputDetails = userInput.split(" ", NUMBER_OF_EDIT_ARGS); if (inputDetails.length < NUMBER_OF_EDIT_ARGS) { //if arguments are missing e.g. edit 2 - throw new MissingArgException(); + throw new MissingArgEditException(); } assert (inputDetails.length == NUMBER_OF_EDIT_ARGS); @@ -32,7 +32,7 @@ public String[] parseContactDetails(String userInput) //handles illegal input "edit 0 -" and "edit 0 [invalid string]" //valid input will take the form of [, -flag input] so min length should be 2 if (destructuredInputs.length < NUMBER_OF_EDIT_ARGS - 1) { - throw new MissingArgException(); + throw new MissingArgEditException(); } //initialise null array of strings diff --git a/src/main/java/seedu/parser/FailedCommandType.java b/src/main/java/seedu/parser/FailedCommandType.java index 04ed4390b5..c097f5b87f 100644 --- a/src/main/java/seedu/parser/FailedCommandType.java +++ b/src/main/java/seedu/parser/FailedCommandType.java @@ -1,7 +1,7 @@ package seedu.parser; public enum FailedCommandType { - GENERAL, INVALID_FLAG, MISSING_ARG, MISSING_DETAIL, MISSING_INDEX, INVALID_NUM, + GENERAL, INVALID_FLAG, MISSING_ARG, MISSING_ARGS_EDIT, MISSING_DETAIL, MISSING_INDEX, INVALID_NUM, INVALID_FORMAT, NUM_OUT_OF_BOUND, INVALID_INDEX, MISSING_NAME, FORBIDDEN_DETAIL, INVALID_NAME, INVALID_GITHUB_USERNAME, INVALID_LINKEDIN, INVALID_TELEGRAM, INVALID_MAIL, INVALID_TWITTER; diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 06b9449295..a259c9058b 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -22,6 +22,7 @@ import seedu.exception.InvalidNameException; import seedu.exception.InvalidTelegramUsernameException; import seedu.exception.InvalidTwitterUsernameException; +import seedu.exception.MissingArgEditException; import seedu.exception.MissingArgException; import seedu.exception.MissingDetailException; import seedu.exception.MissingIndexException; @@ -175,6 +176,8 @@ private Command parseAddContact(String userInput) { return new FailedCommand(FailedCommandType.INVALID_FLAG); } catch (MissingArgException e) { return new FailedCommand(FailedCommandType.MISSING_ARG); + } catch (MissingArgEditException e) { + return new FailedCommand(FailedCommandType.MISSING_ARGS_EDIT); } catch (MissingNameException e) { return new FailedCommand(FailedCommandType.MISSING_NAME); } catch (MissingDetailException e) { @@ -196,8 +199,8 @@ private Command parseEditContact(String userInput) { // userInput is raw user in return new EditContactCommand(details, userIndex); } catch (InvalidFlagException e) { return new FailedCommand(FailedCommandType.INVALID_FLAG); - } catch (MissingArgException e) { - return new FailedCommand(FailedCommandType.MISSING_ARG); + } catch (MissingArgEditException e) { + return new FailedCommand(FailedCommandType.MISSING_ARGS_EDIT); } catch (NumberFormatException e) { return new FailedCommand(FailedCommandType.INVALID_INDEX); } catch (MissingDetailException e) { diff --git a/src/test/java/seedu/parser/EditContactParserTest.java b/src/test/java/seedu/parser/EditContactParserTest.java index ce570ce83c..d8b0f67b29 100644 --- a/src/test/java/seedu/parser/EditContactParserTest.java +++ b/src/test/java/seedu/parser/EditContactParserTest.java @@ -2,16 +2,7 @@ import org.junit.jupiter.api.Test; -import seedu.exception.ForbiddenDetailException; -import seedu.exception.InvalidEmailException; -import seedu.exception.InvalidFlagException; -import seedu.exception.InvalidGithubUsernameException; -import seedu.exception.InvalidLinkedinUsernameException; -import seedu.exception.InvalidNameException; -import seedu.exception.InvalidTelegramUsernameException; -import seedu.exception.InvalidTwitterUsernameException; -import seedu.exception.MissingArgException; -import seedu.exception.MissingDetailException; +import seedu.exception.*; import seedu.parser.EditContactParser; import java.util.Arrays; @@ -24,7 +15,7 @@ class EditContactParserTest { @Test void parseContactDetails() throws MissingDetailException, - MissingArgException, InvalidFlagException, ForbiddenDetailException, InvalidTelegramUsernameException, + MissingArgEditException, InvalidFlagException, ForbiddenDetailException, InvalidTelegramUsernameException, InvalidNameException, InvalidLinkedinUsernameException, InvalidGithubUsernameException, InvalidTwitterUsernameException, InvalidEmailException { String[] expectedResult = {null, "github", null, null, null, null}; From 0ebcf491d9066646901458c33175d6ec0a2c2fd0 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 26 Oct 2021 19:17:37 +0800 Subject: [PATCH 490/756] Add edit missing arguments message --- src/main/java/seedu/ui/ExceptionTextUi.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index aea70e871b..1d5df68816 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -132,6 +132,15 @@ public static void missingArgMessage() { printDoubleLineMessage(message); } + public static void missingArgEditMessage() { + String message = "There seems to be missing parameters in your request.\n" + + "Please enter command in this format:\n" + + " edit -n -g -e -te -l -tw \n" + + " example : edit 0 -n George -g procoder -te george123" + + "NOTE : At least one flag and description required"; + printDoubleLineMessage(message); + } + public static void missingIndexMessage() { String message = "There seems to be missing index in your request.\n" + "Please enter index in the following way: \n" From 075efb9ca0aa7923ce2a925081a938df49797dbc Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 26 Oct 2021 20:31:41 +0800 Subject: [PATCH 491/756] Add MissingArgAddException class --- src/main/java/seedu/exception/MissingArgAddException.java | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/main/java/seedu/exception/MissingArgAddException.java diff --git a/src/main/java/seedu/exception/MissingArgAddException.java b/src/main/java/seedu/exception/MissingArgAddException.java new file mode 100644 index 0000000000..4be9245d8e --- /dev/null +++ b/src/main/java/seedu/exception/MissingArgAddException.java @@ -0,0 +1,4 @@ +package seedu.exception; + +public class MissingArgAddException extends Exception { +} From 29eb1e2ac615f6e367d9ccabc520377193b5918a Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 26 Oct 2021 20:31:52 +0800 Subject: [PATCH 492/756] Add MissingArgSearchException class --- src/main/java/seedu/exception/MissingArgSearchException.java | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/main/java/seedu/exception/MissingArgSearchException.java diff --git a/src/main/java/seedu/exception/MissingArgSearchException.java b/src/main/java/seedu/exception/MissingArgSearchException.java new file mode 100644 index 0000000000..08e3ba48ff --- /dev/null +++ b/src/main/java/seedu/exception/MissingArgSearchException.java @@ -0,0 +1,4 @@ +package seedu.exception; + +public class MissingArgSearchException extends Exception { +} From 818b9c0d00709a5465e4ac8aed6b9fe402ad5b85 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 26 Oct 2021 20:33:57 +0800 Subject: [PATCH 493/756] Update failed commands and handling --- src/main/java/seedu/command/FailedCommand.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/seedu/command/FailedCommand.java b/src/main/java/seedu/command/FailedCommand.java index df07d8f70e..7a2b6e9c2d 100644 --- a/src/main/java/seedu/command/FailedCommand.java +++ b/src/main/java/seedu/command/FailedCommand.java @@ -28,6 +28,8 @@ public void execute() { break; case MISSING_ARG: // Fallthrough case MISSING_ARGS_EDIT: // Fallthrough + case MISSING_ARGS_ADD: // Fallthrough + case MISSING_ARGS_SEARCH: // Fallthrough case MISSING_DETAIL: // Fallthrough case MISSING_NAME: // Fallthrough case MISSING_INDEX: // Fallthrough @@ -68,6 +70,12 @@ private void missingUserInputExecute() { case MISSING_ARGS_EDIT: ExceptionTextUi.missingArgEditMessage(); break; + case MISSING_ARGS_ADD: + ExceptionTextUi.missingArgAddMessage(); + break; + case MISSING_ARGS_SEARCH: + ExceptionTextUi.missingArgSearchMessage(); + break; case MISSING_DETAIL: ExceptionTextUi.missingDetailMessage(); break; From 2137d77a616836789d850a485897abea23dbc2b6 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 26 Oct 2021 20:34:55 +0800 Subject: [PATCH 494/756] Update exception handling --- .../java/seedu/parser/AddContactParser.java | 6 ++-- src/main/java/seedu/parser/ContactParser.java | 3 +- .../java/seedu/parser/FailedCommandType.java | 2 +- src/main/java/seedu/parser/MainParser.java | 31 +++++++------------ .../seedu/parser/SearchContactParser.java | 14 ++++----- .../seedu/parser/AddContactParserTest.java | 3 +- 6 files changed, 27 insertions(+), 32 deletions(-) diff --git a/src/main/java/seedu/parser/AddContactParser.java b/src/main/java/seedu/parser/AddContactParser.java index 3b62ba9ae5..4a652cf78f 100644 --- a/src/main/java/seedu/parser/AddContactParser.java +++ b/src/main/java/seedu/parser/AddContactParser.java @@ -8,7 +8,7 @@ import seedu.exception.InvalidNameException; import seedu.exception.InvalidTelegramUsernameException; import seedu.exception.InvalidTwitterUsernameException; -import seedu.exception.MissingArgException; +import seedu.exception.MissingArgAddException; import seedu.exception.MissingDetailException; public class AddContactParser extends ContactParser { @@ -26,14 +26,14 @@ public class AddContactParser extends ContactParser { * @throws InvalidFlagException If the flag given is not recognised */ - public String[] parseContactDetails(String userInput) throws InvalidFlagException, MissingArgException, + public String[] parseContactDetails(String userInput) throws InvalidFlagException, MissingArgAddException, InvalidNameException, InvalidGithubUsernameException, InvalidTelegramUsernameException, InvalidLinkedinUsernameException, InvalidTwitterUsernameException, InvalidEmailException, MissingDetailException, ForbiddenDetailException { String[] contactDetails = new String[NUMBER_OF_FIELDS]; String[] destructuredInputs = userInput.split(DETAIL_SEPARATOR); if (destructuredInputs.length < NUMBER_OF_ADD_ARGS) { - throw new MissingArgException(); + throw new MissingArgAddException(); } for (int i = CONTACT_PARAMS_START_INDEX; i < destructuredInputs.length; i++) { parseDetail(contactDetails, destructuredInputs[i]); diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index 959bc28c77..776ed9fc19 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -21,7 +21,8 @@ public abstract class ContactParser extends RegexParser implements ContactDetail public abstract String[] parseContactDetails(String userInput) throws InvalidFlagException, MissingArgException, MissingDetailException, ForbiddenDetailException, InvalidNameException, InvalidGithubUsernameException, InvalidTelegramUsernameException, - InvalidLinkedinUsernameException, InvalidTwitterUsernameException, InvalidEmailException, MissingArgEditException; + InvalidLinkedinUsernameException, InvalidTwitterUsernameException, InvalidEmailException, + MissingArgEditException, MissingArgAddException; /** * This method takes in the contactDetails array and populates it with contact diff --git a/src/main/java/seedu/parser/FailedCommandType.java b/src/main/java/seedu/parser/FailedCommandType.java index c097f5b87f..b7c62474ad 100644 --- a/src/main/java/seedu/parser/FailedCommandType.java +++ b/src/main/java/seedu/parser/FailedCommandType.java @@ -1,7 +1,7 @@ package seedu.parser; public enum FailedCommandType { - GENERAL, INVALID_FLAG, MISSING_ARG, MISSING_ARGS_EDIT, MISSING_DETAIL, MISSING_INDEX, INVALID_NUM, + GENERAL, INVALID_FLAG, MISSING_ARG, MISSING_ARGS_EDIT, MISSING_ARGS_ADD, MISSING_ARGS_SEARCH, MISSING_DETAIL, MISSING_INDEX, INVALID_NUM, INVALID_FORMAT, NUM_OUT_OF_BOUND, INVALID_INDEX, MISSING_NAME, FORBIDDEN_DETAIL, INVALID_NAME, INVALID_GITHUB_USERNAME, INVALID_LINKEDIN, INVALID_TELEGRAM, INVALID_MAIL, INVALID_TWITTER; diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index a259c9058b..367226a5e8 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -22,8 +22,9 @@ import seedu.exception.InvalidNameException; import seedu.exception.InvalidTelegramUsernameException; import seedu.exception.InvalidTwitterUsernameException; +import seedu.exception.MissingArgAddException; import seedu.exception.MissingArgEditException; -import seedu.exception.MissingArgException; +import seedu.exception.MissingArgSearchException; import seedu.exception.MissingDetailException; import seedu.exception.MissingIndexException; import seedu.exception.MissingNameException; @@ -165,7 +166,7 @@ private Command parseQueryCommand(String commandWord, String userInput) { private Command parseAddContact(String userInput) { contactParser = addContactParser; try { - String[] details = contactParser.parseContactDetails(userInput); + String[] details = addContactParser.parseContactDetails(userInput); //check if name is specified in input if (details[NAME_INDEX] == null) { throw new MissingNameException(); @@ -174,14 +175,10 @@ private Command parseAddContact(String userInput) { return new AddContactCommand(details); } catch (InvalidFlagException e) { return new FailedCommand(FailedCommandType.INVALID_FLAG); - } catch (MissingArgException e) { - return new FailedCommand(FailedCommandType.MISSING_ARG); - } catch (MissingArgEditException e) { - return new FailedCommand(FailedCommandType.MISSING_ARGS_EDIT); + } catch (MissingDetailException | MissingArgAddException e) { + return new FailedCommand(FailedCommandType.MISSING_ARGS_ADD); } catch (MissingNameException e) { return new FailedCommand(FailedCommandType.MISSING_NAME); - } catch (MissingDetailException e) { - return new FailedCommand(FailedCommandType.MISSING_DETAIL); } catch (InvalidNameException | InvalidGithubUsernameException | InvalidEmailException | InvalidLinkedinUsernameException | InvalidTelegramUsernameException | InvalidTwitterUsernameException | ForbiddenDetailException e) { @@ -195,18 +192,14 @@ private Command parseEditContact(String userInput) { // userInput is raw user in try { int userIndex = IndexParser.getIndexFromInput(userInput); //throws MissingIndexException String[] details = editContactParser.parseContactDetails(userInput); - //throws InvalidFlagException, MissingDetailException, MissingArgException + //throws InvalidFlagException, MissingDetailException, MissingArgEditException return new EditContactCommand(details, userIndex); } catch (InvalidFlagException e) { return new FailedCommand(FailedCommandType.INVALID_FLAG); - } catch (MissingArgEditException e) { + } catch (MissingDetailException | MissingIndexException | MissingArgEditException e) { return new FailedCommand(FailedCommandType.MISSING_ARGS_EDIT); } catch (NumberFormatException e) { - return new FailedCommand(FailedCommandType.INVALID_INDEX); - } catch (MissingDetailException e) { - return new FailedCommand(FailedCommandType.MISSING_DETAIL); - } catch (MissingIndexException e) { - return new FailedCommand(FailedCommandType.MISSING_INDEX); + return new FailedCommand(FailedCommandType.NUM_OUT_OF_BOUND); } catch (InvalidNameException | InvalidGithubUsernameException | InvalidEmailException | InvalidLinkedinUsernameException | InvalidTelegramUsernameException | InvalidTwitterUsernameException | ForbiddenDetailException e) { @@ -247,7 +240,7 @@ private Command parseViewContact(String userInput) { int viewedIndex = IndexParser.getIndexFromInput(userInput); return new ViewContactCommand(viewedIndex); } catch (NumberFormatException e) { - return new FailedCommand(FailedCommandType.INVALID_INDEX); + return new FailedCommand(FailedCommandType.NUM_OUT_OF_BOUND); } catch (MissingIndexException e) { return new FailedCommand(FailedCommandType.MISSING_INDEX); } @@ -259,7 +252,7 @@ private Command parseDeleteContact(String userInput) { int deletedIndex = IndexParser.getIndexFromInput(userInput); return new DeleteContactCommand(deletedIndex); } catch (NumberFormatException e) { - return new FailedCommand(FailedCommandType.INVALID_INDEX); + return new FailedCommand(FailedCommandType.NUM_OUT_OF_BOUND); } catch (MissingIndexException e) { return new FailedCommand(FailedCommandType.MISSING_INDEX); } @@ -273,8 +266,8 @@ private Command parseSearchCommand(String userInput) { int detailFlag = searchContactParser.getDetailFlag(searchInput); String query = searchContactParser.parseSearchQuery(searchInput); return new SearchContactCommand(query, detailFlag); - } catch (MissingArgException e) { - return new FailedCommand(FailedCommandType.MISSING_ARG); + } catch (MissingArgSearchException e) { + return new FailedCommand(FailedCommandType.MISSING_ARGS_SEARCH); } catch (InvalidFlagException e) { return new FailedCommand(FailedCommandType.INVALID_FLAG); } diff --git a/src/main/java/seedu/parser/SearchContactParser.java b/src/main/java/seedu/parser/SearchContactParser.java index acd1560887..3a291e92d0 100644 --- a/src/main/java/seedu/parser/SearchContactParser.java +++ b/src/main/java/seedu/parser/SearchContactParser.java @@ -2,18 +2,18 @@ import seedu.contact.DetailType; import seedu.exception.InvalidFlagException; -import seedu.exception.MissingArgException; +import seedu.exception.MissingArgSearchException; import static seedu.parser.ContactParser.FLAG_INDEX_IN_DETAILS; import static seedu.parser.ContactParser.NUMBER_OF_DETAILS; public class SearchContactParser implements ContactDetails { //return only search query as a String - public String parseSearchQuery(String searchInput) throws MissingArgException { + public String parseSearchQuery(String searchInput) throws MissingArgSearchException { String[] destructuredInputs = searchInput.trim().split(" ", NUMBER_OF_DETAILS); if (searchInput.trim().charAt(FLAG_INDEX_IN_DETAILS) == '-') { //if there is a flag, remove it if (destructuredInputs.length < NUMBER_OF_DETAILS) { //input starts with - but only flag or weird input - throw new MissingArgException(); + throw new MissingArgSearchException(); } //contains flag and search query return destructuredInputs[NUMBER_OF_DETAILS - 1].toLowerCase().trim(); @@ -22,14 +22,14 @@ public String parseSearchQuery(String searchInput) throws MissingArgException { return searchInput; } - public int getDetailFlag(String searchInput) throws MissingArgException, InvalidFlagException { + public int getDetailFlag(String searchInput) throws MissingArgSearchException, InvalidFlagException { //userInput is not null since searchInput was obtained from getSearchInput if (searchInput.trim().charAt(FLAG_INDEX_IN_DETAILS) == '-') { //if a flag is specified then parse the flag //handles inputs "search -g" which is missing search query String[] destructuredInputs = searchInput.trim().split(" ", NUMBER_OF_DETAILS); if (destructuredInputs.length < NUMBER_OF_DETAILS) { //input starts with - but only flag or weird input - throw new MissingArgException(); + throw new MissingArgSearchException(); } String flag = destructuredInputs[FLAG_INDEX_IN_DETAILS].trim().substring(1); return getIndexToStore(flag); @@ -38,11 +38,11 @@ public int getDetailFlag(String searchInput) throws MissingArgException, Invalid return DetailType.NAME.getIndex(); //search names } - public String getSearchInput(String userInput) throws MissingArgException { + public String getSearchInput(String userInput) throws MissingArgSearchException { //remove the search command String[] destructuredInputs = userInput.trim().split(" ", NUMBER_OF_DETAILS); if (destructuredInputs.length < NUMBER_OF_DETAILS) { //no arguments specified, only "search" - throw new MissingArgException(); + throw new MissingArgSearchException(); } assert destructuredInputs.length == NUMBER_OF_DETAILS; return destructuredInputs[NUMBER_OF_DETAILS - 1]; diff --git a/src/test/java/seedu/parser/AddContactParserTest.java b/src/test/java/seedu/parser/AddContactParserTest.java index 38bd7b325e..afbf71f4dc 100644 --- a/src/test/java/seedu/parser/AddContactParserTest.java +++ b/src/test/java/seedu/parser/AddContactParserTest.java @@ -11,6 +11,7 @@ import seedu.exception.InvalidNameException; import seedu.exception.InvalidTelegramUsernameException; import seedu.exception.InvalidTwitterUsernameException; +import seedu.exception.MissingArgAddException; import seedu.exception.MissingArgException; import seedu.exception.MissingDetailException; @@ -37,7 +38,7 @@ public void setUp() { void parseContactDetails_inputsWithIrregularSpacing_expectCorrectDetails() throws InvalidFlagException, MissingDetailException, MissingArgException, ForbiddenDetailException, InvalidTelegramUsernameException, InvalidNameException, InvalidLinkedinUsernameException, InvalidGithubUsernameException, - InvalidTwitterUsernameException, InvalidEmailException { + InvalidTwitterUsernameException, InvalidEmailException, MissingArgAddException { inputUserInput = " add -n andre -g ng-andre -l linkedin -tw twit -te tel69 -e yoyo@gmail.com"; actualOutput = addContactParser.parseContactDetails(inputUserInput); expectedOutput = new String[]{"andre", "ng-andre", "linkedin", "tel69", "twit", "yoyo@gmail.com"}; From a70d4b725350cce0f0d247de1c40174f43e4c476 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 26 Oct 2021 20:35:55 +0800 Subject: [PATCH 495/756] Add error mesage for Add command --- src/main/java/seedu/ui/ExceptionTextUi.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index 1d5df68816..4abb4acddd 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -138,6 +138,15 @@ public static void missingArgEditMessage() { + " edit -n -g -e -te -l -tw \n" + " example : edit 0 -n George -g procoder -te george123" + "NOTE : At least one flag and description required"; + public static void missingArgAddMessage() { + String message = "There seems to be missing parameters in your request.\n" + + "Please enter command in this format:\n" + + " add -n -g -e -te -l -tw \n" + + " example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe\n" + + "NOTE : At least name and description required\n" + + " Order of parameters do not matter"; + printDoubleLineMessage(message); + } printDoubleLineMessage(message); } From 574222e4bfaec8c882f2efaab04acfe79b517bd7 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 26 Oct 2021 20:36:31 +0800 Subject: [PATCH 496/756] Update error mesage for Edit command --- src/main/java/seedu/ui/ExceptionTextUi.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index 4abb4acddd..b4e11072f1 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -136,8 +136,13 @@ public static void missingArgEditMessage() { String message = "There seems to be missing parameters in your request.\n" + "Please enter command in this format:\n" + " edit -n -g -e -te -l -tw \n" - + " example : edit 0 -n George -g procoder -te george123" - + "NOTE : At least one flag and description required"; + + " example : edit 0 -n George -g procoder -te george123\n" + + "NOTE : At least one flag and description required\n" + + " Order of parameters do not matter except for INDEX\n" + + " \"me\" is used as the INDEX for personal contact."; + printDoubleLineMessage(message); + } + public static void missingArgAddMessage() { String message = "There seems to be missing parameters in your request.\n" + "Please enter command in this format:\n" From 177ef218fe314951b40448bbb55ca6555ffc2172 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 26 Oct 2021 20:36:56 +0800 Subject: [PATCH 497/756] Add error mesage for Search command --- src/main/java/seedu/ui/ExceptionTextUi.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index b4e11072f1..369d240525 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -152,6 +152,14 @@ public static void missingArgAddMessage() { + " Order of parameters do not matter"; printDoubleLineMessage(message); } + + public static void missingArgSearchMessage() { + String message = "There seems to be missing parameters in your request.\n" + + "Please enter command in this format:\n" + + " search \n" + + " example : search Ashraf\n" + + " search -g revflash\n" + + "NOTE : Flag is optional and only one can be specified"; printDoubleLineMessage(message); } From 31d214a1ae880661da34000a32b335631d995ea7 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 26 Oct 2021 20:37:20 +0800 Subject: [PATCH 498/756] Update error mesage for Invalid Index --- src/main/java/seedu/ui/ExceptionTextUi.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index 369d240525..4df1902d6b 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -165,8 +165,9 @@ public static void missingArgSearchMessage() { public static void missingIndexMessage() { String message = "There seems to be missing index in your request.\n" - + "Please enter index in the following way: \n" - + " "; + + "Please enter command in the following way: \n" + + " " + + "Where is rm or view"; printDoubleLineMessage(message); } @@ -207,15 +208,15 @@ public static void numOutOfRangeEditMessage(int listSize) { int maxIndex = listSize - 1; if (listSize == 0) { message = "There are no contacts stored in ConTech.\n" - + "Please input index -1 if you wish to edit your Personal Contact details."; + + "Please input index \"me\" if you wish to edit your Personal Contact details."; } else if (listSize == 1) { message = "The index you have input is out of range.\n" + "You only have 1 contact stored.\n" - + "Please input index -1 if you wish to edit your Personal Contact details."; + + "Please input index \"me\" if you wish to edit your Personal Contact details."; } else { message = "The index you have input is out of range.\n" - + "Please input a number between 0 and " + maxIndex + "to edit saved contacts.\n" - + "Otherwise, input index -1 if you wish to edit your Personal Contact details."; + + "Please input a number between 0 and " + maxIndex + " to edit saved contacts.\n" + + "Otherwise, input index \"me\" if you wish to edit your Personal Contact details."; } printDoubleLineMessage(message); } From af587f720425d7fb13c7d01e3a8fb2d2aa34146e Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 26 Oct 2021 20:58:23 +0800 Subject: [PATCH 499/756] Update UI tests --- text-ui-test/ACTUAL.TXT | 115 ++++++++++++++++++++------------------ text-ui-test/EXPECTED.TXT | 115 ++++++++++++++++++++------------------ 2 files changed, 120 insertions(+), 110 deletions(-) diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index ddc13873e5..81397e93db 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -97,7 +97,12 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. -Please specify your command. +Please enter command in this format: + edit -n -g -e -te -l -tw + example : edit 0 -n George -g procoder -te george123 +NOTE : At least one flag and description required + Order of parameters do not matter except for INDEX + "me" is used as the INDEX for personal contact. ____________________________________________________________ ____________________________________________________________ @@ -121,12 +126,12 @@ You now have 1 contact(s). ____________________________________________________________ ____________________________________________________________ -The number you have input is out of range. +The index you have input is out of range. You only have 1 contact stored. ____________________________________________________________ ____________________________________________________________ -Please enter a valid contact index. +There are no contacts stored in ConTech. ____________________________________________________________ ____________________________________________________________ @@ -166,8 +171,8 @@ You now have 3 contact(s). ____________________________________________________________ ____________________________________________________________ -The number you have input is out of range. -Please input a number between 0 and 2. +The index you have input is out of range. +Please input a index between 0 and 2 ____________________________________________________________ ____________________________________________________________ @@ -206,7 +211,6 @@ ____________________________________________________________ 2. bory 3. mayank 4. ng andre - ____________________________________________________________ ____________________________________________________________ @@ -215,19 +219,17 @@ Github: github.com/ashraf ____________________________________________________________ ____________________________________________________________ -There are missing details. -Please remove any flags with no details, -and ensure that your flags used are correct: - -n NAME - -g GITHUB - -l LINKEDIN - -te TELEGRAM - -tw TWITTER - -e EMAIL +There seems to be missing parameters in your request. +Please enter command in this format: + add -n -g -e -te -l -tw + example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe +NOTE : At least name and description required + Order of parameters do not matter ____________________________________________________________ ____________________________________________________________ -Please enter a valid contact index. +The index you have input is out of range. +Please input a index between 0 and 3 ____________________________________________________________ ____________________________________________________________ @@ -239,8 +241,12 @@ You now have 6 contact(s). ____________________________________________________________ ____________________________________________________________ -There are missing details. -Please specify a name when creating a contact with the flag -n +There seems to be missing parameters in your request. +Please enter command in this format: + add -n -g -e -te -l -tw + example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe +NOTE : At least name and description required + Order of parameters do not matter ____________________________________________________________ ____________________________________________________________ @@ -254,7 +260,6 @@ ____________________________________________________________ 3. lezong 4. mayank 5. ng andre - ____________________________________________________________ ____________________________________________________________ @@ -285,15 +290,12 @@ You now have 4 contact(s). ____________________________________________________________ ____________________________________________________________ -There are missing details. -Please remove any flags with no details, -and ensure that your flags used are correct: - -n NAME - -g GITHUB - -l LINKEDIN - -te TELEGRAM - -tw TWITTER - -e EMAIL +There seems to be missing parameters in your request. +Please enter command in this format: + add -n -g -e -te -l -tw + example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe +NOTE : At least name and description required + Order of parameters do not matter ____________________________________________________________ ____________________________________________________________ @@ -365,23 +367,20 @@ ____________________________________________________________ 1. lezongmun 2. mayank 3. ng andre - ____________________________________________________________ ____________________________________________________________ -Please enter a valid contact index. +The index you have input is out of range. +Please input a index between 0 and 2 ____________________________________________________________ ____________________________________________________________ -There are missing details. -Please remove any flags with no details, -and ensure that your flags used are correct: - -n NAME - -g GITHUB - -l LINKEDIN - -te TELEGRAM - -tw TWITTER - -e EMAIL +There seems to be missing parameters in your request. +Please enter command in this format: + add -n -g -e -te -l -tw + example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe +NOTE : At least name and description required + Order of parameters do not matter ____________________________________________________________ ____________________________________________________________ @@ -435,15 +434,12 @@ Telegram: t.me/_123adad ____________________________________________________________ ____________________________________________________________ -There are missing details. -Please remove any flags with no details, -and ensure that your flags used are correct: - -n NAME - -g GITHUB - -l LINKEDIN - -te TELEGRAM - -tw TWITTER - -e EMAIL +There seems to be missing parameters in your request. +Please enter command in this format: + add -n -g -e -te -l -tw + example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe +NOTE : At least name and description required + Order of parameters do not matter ____________________________________________________________ ____________________________________________________________ @@ -558,17 +554,29 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. -Please specify your command. +Please enter command in this format: + search + example : search Ashraf + search -g revflash +NOTE : Flag is optional and only one can be specified ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. -Please specify your command. +Please enter command in this format: + search + example : search Ashraf + search -g revflash +NOTE : Flag is optional and only one can be specified ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. -Please specify your command. +Please enter command in this format: + search + example : search Ashraf + search -g revflash +NOTE : Flag is optional and only one can be specified ____________________________________________________________ ____________________________________________________________ @@ -610,7 +618,6 @@ ____________________________________________________________ 6. mayank 7. ng andre 8. yusdhsdsd - ____________________________________________________________ ____________________________________________________________ @@ -715,7 +722,6 @@ ____________________________________________________________ 11. mayank 12. ng andre 13. yusdhsdsd - ____________________________________________________________ ____________________________________________________________ @@ -745,7 +751,6 @@ ____________________________________________________________ 11. mayank 12. ng andre 13. yusdhsdsd - ____________________________________________________________ ____________________________________________________________ @@ -757,7 +762,7 @@ ConTech has removed all 14 of your contact(s). ____________________________________________________________ ____________________________________________________________ -You have not stored any contacts in ConTech +You do not have any stored contacts ____________________________________________________________ ____________________________________________________________ diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index ddc13873e5..81397e93db 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -97,7 +97,12 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. -Please specify your command. +Please enter command in this format: + edit -n -g -e -te -l -tw + example : edit 0 -n George -g procoder -te george123 +NOTE : At least one flag and description required + Order of parameters do not matter except for INDEX + "me" is used as the INDEX for personal contact. ____________________________________________________________ ____________________________________________________________ @@ -121,12 +126,12 @@ You now have 1 contact(s). ____________________________________________________________ ____________________________________________________________ -The number you have input is out of range. +The index you have input is out of range. You only have 1 contact stored. ____________________________________________________________ ____________________________________________________________ -Please enter a valid contact index. +There are no contacts stored in ConTech. ____________________________________________________________ ____________________________________________________________ @@ -166,8 +171,8 @@ You now have 3 contact(s). ____________________________________________________________ ____________________________________________________________ -The number you have input is out of range. -Please input a number between 0 and 2. +The index you have input is out of range. +Please input a index between 0 and 2 ____________________________________________________________ ____________________________________________________________ @@ -206,7 +211,6 @@ ____________________________________________________________ 2. bory 3. mayank 4. ng andre - ____________________________________________________________ ____________________________________________________________ @@ -215,19 +219,17 @@ Github: github.com/ashraf ____________________________________________________________ ____________________________________________________________ -There are missing details. -Please remove any flags with no details, -and ensure that your flags used are correct: - -n NAME - -g GITHUB - -l LINKEDIN - -te TELEGRAM - -tw TWITTER - -e EMAIL +There seems to be missing parameters in your request. +Please enter command in this format: + add -n -g -e -te -l -tw + example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe +NOTE : At least name and description required + Order of parameters do not matter ____________________________________________________________ ____________________________________________________________ -Please enter a valid contact index. +The index you have input is out of range. +Please input a index between 0 and 3 ____________________________________________________________ ____________________________________________________________ @@ -239,8 +241,12 @@ You now have 6 contact(s). ____________________________________________________________ ____________________________________________________________ -There are missing details. -Please specify a name when creating a contact with the flag -n +There seems to be missing parameters in your request. +Please enter command in this format: + add -n -g -e -te -l -tw + example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe +NOTE : At least name and description required + Order of parameters do not matter ____________________________________________________________ ____________________________________________________________ @@ -254,7 +260,6 @@ ____________________________________________________________ 3. lezong 4. mayank 5. ng andre - ____________________________________________________________ ____________________________________________________________ @@ -285,15 +290,12 @@ You now have 4 contact(s). ____________________________________________________________ ____________________________________________________________ -There are missing details. -Please remove any flags with no details, -and ensure that your flags used are correct: - -n NAME - -g GITHUB - -l LINKEDIN - -te TELEGRAM - -tw TWITTER - -e EMAIL +There seems to be missing parameters in your request. +Please enter command in this format: + add -n -g -e -te -l -tw + example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe +NOTE : At least name and description required + Order of parameters do not matter ____________________________________________________________ ____________________________________________________________ @@ -365,23 +367,20 @@ ____________________________________________________________ 1. lezongmun 2. mayank 3. ng andre - ____________________________________________________________ ____________________________________________________________ -Please enter a valid contact index. +The index you have input is out of range. +Please input a index between 0 and 2 ____________________________________________________________ ____________________________________________________________ -There are missing details. -Please remove any flags with no details, -and ensure that your flags used are correct: - -n NAME - -g GITHUB - -l LINKEDIN - -te TELEGRAM - -tw TWITTER - -e EMAIL +There seems to be missing parameters in your request. +Please enter command in this format: + add -n -g -e -te -l -tw + example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe +NOTE : At least name and description required + Order of parameters do not matter ____________________________________________________________ ____________________________________________________________ @@ -435,15 +434,12 @@ Telegram: t.me/_123adad ____________________________________________________________ ____________________________________________________________ -There are missing details. -Please remove any flags with no details, -and ensure that your flags used are correct: - -n NAME - -g GITHUB - -l LINKEDIN - -te TELEGRAM - -tw TWITTER - -e EMAIL +There seems to be missing parameters in your request. +Please enter command in this format: + add -n -g -e -te -l -tw + example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe +NOTE : At least name and description required + Order of parameters do not matter ____________________________________________________________ ____________________________________________________________ @@ -558,17 +554,29 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. -Please specify your command. +Please enter command in this format: + search + example : search Ashraf + search -g revflash +NOTE : Flag is optional and only one can be specified ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. -Please specify your command. +Please enter command in this format: + search + example : search Ashraf + search -g revflash +NOTE : Flag is optional and only one can be specified ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. -Please specify your command. +Please enter command in this format: + search + example : search Ashraf + search -g revflash +NOTE : Flag is optional and only one can be specified ____________________________________________________________ ____________________________________________________________ @@ -610,7 +618,6 @@ ____________________________________________________________ 6. mayank 7. ng andre 8. yusdhsdsd - ____________________________________________________________ ____________________________________________________________ @@ -715,7 +722,6 @@ ____________________________________________________________ 11. mayank 12. ng andre 13. yusdhsdsd - ____________________________________________________________ ____________________________________________________________ @@ -745,7 +751,6 @@ ____________________________________________________________ 11. mayank 12. ng andre 13. yusdhsdsd - ____________________________________________________________ ____________________________________________________________ @@ -757,7 +762,7 @@ ConTech has removed all 14 of your contact(s). ____________________________________________________________ ____________________________________________________________ -You have not stored any contacts in ConTech +You do not have any stored contacts ____________________________________________________________ ____________________________________________________________ From 65342366ca93e573282c13341263c3ff1d1742a5 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 26 Oct 2021 20:58:49 +0800 Subject: [PATCH 500/756] Fix exception handling errors --- src/main/java/seedu/parser/ContactParser.java | 14 ++++++++++++-- src/main/java/seedu/parser/MainParser.java | 5 +---- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index 776ed9fc19..bcc9c91c84 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -1,6 +1,16 @@ package seedu.parser; -import seedu.exception.*; +import seedu.exception.ForbiddenDetailException; +import seedu.exception.InvalidEmailException; +import seedu.exception.InvalidFlagException; +import seedu.exception.InvalidGithubUsernameException; +import seedu.exception.InvalidLinkedinUsernameException; +import seedu.exception.InvalidNameException; +import seedu.exception.InvalidTelegramUsernameException; +import seedu.exception.InvalidTwitterUsernameException; +import seedu.exception.MissingArgAddException; +import seedu.exception.MissingArgEditException; +import seedu.exception.MissingDetailException; import java.util.logging.Logger; @@ -19,7 +29,7 @@ public abstract class ContactParser extends RegexParser implements ContactDetail private static final Logger LOGGER = Logger.getLogger(ContactParser.class.getName()); public abstract String[] parseContactDetails(String userInput) - throws InvalidFlagException, MissingArgException, MissingDetailException, ForbiddenDetailException, + throws InvalidFlagException, MissingDetailException, ForbiddenDetailException, InvalidNameException, InvalidGithubUsernameException, InvalidTelegramUsernameException, InvalidLinkedinUsernameException, InvalidTwitterUsernameException, InvalidEmailException, MissingArgEditException, MissingArgAddException; diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 367226a5e8..5cac28e279 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -27,7 +27,6 @@ import seedu.exception.MissingArgSearchException; import seedu.exception.MissingDetailException; import seedu.exception.MissingIndexException; -import seedu.exception.MissingNameException; import static seedu.parser.ContactParser.NUMBER_OF_FIELDS; @@ -169,7 +168,7 @@ private Command parseAddContact(String userInput) { String[] details = addContactParser.parseContactDetails(userInput); //check if name is specified in input if (details[NAME_INDEX] == null) { - throw new MissingNameException(); + throw new MissingArgAddException(); } assert details.length == NUMBER_OF_FIELDS; return new AddContactCommand(details); @@ -177,8 +176,6 @@ private Command parseAddContact(String userInput) { return new FailedCommand(FailedCommandType.INVALID_FLAG); } catch (MissingDetailException | MissingArgAddException e) { return new FailedCommand(FailedCommandType.MISSING_ARGS_ADD); - } catch (MissingNameException e) { - return new FailedCommand(FailedCommandType.MISSING_NAME); } catch (InvalidNameException | InvalidGithubUsernameException | InvalidEmailException | InvalidLinkedinUsernameException | InvalidTelegramUsernameException | InvalidTwitterUsernameException | ForbiddenDetailException e) { From 3bb5a8a9cb4147a2806babba13a6d076b0bcb7bd Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 26 Oct 2021 20:59:03 +0800 Subject: [PATCH 501/756] Fix JUnit exception tests --- src/test/java/seedu/parser/AddContactParserTest.java | 2 +- src/test/java/seedu/parser/EditContactParserTest.java | 11 ++++++++++- src/test/java/seedu/parser/MainParserTest.java | 10 +++++----- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/test/java/seedu/parser/AddContactParserTest.java b/src/test/java/seedu/parser/AddContactParserTest.java index afbf71f4dc..3f5f33904f 100644 --- a/src/test/java/seedu/parser/AddContactParserTest.java +++ b/src/test/java/seedu/parser/AddContactParserTest.java @@ -48,7 +48,7 @@ void parseContactDetails_inputsWithIrregularSpacing_expectCorrectDetails() throw @Test void parseContactDetails_onlyAddInput_expectException() { inputUserInput = " add "; - assertThrows(MissingArgException.class, () -> addContactParser.parseContactDetails(inputUserInput)); + assertThrows(MissingArgAddException.class, () -> addContactParser.parseContactDetails(inputUserInput)); } @Test diff --git a/src/test/java/seedu/parser/EditContactParserTest.java b/src/test/java/seedu/parser/EditContactParserTest.java index d8b0f67b29..1a2edd9ef9 100644 --- a/src/test/java/seedu/parser/EditContactParserTest.java +++ b/src/test/java/seedu/parser/EditContactParserTest.java @@ -2,7 +2,16 @@ import org.junit.jupiter.api.Test; -import seedu.exception.*; +import seedu.exception.ForbiddenDetailException; +import seedu.exception.InvalidEmailException; +import seedu.exception.InvalidFlagException; +import seedu.exception.InvalidGithubUsernameException; +import seedu.exception.InvalidLinkedinUsernameException; +import seedu.exception.InvalidNameException; +import seedu.exception.InvalidTelegramUsernameException; +import seedu.exception.InvalidTwitterUsernameException; +import seedu.exception.MissingArgEditException; +import seedu.exception.MissingDetailException; import seedu.parser.EditContactParser; import java.util.Arrays; diff --git a/src/test/java/seedu/parser/MainParserTest.java b/src/test/java/seedu/parser/MainParserTest.java index 512a5f376a..95d467dffd 100644 --- a/src/test/java/seedu/parser/MainParserTest.java +++ b/src/test/java/seedu/parser/MainParserTest.java @@ -81,7 +81,7 @@ public void parseDeleteCommand_validIndexWithSpaces_expectDeleteContactIndexMatc @Test public void parseDeleteCommand_missingIndex_expectFailedCommandType() { testUserInput = "rm"; - FailedCommandType expectedFailedCommandType = FailedCommandType.MISSING_ARG; + FailedCommandType expectedFailedCommandType = FailedCommandType.MISSING_INDEX; final FailedCommand actualFailedCommand = getParsedCommand(testUserInput, FailedCommand.class); assertEquals(expectedFailedCommandType, actualFailedCommand.getType()); } @@ -89,7 +89,7 @@ public void parseDeleteCommand_missingIndex_expectFailedCommandType() { @Test public void parseDeleteCommand_invalidNumber_expectFailedCommandType() { testUserInput = "rm abc"; - FailedCommandType expectedFailedCommandType = FailedCommandType.INVALID_INDEX; + FailedCommandType expectedFailedCommandType = FailedCommandType.NUM_OUT_OF_BOUND; final FailedCommand actualFailedCommand = getParsedCommand(testUserInput, FailedCommand.class); assertEquals(expectedFailedCommandType, actualFailedCommand.getType()); } @@ -259,7 +259,7 @@ public void parseViewCommand_validIndexWithSpaces_expectViewContactIndexMatch() @Test public void parseViewCommand_missingIndex_expectFailedCommandType() { testUserInput = "view"; - FailedCommandType expectedFailedCommandType = FailedCommandType.MISSING_ARG; + FailedCommandType expectedFailedCommandType = FailedCommandType.MISSING_INDEX; final FailedCommand actualFailedCommand = getParsedCommand(testUserInput, FailedCommand.class); assertEquals(expectedFailedCommandType, actualFailedCommand.getType()); } @@ -267,7 +267,7 @@ public void parseViewCommand_missingIndex_expectFailedCommandType() { @Test public void parseViewCommand_invalidInput_expectFailedCommandType() { testUserInput = "view abc"; - FailedCommandType expectedFailedCommandType = FailedCommandType.INVALID_INDEX; + FailedCommandType expectedFailedCommandType = FailedCommandType.NUM_OUT_OF_BOUND; final FailedCommand actualFailedCommand = getParsedCommand(testUserInput, FailedCommand.class); assertEquals(expectedFailedCommandType, actualFailedCommand.getType()); } @@ -277,7 +277,7 @@ public void parseViewCommand_invalidInput_expectFailedCommandType() { public void parseAddCommand_missingName_expectFailedCommand() { testUserInput = " add -g github "; final FailedCommand actualCommand = getParsedCommand(testUserInput, FailedCommand.class); - final FailedCommand expectedCommand = new FailedCommand(FailedCommandType.MISSING_NAME); + final FailedCommand expectedCommand = new FailedCommand(FailedCommandType.MISSING_ARGS_ADD); assertEquals(expectedCommand.getType(), actualCommand.getType()); } } From f00110764f9ba1e98d1451a919a29d3c2aa0e904 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 26 Oct 2021 21:04:37 +0800 Subject: [PATCH 502/756] Add author tags --- src/main/java/seedu/ui/ExceptionTextUi.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index 4df1902d6b..0db8a020e1 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -132,6 +132,7 @@ public static void missingArgMessage() { printDoubleLineMessage(message); } + //@@author mayankp291 public static void missingArgEditMessage() { String message = "There seems to be missing parameters in your request.\n" + "Please enter command in this format:\n" @@ -143,6 +144,7 @@ public static void missingArgEditMessage() { printDoubleLineMessage(message); } + //@@author mayankp291 public static void missingArgAddMessage() { String message = "There seems to be missing parameters in your request.\n" + "Please enter command in this format:\n" @@ -153,6 +155,7 @@ public static void missingArgAddMessage() { printDoubleLineMessage(message); } + //@@author mayankp291 public static void missingArgSearchMessage() { String message = "There seems to be missing parameters in your request.\n" + "Please enter command in this format:\n" @@ -163,6 +166,7 @@ public static void missingArgSearchMessage() { printDoubleLineMessage(message); } + //@@author mayankp291 public static void missingIndexMessage() { String message = "There seems to be missing index in your request.\n" + "Please enter command in the following way: \n" @@ -171,6 +175,7 @@ public static void missingIndexMessage() { printDoubleLineMessage(message); } + //@@author public static void invalidNumMessage() { String message = "That does not seem to be a number.\n" + "Please provide a number instead."; printDoubleLineMessage(message); @@ -203,6 +208,7 @@ public static void numOutOfRangeMessage(int listSize) { printDoubleLineMessage(message); } + //@@author mayankp291 public static void numOutOfRangeEditMessage(int listSize) { String message; int maxIndex = listSize - 1; @@ -221,6 +227,7 @@ public static void numOutOfRangeEditMessage(int listSize) { printDoubleLineMessage(message); } + //@@author public static void corruptLineMessage(String line, int lineIndex, String contactFilePath) { System.out.println(contactFilePath + ":" + lineIndex + " - \"" + line + "\" is corrupted and not loaded."); } From 95a86a156153fe2e8cb98ee6c5746397a0223c3c Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 26 Oct 2021 21:07:37 +0800 Subject: [PATCH 503/756] Fix formatting --- src/main/java/seedu/exception/MissingArgAddException.java | 2 ++ src/main/java/seedu/exception/MissingArgEditException.java | 2 ++ src/main/java/seedu/exception/MissingArgSearchException.java | 2 ++ src/main/java/seedu/exception/MissingIndexException.java | 2 ++ 4 files changed, 8 insertions(+) diff --git a/src/main/java/seedu/exception/MissingArgAddException.java b/src/main/java/seedu/exception/MissingArgAddException.java index 4be9245d8e..2e6ef3839a 100644 --- a/src/main/java/seedu/exception/MissingArgAddException.java +++ b/src/main/java/seedu/exception/MissingArgAddException.java @@ -1,3 +1,5 @@ +//@@author mayankp291 + package seedu.exception; public class MissingArgAddException extends Exception { diff --git a/src/main/java/seedu/exception/MissingArgEditException.java b/src/main/java/seedu/exception/MissingArgEditException.java index 7dc08fedd8..095ffe3bcd 100644 --- a/src/main/java/seedu/exception/MissingArgEditException.java +++ b/src/main/java/seedu/exception/MissingArgEditException.java @@ -1,3 +1,5 @@ +//@@author mayankp291 + package seedu.exception; public class MissingArgEditException extends Exception { diff --git a/src/main/java/seedu/exception/MissingArgSearchException.java b/src/main/java/seedu/exception/MissingArgSearchException.java index 08e3ba48ff..3ce56ce77e 100644 --- a/src/main/java/seedu/exception/MissingArgSearchException.java +++ b/src/main/java/seedu/exception/MissingArgSearchException.java @@ -1,3 +1,5 @@ +//@@author mayankp291 + package seedu.exception; public class MissingArgSearchException extends Exception { diff --git a/src/main/java/seedu/exception/MissingIndexException.java b/src/main/java/seedu/exception/MissingIndexException.java index e8097aa10e..19bdf8e787 100644 --- a/src/main/java/seedu/exception/MissingIndexException.java +++ b/src/main/java/seedu/exception/MissingIndexException.java @@ -1,3 +1,5 @@ +//@@author mayankp291 + package seedu.exception; public class MissingIndexException extends Exception { From 5da1177659829d6bcc3b22b56c6d83e211b394a6 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 26 Oct 2021 21:35:49 +0800 Subject: [PATCH 504/756] Update methods and constants for TextUI --- src/main/java/seedu/ui/TextUi.java | 63 +++++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 6 deletions(-) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 2f70a29fdd..f26295f1f9 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -11,6 +11,11 @@ public abstract class TextUi { + " \\_____\\___/|_| |_|_|\\___|\\___|_| |_|\n" + " "; private static final String LINE = "____________________________________________________________\n"; + public static final int GITHUB_INDEX = 1; + public static final int LINKEDIN_INDEX = 2; + public static final int TELEGRAM_INDEX = 3; + public static final int TWITTER_INDEX = 4; + public static final int EMAIL_INDEX = 5; // Used for print messages after user inputs private static void printDoubleLineMessage(String message) { @@ -195,16 +200,63 @@ public static void confirmDeleteAllMessage() { printDoubleLineMessage(message); } - public static void confirmDeleteFieldMessage() { - String message = "Delete the specified fields? (y/n)"; - printDoubleLineMessage(message); + public static void confirmDeleteFieldMessage(boolean[] deletedFields, Contact contact) { + String message = "Delete the following fields for " + contact.getName() + "? (y/n)\n"; + String fields = deletedFieldsGenerator(deletedFields, contact); + printDoubleLineMessage(message + fields); } - public static void deleteFieldsMessage() { - String message = "The specified fields have been deleted."; + public static void deleteFieldsMessage(boolean[] deletedFields, Contact contact) { + String message = "The specified fields for " + contact.getName() + " have been deleted.\n"; + //String fields = deletedFieldsGenerator(deletedFields, contact); printDoubleLineMessage(message); } + public static String deletedFieldsGenerator(boolean[] deletedFields, Contact contact) { + StringBuilder output = new StringBuilder(); + assert deletedFields.length == 7; + for (int i = 1; i < 6; i++) { + switch (i) { + case GITHUB_INDEX: + if (contact.getGithub() != null && deletedFields[GITHUB_INDEX]) { + output.append(ViewMessageFormatterUi.viewGithubFormatter(contact)).append("\n"); + } + break; + case LINKEDIN_INDEX: + if (contact.getLinkedin() != null && deletedFields[LINKEDIN_INDEX]) { + output.append(ViewMessageFormatterUi.viewLinkedinFormatter(contact)).append("\n"); + } + break; + case TELEGRAM_INDEX: + if (contact.getTelegram() != null && deletedFields[TELEGRAM_INDEX]) { + output.append(ViewMessageFormatterUi.viewTelegramFormatter(contact)).append("\n"); + } + break; + case TWITTER_INDEX: + if (contact.getTwitter() != null && deletedFields[TWITTER_INDEX]) { + output.append(ViewMessageFormatterUi.viewTwitterFormatter(contact)).append("\n"); + } + break; + case EMAIL_INDEX: + if (contact.getEmail() != null && deletedFields[EMAIL_INDEX]) { + output.append(ViewMessageFormatterUi.viewEmailFormatter(contact)).append("\n"); + } + break; + default: + //should never reach here + assert false; + } + } + if (output.toString().isEmpty()) { + return ""; + } + return output.toString(); + } + + public static void noDeleteFields() { + String message = "The specified fields are already empty.\n" + "No fields will be deleted"; + printDoubleLineMessage(message); + } public static void deleteContactMessage(String contactName, int listSize) { String message = "ConTech has removed the specified contact: " + contactName + "\n" + "You now have " + listSize @@ -317,5 +369,4 @@ public static void successfulImportMessage(int numberOfLines) { String message = "ConTech has successfully imported " + numberOfLines + " lines"; printDoubleLineMessage(message); } - } From d857c6e5a7bdc954d20866a040f4ac20e41c39d9 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 26 Oct 2021 21:40:18 +0800 Subject: [PATCH 505/756] Remove unused parameter from textUI method --- src/main/java/seedu/ui/TextUi.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index f26295f1f9..a0a6248c8e 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -206,9 +206,8 @@ public static void confirmDeleteFieldMessage(boolean[] deletedFields, Contact co printDoubleLineMessage(message + fields); } - public static void deleteFieldsMessage(boolean[] deletedFields, Contact contact) { - String message = "The specified fields for " + contact.getName() + " have been deleted.\n"; - //String fields = deletedFieldsGenerator(deletedFields, contact); + public static void deleteFieldsMessage(Contact contact) { + String message = "The specified fields for " + contact.getName() + " have been deleted."; printDoubleLineMessage(message); } From 0b9b7f6f39c2060de7b283291c28c438d2757243 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 26 Oct 2021 21:40:47 +0800 Subject: [PATCH 506/756] Update delete contact command to ignore empty fields --- src/main/java/seedu/command/DeleteContactCommand.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/command/DeleteContactCommand.java b/src/main/java/seedu/command/DeleteContactCommand.java index e963173f50..c9b49847ef 100644 --- a/src/main/java/seedu/command/DeleteContactCommand.java +++ b/src/main/java/seedu/command/DeleteContactCommand.java @@ -66,7 +66,12 @@ private void deleteAllContacts() { private void deleteFields() { Contact deletedContact = IndexParser.getContactFromIndex(contactIndex, contactList); assert contactIndex >= 0 && contactIndex < contactList.getListSize(); - TextUi.confirmDeleteFieldMessage(); + if (TextUi.deletedFieldsGenerator(deleteDetails, deletedContact).isEmpty()) { + //if no fields exist, return false + TextUi.noDeleteFields(); + return; + } + TextUi.confirmDeleteFieldMessage(deleteDetails, deletedContact); String userConfirmation = UserInputTextUi.getUserConfirmation(); if (userConfirmation.equalsIgnoreCase(ACKNOWLEDGE_DELETE)) { if (deleteDetails[GITHUB_INDEX]) { @@ -84,7 +89,7 @@ private void deleteFields() { if (deleteDetails[EMAIL_INDEX]) { deletedContact.setEmail(null); } - TextUi.deleteFieldsMessage(); + TextUi.deleteFieldsMessage(deletedContact); } else { assert !userConfirmation.equalsIgnoreCase(ACKNOWLEDGE_DELETE); TextUi.cancelDeleteContactMessage(); From ae3735dc929660e88a215868c812455644dc106f Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 26 Oct 2021 22:46:55 +0800 Subject: [PATCH 507/756] Add detailFormatter for ViewMessageFormatter --- .../java/seedu/ui/ViewMessageFormatterUi.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/main/java/seedu/ui/ViewMessageFormatterUi.java b/src/main/java/seedu/ui/ViewMessageFormatterUi.java index d997538fc9..8bc68a1e60 100644 --- a/src/main/java/seedu/ui/ViewMessageFormatterUi.java +++ b/src/main/java/seedu/ui/ViewMessageFormatterUi.java @@ -5,6 +5,14 @@ import seedu.contact.Contact; public class ViewMessageFormatterUi { + public static final int NAME_INDEX = 0; + public static final int GITHUB_INDEX = 1; + public static final int LINKEDIN_INDEX = 2; + public static final int TELEGRAM_INDEX = 3; + public static final int TWITTER_INDEX = 4; + public static final int EMAIL_INDEX = 5; + public static final int NUMBER_OF_FIELDS = 6; + public static String viewNameFormatter(Contact contact) { if (contact.getName() == null) { return ""; @@ -47,4 +55,23 @@ public static String viewTwitterFormatter(Contact contact) { return "\nTwitter: twitter.com/" + contact.getTwitter(); } + public static String viewDetailFormatter(Contact contact, int index) { + switch (index) { + case NAME_INDEX: + return viewNameFormatter(contact); + case GITHUB_INDEX: + return viewGithubFormatter(contact); + case LINKEDIN_INDEX: + return viewLinkedinFormatter(contact); + case TELEGRAM_INDEX: + return viewTelegramFormatter(contact); + case TWITTER_INDEX: + return viewTwitterFormatter(contact); + case EMAIL_INDEX: + return viewEmailFormatter(contact); + default: + assert false; //should never reach here + return null; + } + } } From 7694385271eae8f5e77962621d7978c8c3e16ebc Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 26 Oct 2021 22:55:55 +0800 Subject: [PATCH 508/756] Abstract deletedFieldsGenerator method --- src/main/java/seedu/parser/MainParser.java | 1 - src/main/java/seedu/ui/TextUi.java | 37 +++------------------- 2 files changed, 4 insertions(+), 34 deletions(-) diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 9ffc176027..43db055518 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -1,6 +1,5 @@ package seedu.parser; - import seedu.command.AddContactCommand; import seedu.command.Command; import seedu.command.DeleteContactCommand; diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index a0a6248c8e..7d4970b9c9 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -12,9 +12,6 @@ public abstract class TextUi { private static final String LINE = "____________________________________________________________\n"; public static final int GITHUB_INDEX = 1; - public static final int LINKEDIN_INDEX = 2; - public static final int TELEGRAM_INDEX = 3; - public static final int TWITTER_INDEX = 4; public static final int EMAIL_INDEX = 5; // Used for print messages after user inputs @@ -214,36 +211,10 @@ public static void deleteFieldsMessage(Contact contact) { public static String deletedFieldsGenerator(boolean[] deletedFields, Contact contact) { StringBuilder output = new StringBuilder(); assert deletedFields.length == 7; - for (int i = 1; i < 6; i++) { - switch (i) { - case GITHUB_INDEX: - if (contact.getGithub() != null && deletedFields[GITHUB_INDEX]) { - output.append(ViewMessageFormatterUi.viewGithubFormatter(contact)).append("\n"); - } - break; - case LINKEDIN_INDEX: - if (contact.getLinkedin() != null && deletedFields[LINKEDIN_INDEX]) { - output.append(ViewMessageFormatterUi.viewLinkedinFormatter(contact)).append("\n"); - } - break; - case TELEGRAM_INDEX: - if (contact.getTelegram() != null && deletedFields[TELEGRAM_INDEX]) { - output.append(ViewMessageFormatterUi.viewTelegramFormatter(contact)).append("\n"); - } - break; - case TWITTER_INDEX: - if (contact.getTwitter() != null && deletedFields[TWITTER_INDEX]) { - output.append(ViewMessageFormatterUi.viewTwitterFormatter(contact)).append("\n"); - } - break; - case EMAIL_INDEX: - if (contact.getEmail() != null && deletedFields[EMAIL_INDEX]) { - output.append(ViewMessageFormatterUi.viewEmailFormatter(contact)).append("\n"); - } - break; - default: - //should never reach here - assert false; + String[] contactDetails = contact.getContactStringArray(); + for (int i = GITHUB_INDEX; i < EMAIL_INDEX; i++) { //from GitHub to Email + if (contactDetails[i] != null && deletedFields[i]) { + output.append(ViewMessageFormatterUi.viewDetailFormatter(contact, i)); } } if (output.toString().isEmpty()) { From e7080d609a2ace7090044b76bbfd1c8a6bce22e5 Mon Sep 17 00:00:00 2001 From: Ng Andre Date: Tue, 26 Oct 2021 23:01:44 +0800 Subject: [PATCH 509/756] Update boolean array names to adhere to coding standards --- .../seedu/command/DeleteContactCommand.java | 22 +++++++++---------- .../seedu/parser/DeleteContactParser.java | 16 +++++++------- src/main/java/seedu/parser/MainParser.java | 4 ++-- src/main/java/seedu/ui/TextUi.java | 10 ++++----- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/main/java/seedu/command/DeleteContactCommand.java b/src/main/java/seedu/command/DeleteContactCommand.java index c9b49847ef..4964807a0b 100644 --- a/src/main/java/seedu/command/DeleteContactCommand.java +++ b/src/main/java/seedu/command/DeleteContactCommand.java @@ -19,11 +19,11 @@ public class DeleteContactCommand extends Command { public static final int EMAIL_INDEX = 5; private final int contactIndex; - private final boolean[] deleteDetails; + private final boolean[] hasDeletedDetail; - public DeleteContactCommand(int contactIndex, boolean[] deleteDetails) { + public DeleteContactCommand(int contactIndex, boolean[] hasDeletedDetail) { this.contactIndex = contactIndex; - this.deleteDetails = deleteDetails; + this.hasDeletedDetail = hasDeletedDetail; } public int getContactIndex() { @@ -66,27 +66,27 @@ private void deleteAllContacts() { private void deleteFields() { Contact deletedContact = IndexParser.getContactFromIndex(contactIndex, contactList); assert contactIndex >= 0 && contactIndex < contactList.getListSize(); - if (TextUi.deletedFieldsGenerator(deleteDetails, deletedContact).isEmpty()) { + if (TextUi.deletedFieldsGenerator(hasDeletedDetail, deletedContact).isEmpty()) { //if no fields exist, return false TextUi.noDeleteFields(); return; } - TextUi.confirmDeleteFieldMessage(deleteDetails, deletedContact); + TextUi.confirmDeleteFieldMessage(hasDeletedDetail, deletedContact); String userConfirmation = UserInputTextUi.getUserConfirmation(); if (userConfirmation.equalsIgnoreCase(ACKNOWLEDGE_DELETE)) { - if (deleteDetails[GITHUB_INDEX]) { + if (hasDeletedDetail[GITHUB_INDEX]) { deletedContact.setGithub(null); } - if (deleteDetails[LINKEDIN_INDEX]) { + if (hasDeletedDetail[LINKEDIN_INDEX]) { deletedContact.setLinkedin(null); } - if (deleteDetails[TELEGRAM_INDEX]) { + if (hasDeletedDetail[TELEGRAM_INDEX]) { deletedContact.setTelegram(null); } - if (deleteDetails[TWITTER_INDEX]) { + if (hasDeletedDetail[TWITTER_INDEX]) { deletedContact.setTwitter(null); } - if (deleteDetails[EMAIL_INDEX]) { + if (hasDeletedDetail[EMAIL_INDEX]) { deletedContact.setEmail(null); } TextUi.deleteFieldsMessage(deletedContact); @@ -100,7 +100,7 @@ public void execute() { try { if (contactIndex == DELETE_ALL_CONTACTS) { deleteAllContacts(); - } else if (deleteDetails[6]) { //delete entire contact + } else if (hasDeletedDetail[6]) { //delete entire contact deleteSelectedContact(); } else { deleteFields(); diff --git a/src/main/java/seedu/parser/DeleteContactParser.java b/src/main/java/seedu/parser/DeleteContactParser.java index 8a0cb16b26..bf348d372e 100644 --- a/src/main/java/seedu/parser/DeleteContactParser.java +++ b/src/main/java/seedu/parser/DeleteContactParser.java @@ -12,13 +12,13 @@ public class DeleteContactParser implements ContactDetails { public static final int NUMBER_OF_DELETE_ARGS = 3; public static final String BUFFER = " "; - boolean[] getDeleteDetails(String userInput) throws InvalidFlagException, InvalidDeleteDetailException { - boolean[] deleteDetails = new boolean[7]; //all false by default + boolean[] hasDeletedDetail(String userInput) throws InvalidFlagException, InvalidDeleteDetailException { + boolean[] hasDeletedDetail = new boolean[7]; //all false by default //deleteDetails[6] is true if delete entire contact String[] inputDetails = userInput.trim().split(" ", NUMBER_OF_DELETE_ARGS); if (inputDetails.length < NUMBER_OF_DELETE_ARGS) { //no flags specified, delete entire contact - deleteDetails[DELETE_CONTACT_INDEX] = true; - return deleteDetails; + hasDeletedDetail[DELETE_CONTACT_INDEX] = true; + return hasDeletedDetail; } assert inputDetails.length == NUMBER_OF_DELETE_ARGS; //flags may be specified String[] destructuredInputs = (BUFFER + inputDetails[USER_INFO_INDEX]).split(DETAIL_SEPARATOR); @@ -26,8 +26,8 @@ boolean[] getDeleteDetails(String userInput) throws InvalidFlagException, Invali //valid input will take the form of [, -flag input] so min length should be 2 if (destructuredInputs.length < NUMBER_OF_DELETE_ARGS - 1) { //input is in the form delete INDEX [invalid string] so delete entire contact - deleteDetails[DELETE_CONTACT_INDEX] = true; - return deleteDetails; + hasDeletedDetail[DELETE_CONTACT_INDEX] = true; + return hasDeletedDetail; } for (int i = 1; i < destructuredInputs.length; i++) { int flag = getIndexToStore(destructuredInputs[i].trim()); @@ -35,9 +35,9 @@ boolean[] getDeleteDetails(String userInput) throws InvalidFlagException, Invali if (flag == 0) { //cannot delete -n throw new InvalidDeleteDetailException(); } else { - deleteDetails[flag] = true; + hasDeletedDetail[flag] = true; } } - return deleteDetails; + return hasDeletedDetail; } } diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 43db055518..e74ab98de2 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -252,8 +252,8 @@ private Command parseViewContact(String userInput) { private Command parseDeleteContact(String userInput) { try { int deletedIndex = IndexParser.getIndexFromInput(userInput); - boolean[] deleteDetails = deleteContactParser.getDeleteDetails(userInput); - return new DeleteContactCommand(deletedIndex, deleteDetails); + boolean[] hasDeletedDetail = deleteContactParser.hasDeletedDetail(userInput); + return new DeleteContactCommand(deletedIndex, hasDeletedDetail); } catch (MissingArgException e) { return new FailedCommand(FailedCommandType.MISSING_ARG); } catch (NumberFormatException e) { diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 7d4970b9c9..db4ad84cf8 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -197,9 +197,9 @@ public static void confirmDeleteAllMessage() { printDoubleLineMessage(message); } - public static void confirmDeleteFieldMessage(boolean[] deletedFields, Contact contact) { + public static void confirmDeleteFieldMessage(boolean[] hasDeletedDetail, Contact contact) { String message = "Delete the following fields for " + contact.getName() + "? (y/n)\n"; - String fields = deletedFieldsGenerator(deletedFields, contact); + String fields = deletedFieldsGenerator(hasDeletedDetail, contact); printDoubleLineMessage(message + fields); } @@ -208,12 +208,12 @@ public static void deleteFieldsMessage(Contact contact) { printDoubleLineMessage(message); } - public static String deletedFieldsGenerator(boolean[] deletedFields, Contact contact) { + public static String deletedFieldsGenerator(boolean[] hasDeletedDetail, Contact contact) { StringBuilder output = new StringBuilder(); - assert deletedFields.length == 7; + assert hasDeletedDetail.length == 7; String[] contactDetails = contact.getContactStringArray(); for (int i = GITHUB_INDEX; i < EMAIL_INDEX; i++) { //from GitHub to Email - if (contactDetails[i] != null && deletedFields[i]) { + if (contactDetails[i] != null && hasDeletedDetail[i]) { output.append(ViewMessageFormatterUi.viewDetailFormatter(contact, i)); } } From abb1cefa4968badf709d6d0210c40cd4657971db Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Tue, 26 Oct 2021 23:15:07 +0800 Subject: [PATCH 510/756] Update formatting to adhere to checkstyle --- src/main/java/seedu/parser/FailedCommandType.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/FailedCommandType.java b/src/main/java/seedu/parser/FailedCommandType.java index b7c62474ad..9433a3a4d9 100644 --- a/src/main/java/seedu/parser/FailedCommandType.java +++ b/src/main/java/seedu/parser/FailedCommandType.java @@ -1,7 +1,8 @@ package seedu.parser; public enum FailedCommandType { - GENERAL, INVALID_FLAG, MISSING_ARG, MISSING_ARGS_EDIT, MISSING_ARGS_ADD, MISSING_ARGS_SEARCH, MISSING_DETAIL, MISSING_INDEX, INVALID_NUM, + GENERAL, INVALID_FLAG, MISSING_ARG, MISSING_ARGS_EDIT, MISSING_ARGS_ADD, MISSING_ARGS_SEARCH, + MISSING_DETAIL, MISSING_INDEX, INVALID_NUM, INVALID_FORMAT, NUM_OUT_OF_BOUND, INVALID_INDEX, MISSING_NAME, FORBIDDEN_DETAIL, INVALID_NAME, INVALID_GITHUB_USERNAME, INVALID_LINKEDIN, INVALID_TELEGRAM, INVALID_MAIL, INVALID_TWITTER; From 4a11f06253092a062f64dd5b3c845ba5c63c75a4 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 27 Oct 2021 00:22:39 +0800 Subject: [PATCH 511/756] Fix Ui issue --- src/main/java/seedu/command/FailedCommand.java | 4 ++-- src/main/java/seedu/parser/MainParser.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/command/FailedCommand.java b/src/main/java/seedu/command/FailedCommand.java index 8c9a6c2574..696048217d 100644 --- a/src/main/java/seedu/command/FailedCommand.java +++ b/src/main/java/seedu/command/FailedCommand.java @@ -57,10 +57,10 @@ private void invalidUserInputExecute() { ExceptionTextUi.invalidFormatMessage(); break; case NUM_OUT_OF_BOUND: - ExceptionTextUi.numOutOfRangeMessage(contactList.getListSize() - 1); + ExceptionTextUi.numOutOfRangeMessage(contactList.getListSize()); break; case NUM_OUT_OF_BOUND_EDIT: - ExceptionTextUi.numOutOfRangeEditMessage(contactList.getListSize() - 1); + ExceptionTextUi.numOutOfRangeEditMessage(contactList.getListSize()); break; case INVALID_DELETE: ExceptionTextUi.invalidDeleteFlag(); diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 4238ebabce..7a3ac10d4b 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -188,8 +188,8 @@ private Command parseAddContact(String userInput) { private Command parseEditContact(String userInput) { // userInput is raw user input contactParser = editContactParser; try { - int userIndex = IndexParser.getIndexFromInput(userInput); //throws MissingIndexException String[] details = editContactParser.parseContactDetails(userInput); + int userIndex = IndexParser.getIndexFromInput(userInput); //throws MissingIndexException //throws InvalidFlagException, MissingDetailException, MissingArgEditException return new EditContactCommand(details, userIndex); } catch (InvalidFlagException e) { From 13cd0e3cb806801d141347bcef89d61f2f2e344a Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 27 Oct 2021 01:00:21 +0800 Subject: [PATCH 512/756] Remove redundant code --- src/main/java/seedu/exception/MissingArgException.java | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 src/main/java/seedu/exception/MissingArgException.java diff --git a/src/main/java/seedu/exception/MissingArgException.java b/src/main/java/seedu/exception/MissingArgException.java deleted file mode 100644 index 61d61b3107..0000000000 --- a/src/main/java/seedu/exception/MissingArgException.java +++ /dev/null @@ -1,4 +0,0 @@ -package seedu.exception; - -public class MissingArgException extends Exception { -} From b6cda47813551a84c55315966910cea6b65f693c Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 27 Oct 2021 01:01:01 +0800 Subject: [PATCH 513/756] Fix exception handling bugs --- src/main/java/seedu/command/FailedCommand.java | 4 ---- src/main/java/seedu/parser/FailedCommandType.java | 2 +- src/main/java/seedu/ui/ExceptionTextUi.java | 9 ++------- src/test/java/seedu/parser/AddContactParserTest.java | 3 +-- 4 files changed, 4 insertions(+), 14 deletions(-) diff --git a/src/main/java/seedu/command/FailedCommand.java b/src/main/java/seedu/command/FailedCommand.java index 696048217d..bf8b80e3e2 100644 --- a/src/main/java/seedu/command/FailedCommand.java +++ b/src/main/java/seedu/command/FailedCommand.java @@ -28,7 +28,6 @@ public void execute() { case INVALID_DELETE: //Fallthrough invalidUserInputExecute(); break; - case MISSING_ARG: // Fallthrough case MISSING_ARGS_EDIT: // Fallthrough case MISSING_ARGS_ADD: // Fallthrough case MISSING_ARGS_SEARCH: // Fallthrough @@ -72,9 +71,6 @@ private void invalidUserInputExecute() { private void missingUserInputExecute() { switch (type) { - case MISSING_ARG: - ExceptionTextUi.missingArgMessage(); - break; case MISSING_ARGS_EDIT: ExceptionTextUi.missingArgEditMessage(); break; diff --git a/src/main/java/seedu/parser/FailedCommandType.java b/src/main/java/seedu/parser/FailedCommandType.java index 568a7936c0..83b0b866ae 100644 --- a/src/main/java/seedu/parser/FailedCommandType.java +++ b/src/main/java/seedu/parser/FailedCommandType.java @@ -1,7 +1,7 @@ package seedu.parser; public enum FailedCommandType { - GENERAL, INVALID_FLAG, MISSING_ARG, MISSING_ARGS_EDIT, MISSING_ARGS_ADD, MISSING_ARGS_SEARCH, + GENERAL, INVALID_FLAG, MISSING_ARGS_EDIT, MISSING_ARGS_ADD, MISSING_ARGS_SEARCH, MISSING_DETAIL, MISSING_INDEX, INVALID_NUM, INVALID_FORMAT, NUM_OUT_OF_BOUND, NUM_OUT_OF_BOUND_EDIT, INVALID_INDEX, MISSING_NAME, FORBIDDEN_DETAIL, INVALID_NAME, INVALID_GITHUB_USERNAME, diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index c5aa507607..c3d84ad7fa 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -127,11 +127,6 @@ public static void missingDetailMessage() { printDoubleLineMessage(message); } - public static void missingArgMessage() { - String message = "There seems to be missing parameters in your request.\n" + "Please specify your command."; - printDoubleLineMessage(message); - } - //@@author mayankp291 public static void missingArgEditMessage() { String message = "There seems to be missing parameters in your request.\n" @@ -168,9 +163,9 @@ public static void missingArgSearchMessage() { //@@author mayankp291 public static void missingIndexMessage() { - String message = "There seems to be missing index in your request.\n" + String message = "There seems to be missing or invalid index in your request.\n" + "Please enter command in the following way: \n" - + " " + + " \n" + "Where is rm or view"; printDoubleLineMessage(message); } diff --git a/src/test/java/seedu/parser/AddContactParserTest.java b/src/test/java/seedu/parser/AddContactParserTest.java index 3f5f33904f..ad56aff0b4 100644 --- a/src/test/java/seedu/parser/AddContactParserTest.java +++ b/src/test/java/seedu/parser/AddContactParserTest.java @@ -12,7 +12,6 @@ import seedu.exception.InvalidTelegramUsernameException; import seedu.exception.InvalidTwitterUsernameException; import seedu.exception.MissingArgAddException; -import seedu.exception.MissingArgException; import seedu.exception.MissingDetailException; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -36,7 +35,7 @@ public void setUp() { @Test void parseContactDetails_inputsWithIrregularSpacing_expectCorrectDetails() throws InvalidFlagException, - MissingDetailException, MissingArgException, ForbiddenDetailException, InvalidTelegramUsernameException, + MissingDetailException, ForbiddenDetailException, InvalidTelegramUsernameException, InvalidNameException, InvalidLinkedinUsernameException, InvalidGithubUsernameException, InvalidTwitterUsernameException, InvalidEmailException, MissingArgAddException { inputUserInput = " add -n andre -g ng-andre -l linkedin -tw twit -te tel69 -e yoyo@gmail.com"; From 835b607754f7cc5498f5c2fa32c7a8255897a110 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 27 Oct 2021 01:01:18 +0800 Subject: [PATCH 514/756] Fix delete bug using regex --- src/main/java/seedu/parser/IndexParser.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/IndexParser.java b/src/main/java/seedu/parser/IndexParser.java index c9d72e93d4..4fe784ef1b 100644 --- a/src/main/java/seedu/parser/IndexParser.java +++ b/src/main/java/seedu/parser/IndexParser.java @@ -16,7 +16,7 @@ public class IndexParser { private static final int PERSONAL_CONTACT_ID = -1; private static final String REMOVE_ALL_INDEX = "all"; private static final int REMOVE_ALL_ID = -2; - + private static final String numbers = "[0-9]+"; public static int getIndexFromInput(String userInput) throws NumberFormatException, MissingIndexException { @@ -38,6 +38,9 @@ public static int getIndexFromInput(String userInput) if (significantIndex.equalsIgnoreCase(REMOVE_ALL_INDEX)) { return REMOVE_ALL_ID; } + if (!significantIndex.matches(numbers)) { + throw new MissingIndexException(); + } // takes only the first word/ element as given user input, and throws NumberFormatExcept if it is not integer int index = Integer.parseInt(significantIndex); if (index < 0) { From 0e4e7262103c237a5fa21b891f6bc8dfe6cbb357 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 27 Oct 2021 01:55:43 +0800 Subject: [PATCH 515/756] Add author tags --- .../java/seedu/parser/AddContactParserTest.java | 2 ++ src/test/java/seedu/parser/MainParserTest.java | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/test/java/seedu/parser/AddContactParserTest.java b/src/test/java/seedu/parser/AddContactParserTest.java index ad56aff0b4..95c3c70069 100644 --- a/src/test/java/seedu/parser/AddContactParserTest.java +++ b/src/test/java/seedu/parser/AddContactParserTest.java @@ -33,6 +33,7 @@ public void setUp() { inputContactDetails = new String[NUMBER_OF_DETAILS]; } + //@@author mayankp291 @Test void parseContactDetails_inputsWithIrregularSpacing_expectCorrectDetails() throws InvalidFlagException, MissingDetailException, ForbiddenDetailException, InvalidTelegramUsernameException, @@ -44,6 +45,7 @@ void parseContactDetails_inputsWithIrregularSpacing_expectCorrectDetails() throw assertArrayEquals(expectedOutput, actualOutput); } + //@@author @Test void parseContactDetails_onlyAddInput_expectException() { inputUserInput = " add "; diff --git a/src/test/java/seedu/parser/MainParserTest.java b/src/test/java/seedu/parser/MainParserTest.java index 95d467dffd..dadc03d4fe 100644 --- a/src/test/java/seedu/parser/MainParserTest.java +++ b/src/test/java/seedu/parser/MainParserTest.java @@ -89,11 +89,12 @@ public void parseDeleteCommand_missingIndex_expectFailedCommandType() { @Test public void parseDeleteCommand_invalidNumber_expectFailedCommandType() { testUserInput = "rm abc"; - FailedCommandType expectedFailedCommandType = FailedCommandType.NUM_OUT_OF_BOUND; + FailedCommandType expectedFailedCommandType = FailedCommandType.MISSING_INDEX; final FailedCommand actualFailedCommand = getParsedCommand(testUserInput, FailedCommand.class); assertEquals(expectedFailedCommandType, actualFailedCommand.getType()); } + //@@author mayankp291 @Test public void parseDeleteCommand_outOfRangeIndex_expectException() { ContactList contactList = new ContactList(); @@ -107,10 +108,10 @@ public void parseDeleteCommand_outOfRangeIndex_expectException() { DeleteContactCommand deleteContactCommand = getParsedCommand(testUserInput, DeleteContactCommand.class); deleteContactCommand.setContactList(contactList); int deletedIndex = deleteContactCommand.getContactIndex(); - assertThrows(IndexOutOfBoundsException.class, () -> contactList.deleteContact(deletedIndex)); } + //@@author mayankp291 @Test public void parseAddCommand_validInputsWithIrregularSpaces_expectAddContactCommand() { testUserInput = " add -n andre -g ng-andre -l linkedin -tw twit -te teles123 -e andre@twix.com"; @@ -125,6 +126,7 @@ public void parseAddCommand_validInputsWithIrregularSpaces_expectAddContactComma assertEquals(expectedCommand.getEmail(), actualCommand.getEmail()); } + //@@author mayankp291 @Test public void parseAddCommand_validInputsWithExtraCharacters_expectAddContactCommand() { testUserInput = " add 1231267azldasd -n marcus -g marcus-bory "; @@ -135,6 +137,7 @@ public void parseAddCommand_validInputsWithExtraCharacters_expectAddContactComma assertEquals(expectedCommand.getGithub(), actualCommand.getGithub()); } + //@@author @Test public void parseAddCommand_validInputs_expectAddContactCommand() { testUserInput = "add -n andre -g ng-andre -l linkedin -tw twit -te teles123 -e andre@twix.com"; @@ -149,6 +152,7 @@ public void parseAddCommand_validInputs_expectAddContactCommand() { assertEquals(expectedCommand.getEmail(), actualCommand.getEmail()); } + //@@author mayankp291 @Test public void parseAddCommand_validInputsWithPartialFlags_expectAddContactCommand() { testUserInput = " add -n ashraf -g fdada-121 -tw 66123ada -e ash@yahoo.com "; @@ -225,6 +229,7 @@ public void parseAddCommand_forbiddenName_expectInvalidDetailCommand() { assertEquals(expectedFailedCommandType, actualCommand.getType()); } + //@@author mayankp291 @Test public void parseViewCommand_validIndex_expectViewContactIndexMatch() { final int testIndex = 1; @@ -233,6 +238,7 @@ public void parseViewCommand_validIndex_expectViewContactIndexMatch() { assertEquals(testIndex,testResultCommand.getIndex()); } + //@@author @Test public void parseViewCommand_multipleIndexes_expectViewContactIndexMatch() { int testIndex = 1; @@ -241,6 +247,7 @@ public void parseViewCommand_multipleIndexes_expectViewContactIndexMatch() { assertEquals(testIndex,testResultCommand.getIndex()); } + //@@author mayankp291 @Test public void parseViewCommand_invalidIndex_expectException() { testIndex = 99999; @@ -248,6 +255,7 @@ public void parseViewCommand_invalidIndex_expectException() { assertThrows(NullPointerException.class, testResultCommand::execute); } + //@@author @Test public void parseViewCommand_validIndexWithSpaces_expectViewContactIndexMatch() { testIndex = 1; @@ -264,10 +272,11 @@ public void parseViewCommand_missingIndex_expectFailedCommandType() { assertEquals(expectedFailedCommandType, actualFailedCommand.getType()); } + @Test public void parseViewCommand_invalidInput_expectFailedCommandType() { testUserInput = "view abc"; - FailedCommandType expectedFailedCommandType = FailedCommandType.NUM_OUT_OF_BOUND; + FailedCommandType expectedFailedCommandType = FailedCommandType.MISSING_INDEX; final FailedCommand actualFailedCommand = getParsedCommand(testUserInput, FailedCommand.class); assertEquals(expectedFailedCommandType, actualFailedCommand.getType()); } From 985c28e087cf6f83bac2ffae397d076f82c526a5 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 27 Oct 2021 01:56:29 +0800 Subject: [PATCH 516/756] Add JUnit test for edit --- .../java/seedu/parser/EditContactParserTest.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/test/java/seedu/parser/EditContactParserTest.java b/src/test/java/seedu/parser/EditContactParserTest.java index 1a2edd9ef9..e749982cd8 100644 --- a/src/test/java/seedu/parser/EditContactParserTest.java +++ b/src/test/java/seedu/parser/EditContactParserTest.java @@ -32,4 +32,17 @@ void parseContactDetails() throws MissingDetailException, String[] actualResult = editContactParser.parseContactDetails(testInput); assertArrayEquals(expectedResult, actualResult); } + + //@@author mayankp291 + @Test + void parseEditCommand_inputAllFields_expectOutput() throws MissingDetailException, + MissingArgEditException, InvalidFlagException, ForbiddenDetailException, InvalidTelegramUsernameException, + InvalidNameException, InvalidLinkedinUsernameException, InvalidGithubUsernameException, + InvalidTwitterUsernameException, InvalidEmailException { + String[] expectedResult = {"akshay", "topcoder", "akshay123", "akshay123", "akshay123", "akshay@gmail.com"}; + String testInput = "edit 1 -n akshay -g topcoder -l akshay123 -te akshay123 -tw akshay123 -e akshay@gmail.com"; + String[] actualResult = editContactParser.parseContactDetails(testInput); + assertArrayEquals(expectedResult, actualResult); + } + } From 2f31ecb7c76a9c927c6b4fb4dac1d81d86d684df Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 27 Oct 2021 01:57:52 +0800 Subject: [PATCH 517/756] Add JUnit test flag exception --- .../java/seedu/parser/EditContactParserTest.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/test/java/seedu/parser/EditContactParserTest.java b/src/test/java/seedu/parser/EditContactParserTest.java index e749982cd8..dfff4db414 100644 --- a/src/test/java/seedu/parser/EditContactParserTest.java +++ b/src/test/java/seedu/parser/EditContactParserTest.java @@ -45,4 +45,18 @@ void parseEditCommand_inputAllFields_expectOutput() throws MissingDetailExceptio assertArrayEquals(expectedResult, actualResult); } + //@@author mayankp291 + @Test + void parseEditCommand_invalidFlag_expectInvalidFlagException() { + String testInput = "edit 1 -name akshaygivemarksplsss"; + assertThrows(InvalidFlagException.class, () -> editContactParser.parseContactDetails(testInput)); + } + + //@@author mayankp291 + @Test + void parseEditCommand_missingFlags_expectMissingArgEditException() { + String testInput = "edit 2"; + assertThrows(MissingArgEditException.class, () -> editContactParser.parseContactDetails(testInput)); + } + } From 6d17f11ab6db98a3076eaa520aae4f8abc8dd453 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 27 Oct 2021 01:58:29 +0800 Subject: [PATCH 518/756] Add JUnit test missingDetailException --- .../java/seedu/parser/EditContactParserTest.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/test/java/seedu/parser/EditContactParserTest.java b/src/test/java/seedu/parser/EditContactParserTest.java index dfff4db414..3c1eff31dc 100644 --- a/src/test/java/seedu/parser/EditContactParserTest.java +++ b/src/test/java/seedu/parser/EditContactParserTest.java @@ -59,4 +59,18 @@ void parseEditCommand_missingFlags_expectMissingArgEditException() { assertThrows(MissingArgEditException.class, () -> editContactParser.parseContactDetails(testInput)); } + //@@author mayankp291 + @Test + void parseEditCommand_noFlags_expectMissingArgEditException() { + String testInput = "edit"; + assertThrows(MissingArgEditException.class, () -> editContactParser.parseContactDetails(testInput)); + } + + //@@author mayankp291 + @Test + void parseEditCommand_missingDescription_expectMissingDetailException() { + String testInput = "edit 1 -n"; + assertThrows(MissingDetailException.class, () -> editContactParser.parseContactDetails(testInput)); + } + } From d4545528f4ad69a65852b3cca226aefe11e8b498 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 27 Oct 2021 01:59:28 +0800 Subject: [PATCH 519/756] Add JUnit test invalidTwitterException --- .../java/seedu/parser/EditContactParserTest.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/test/java/seedu/parser/EditContactParserTest.java b/src/test/java/seedu/parser/EditContactParserTest.java index 3c1eff31dc..ac50ae175e 100644 --- a/src/test/java/seedu/parser/EditContactParserTest.java +++ b/src/test/java/seedu/parser/EditContactParserTest.java @@ -73,4 +73,18 @@ void parseEditCommand_missingDescription_expectMissingDetailException() { assertThrows(MissingDetailException.class, () -> editContactParser.parseContactDetails(testInput)); } + //@@author mayankp291 + @Test + void parseEditCommand_invalidTwitterLength_exceptInvalidTwitterUsernameException() { + String testInput = "edit 1 -tw aksha237861238129389asdas12"; + assertThrows(InvalidTwitterUsernameException.class, () -> editContactParser.parseContactDetails(testInput)); + } + + //@@author mayankp291 + @Test + void parseEditCommand_invalidTwitterCharacters_exceptInvalidTwitterUsernameException() { + String testInput = "edit 1 -tw aks-haAaa"; + assertThrows(InvalidTwitterUsernameException.class, () -> editContactParser.parseContactDetails(testInput)); + } + } From d793cfa8cf7ad6860dd66b055d1e0ffacf8db551 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 27 Oct 2021 02:00:13 +0800 Subject: [PATCH 520/756] Add JUnit test invalidTelegramException --- .../seedu/parser/EditContactParserTest.java | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/test/java/seedu/parser/EditContactParserTest.java b/src/test/java/seedu/parser/EditContactParserTest.java index ac50ae175e..5e33db9854 100644 --- a/src/test/java/seedu/parser/EditContactParserTest.java +++ b/src/test/java/seedu/parser/EditContactParserTest.java @@ -12,15 +12,13 @@ import seedu.exception.InvalidTwitterUsernameException; import seedu.exception.MissingArgEditException; import seedu.exception.MissingDetailException; -import seedu.parser.EditContactParser; - -import java.util.Arrays; import static org.junit.jupiter.api.Assertions.assertArrayEquals; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + class EditContactParserTest { - private EditContactParser editContactParser = new EditContactParser(); + private final EditContactParser editContactParser = new EditContactParser(); @Test void parseContactDetails() throws MissingDetailException, @@ -87,4 +85,18 @@ void parseEditCommand_invalidTwitterCharacters_exceptInvalidTwitterUsernameExcep assertThrows(InvalidTwitterUsernameException.class, () -> editContactParser.parseContactDetails(testInput)); } + //@@author mayankp291 + @Test + void parseEditCommand_invalidTelegramLength_exceptInvalidTelegramUsernameException() { + String testInput = "edit 1 -te absd"; + assertThrows(InvalidTelegramUsernameException.class, () -> editContactParser.parseContactDetails(testInput)); + } + + //@@author mayankp291 + @Test + void parseEditCommand_invalidTelegramCharacters_exceptInvalidTelegramUsernameException() { + String testInput = "edit 1 -te JKasn- kasd"; + assertThrows(InvalidTelegramUsernameException.class, () -> editContactParser.parseContactDetails(testInput)); + } + } From 3184904f3494d60f662b714f7fb21fbfbee774e6 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 27 Oct 2021 02:00:32 +0800 Subject: [PATCH 521/756] Add JUnit test invalidTelegramException --- .../java/seedu/parser/EditContactParserTest.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/test/java/seedu/parser/EditContactParserTest.java b/src/test/java/seedu/parser/EditContactParserTest.java index 5e33db9854..e24fad9e19 100644 --- a/src/test/java/seedu/parser/EditContactParserTest.java +++ b/src/test/java/seedu/parser/EditContactParserTest.java @@ -99,4 +99,18 @@ void parseEditCommand_invalidTelegramCharacters_exceptInvalidTelegramUsernameExc assertThrows(InvalidTelegramUsernameException.class, () -> editContactParser.parseContactDetails(testInput)); } + //@@author mayankp291 + @Test + void parseEditCommand_invalidGithubCharacters_exceptInvalidGithubUsernameException() { + String testInput = "edit 1 -g akshay@git"; + assertThrows(InvalidGithubUsernameException.class, () -> editContactParser.parseContactDetails(testInput)); + } + + //@@author mayankp291 + @Test + void parseEditCommand_invalidGithubLength_exceptInvalidGithubUsernameException() { + String testInput = "edit 1 -g akshaynarayanismazingprofbutgithubusernameistoolongsoexpectexception"; + assertThrows(InvalidGithubUsernameException.class, () -> editContactParser.parseContactDetails(testInput)); + } + } From 8d6db2a7db5a54f50bcbdf57d51031314e04c17b Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 27 Oct 2021 02:00:56 +0800 Subject: [PATCH 522/756] Add JUnit test invalidEmailException --- .../seedu/parser/EditContactParserTest.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/test/java/seedu/parser/EditContactParserTest.java b/src/test/java/seedu/parser/EditContactParserTest.java index e24fad9e19..0abde21ea7 100644 --- a/src/test/java/seedu/parser/EditContactParserTest.java +++ b/src/test/java/seedu/parser/EditContactParserTest.java @@ -113,4 +113,24 @@ void parseEditCommand_invalidGithubLength_exceptInvalidGithubUsernameException() assertThrows(InvalidGithubUsernameException.class, () -> editContactParser.parseContactDetails(testInput)); } + //@@author mayankp291 + @Test + void parseEditCommand_invalidEmail_exceptInvalidEmailException() { + String testInput = "edit 1 -e akshay@@gmail.com"; + assertThrows(InvalidEmailException.class, () -> editContactParser.parseContactDetails(testInput)); + } + + //@@author mayankp291 + @Test + void parseEditCommand_invalidEmailMissingDetails_exceptInvalidEmailException() { + String testInput = "edit 1 -e akshaygmail.com"; + assertThrows(InvalidEmailException.class, () -> editContactParser.parseContactDetails(testInput)); + } + + //@@author mayankp291 + @Test + void parseEditCommand_invalidName_exceptInvalidNameException() { + String testInput = "edit 1 -n akshaygivema123rksplsss"; + assertThrows(InvalidNameException.class, () -> editContactParser.parseContactDetails(testInput)); + } } From 93f6ef34a002690e14c6fc0137d8aa7d4cf8161b Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 27 Oct 2021 02:04:59 +0800 Subject: [PATCH 523/756] Update IO tests --- src/main/java/seedu/ui/ExceptionTextUi.java | 2 +- text-ui-test/ACTUAL.TXT | 17 ++- text-ui-test/EXPECTED-UNIX.TXT | 122 +++++++++++--------- text-ui-test/EXPECTED.TXT | 17 ++- 4 files changed, 92 insertions(+), 66 deletions(-) diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index c3d84ad7fa..7829efb2f5 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -164,7 +164,7 @@ public static void missingArgSearchMessage() { //@@author mayankp291 public static void missingIndexMessage() { String message = "There seems to be missing or invalid index in your request.\n" - + "Please enter command in the following way: \n" + + "Please enter command in the following way:\n" + " \n" + "Where is rm or view"; printDoubleLineMessage(message); diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index 81397e93db..1a3ae732c5 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -131,7 +131,10 @@ You only have 1 contact stored. ____________________________________________________________ ____________________________________________________________ -There are no contacts stored in ConTech. +There seems to be missing or invalid index in your request. +Please enter command in the following way: + +Where is rm or view ____________________________________________________________ ____________________________________________________________ @@ -228,8 +231,10 @@ NOTE : At least name and description required ____________________________________________________________ ____________________________________________________________ -The index you have input is out of range. -Please input a index between 0 and 3 +There seems to be missing or invalid index in your request. +Please enter command in the following way: + +Where is rm or view ____________________________________________________________ ____________________________________________________________ @@ -370,8 +375,10 @@ ____________________________________________________________ ____________________________________________________________ ____________________________________________________________ -The index you have input is out of range. -Please input a index between 0 and 2 +There seems to be missing or invalid index in your request. +Please enter command in the following way: + +Where is rm or view ____________________________________________________________ ____________________________________________________________ diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index ddc13873e5..1a3ae732c5 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -97,7 +97,12 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. -Please specify your command. +Please enter command in this format: + edit -n -g -e -te -l -tw + example : edit 0 -n George -g procoder -te george123 +NOTE : At least one flag and description required + Order of parameters do not matter except for INDEX + "me" is used as the INDEX for personal contact. ____________________________________________________________ ____________________________________________________________ @@ -121,12 +126,15 @@ You now have 1 contact(s). ____________________________________________________________ ____________________________________________________________ -The number you have input is out of range. +The index you have input is out of range. You only have 1 contact stored. ____________________________________________________________ ____________________________________________________________ -Please enter a valid contact index. +There seems to be missing or invalid index in your request. +Please enter command in the following way: + +Where is rm or view ____________________________________________________________ ____________________________________________________________ @@ -166,8 +174,8 @@ You now have 3 contact(s). ____________________________________________________________ ____________________________________________________________ -The number you have input is out of range. -Please input a number between 0 and 2. +The index you have input is out of range. +Please input a index between 0 and 2 ____________________________________________________________ ____________________________________________________________ @@ -206,7 +214,6 @@ ____________________________________________________________ 2. bory 3. mayank 4. ng andre - ____________________________________________________________ ____________________________________________________________ @@ -215,19 +222,19 @@ Github: github.com/ashraf ____________________________________________________________ ____________________________________________________________ -There are missing details. -Please remove any flags with no details, -and ensure that your flags used are correct: - -n NAME - -g GITHUB - -l LINKEDIN - -te TELEGRAM - -tw TWITTER - -e EMAIL +There seems to be missing parameters in your request. +Please enter command in this format: + add -n -g -e -te -l -tw + example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe +NOTE : At least name and description required + Order of parameters do not matter ____________________________________________________________ ____________________________________________________________ -Please enter a valid contact index. +There seems to be missing or invalid index in your request. +Please enter command in the following way: + +Where is rm or view ____________________________________________________________ ____________________________________________________________ @@ -239,8 +246,12 @@ You now have 6 contact(s). ____________________________________________________________ ____________________________________________________________ -There are missing details. -Please specify a name when creating a contact with the flag -n +There seems to be missing parameters in your request. +Please enter command in this format: + add -n -g -e -te -l -tw + example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe +NOTE : At least name and description required + Order of parameters do not matter ____________________________________________________________ ____________________________________________________________ @@ -254,7 +265,6 @@ ____________________________________________________________ 3. lezong 4. mayank 5. ng andre - ____________________________________________________________ ____________________________________________________________ @@ -285,15 +295,12 @@ You now have 4 contact(s). ____________________________________________________________ ____________________________________________________________ -There are missing details. -Please remove any flags with no details, -and ensure that your flags used are correct: - -n NAME - -g GITHUB - -l LINKEDIN - -te TELEGRAM - -tw TWITTER - -e EMAIL +There seems to be missing parameters in your request. +Please enter command in this format: + add -n -g -e -te -l -tw + example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe +NOTE : At least name and description required + Order of parameters do not matter ____________________________________________________________ ____________________________________________________________ @@ -365,23 +372,22 @@ ____________________________________________________________ 1. lezongmun 2. mayank 3. ng andre - ____________________________________________________________ ____________________________________________________________ -Please enter a valid contact index. +There seems to be missing or invalid index in your request. +Please enter command in the following way: + +Where is rm or view ____________________________________________________________ ____________________________________________________________ -There are missing details. -Please remove any flags with no details, -and ensure that your flags used are correct: - -n NAME - -g GITHUB - -l LINKEDIN - -te TELEGRAM - -tw TWITTER - -e EMAIL +There seems to be missing parameters in your request. +Please enter command in this format: + add -n -g -e -te -l -tw + example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe +NOTE : At least name and description required + Order of parameters do not matter ____________________________________________________________ ____________________________________________________________ @@ -435,15 +441,12 @@ Telegram: t.me/_123adad ____________________________________________________________ ____________________________________________________________ -There are missing details. -Please remove any flags with no details, -and ensure that your flags used are correct: - -n NAME - -g GITHUB - -l LINKEDIN - -te TELEGRAM - -tw TWITTER - -e EMAIL +There seems to be missing parameters in your request. +Please enter command in this format: + add -n -g -e -te -l -tw + example : add -n John Doe -g johndoecoder -e john@email.com -te johndoe +NOTE : At least name and description required + Order of parameters do not matter ____________________________________________________________ ____________________________________________________________ @@ -558,17 +561,29 @@ ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. -Please specify your command. +Please enter command in this format: + search + example : search Ashraf + search -g revflash +NOTE : Flag is optional and only one can be specified ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. -Please specify your command. +Please enter command in this format: + search + example : search Ashraf + search -g revflash +NOTE : Flag is optional and only one can be specified ____________________________________________________________ ____________________________________________________________ There seems to be missing parameters in your request. -Please specify your command. +Please enter command in this format: + search + example : search Ashraf + search -g revflash +NOTE : Flag is optional and only one can be specified ____________________________________________________________ ____________________________________________________________ @@ -610,7 +625,6 @@ ____________________________________________________________ 6. mayank 7. ng andre 8. yusdhsdsd - ____________________________________________________________ ____________________________________________________________ @@ -715,7 +729,6 @@ ____________________________________________________________ 11. mayank 12. ng andre 13. yusdhsdsd - ____________________________________________________________ ____________________________________________________________ @@ -745,7 +758,6 @@ ____________________________________________________________ 11. mayank 12. ng andre 13. yusdhsdsd - ____________________________________________________________ ____________________________________________________________ @@ -757,7 +769,7 @@ ConTech has removed all 14 of your contact(s). ____________________________________________________________ ____________________________________________________________ -You have not stored any contacts in ConTech +You do not have any stored contacts ____________________________________________________________ ____________________________________________________________ diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 81397e93db..1a3ae732c5 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -131,7 +131,10 @@ You only have 1 contact stored. ____________________________________________________________ ____________________________________________________________ -There are no contacts stored in ConTech. +There seems to be missing or invalid index in your request. +Please enter command in the following way: + +Where is rm or view ____________________________________________________________ ____________________________________________________________ @@ -228,8 +231,10 @@ NOTE : At least name and description required ____________________________________________________________ ____________________________________________________________ -The index you have input is out of range. -Please input a index between 0 and 3 +There seems to be missing or invalid index in your request. +Please enter command in the following way: + +Where is rm or view ____________________________________________________________ ____________________________________________________________ @@ -370,8 +375,10 @@ ____________________________________________________________ ____________________________________________________________ ____________________________________________________________ -The index you have input is out of range. -Please input a index between 0 and 2 +There seems to be missing or invalid index in your request. +Please enter command in the following way: + +Where is rm or view ____________________________________________________________ ____________________________________________________________ From 59b9b23b797871b0e663a87d8b986e38c2a710d4 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 27 Oct 2021 03:19:20 +0800 Subject: [PATCH 524/756] Add MainParser sequence diagram --- docs/diagrams/MainParser.puml | 25 ++++++++++++++++++++++ docs/images/MainParserSequenceDiagram.png | Bin 0 -> 16748 bytes 2 files changed, 25 insertions(+) create mode 100644 docs/diagrams/MainParser.puml create mode 100644 docs/images/MainParserSequenceDiagram.png diff --git a/docs/diagrams/MainParser.puml b/docs/diagrams/MainParser.puml new file mode 100644 index 0000000000..cfb0f75822 --- /dev/null +++ b/docs/diagrams/MainParser.puml @@ -0,0 +1,25 @@ +@startuml +hide footbox +'https://plantuml.com/sequence-diagram +->":MainParser":userInput:String +activate ":MainParser" + +":MainParser"->":MainParser":parseCommand(userInput:String) +activate ":MainParser" + +":MainParser"->":MainParser":getCommandType(userInput:String) +activate ":MainParser" +":MainParser"-->":MainParser":commandType:CommandType +deactivate ":MainParser" + +":MainParser"->":MainParser":getCommandWord(userInput:String) +activate ":MainParser" +":MainParser"-->":MainParser":commandWord:CommandWord +deactivate ":MainParser" + +ref over ":MainParser": Detailed Parsing\nbased on CommandType + +<--":MainParser"::Command +deactivate ":MainParser" +deactivate ":MainParser" +@enduml \ No newline at end of file diff --git a/docs/images/MainParserSequenceDiagram.png b/docs/images/MainParserSequenceDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..1f84ccfbd050d09b00172d8dc190897633448d59 GIT binary patch literal 16748 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 Date: Wed, 27 Oct 2021 03:19:37 +0800 Subject: [PATCH 525/756] Add AddContactCommand sequence diagram --- docs/diagrams/AddContactCommand.puml | 32 ++++++++++++++++++ .../AddContactCommandSequenceDiagram.png | Bin 0 -> 20675 bytes 2 files changed, 32 insertions(+) create mode 100644 docs/diagrams/AddContactCommand.puml create mode 100644 docs/images/AddContactCommandSequenceDiagram.png diff --git a/docs/diagrams/AddContactCommand.puml b/docs/diagrams/AddContactCommand.puml new file mode 100644 index 0000000000..82a03e015e --- /dev/null +++ b/docs/diagrams/AddContactCommand.puml @@ -0,0 +1,32 @@ +@startuml +hide footbox +'https://plantuml.com/sequence-diagram +-> ":AddContactCommand": execute() +activate ":AddContactCommand" + +create "addedContact:Contact" +":AddContactCommand" -> "addedContact:Contact":Contact() +activate "addedContact:Contact" + +"addedContact:Contact" --> ":AddContactCommand" +deactivate "addedContact:Contact" + +alt#gold #lightgreen hasDuplicates(addedContact:Contact, contactList:ContactList) + ":AddContactCommand" -> ":TextUi":ignoreContact("add") + activate ":TextUi" + ":TextUi" --> ":AddContactCommand" + deactivate ":TextUi" + +else #lightblue else + ":AddContactCommand" -> ":ContactList":addContact(addedContact:Contact) + activate ":ContactList" + ":ContactList" --> ":AddContactCommand" + deactivate ":ContactList" + + ":AddContactCommand" -> ":TextUi":addContactMessage(addedContact:Contact, contactList.getSize():int) + activate ":TextUi" + ":TextUi" --> ":AddContactCommand" + deactivate ":TextUi" +end + +@enduml diff --git a/docs/images/AddContactCommandSequenceDiagram.png b/docs/images/AddContactCommandSequenceDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..dfef50b80b15f76d09100317f255e08f09fcb6e0 GIT binary patch literal 20675 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 E0JG&kcmMzZ literal 0 HcmV?d00001 From 739ce49515eb2a3bd1ecfd649005a417d37dfd28 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 27 Oct 2021 03:19:51 +0800 Subject: [PATCH 526/756] Add AddContact parsing sequence diagram --- docs/diagrams/AddContactParsing.puml | 16 ++++++++++++++++ .../images/AddContactParsingSequenceDiagram.png | Bin 0 -> 14612 bytes 2 files changed, 16 insertions(+) create mode 100644 docs/diagrams/AddContactParsing.puml create mode 100644 docs/images/AddContactParsingSequenceDiagram.png diff --git a/docs/diagrams/AddContactParsing.puml b/docs/diagrams/AddContactParsing.puml new file mode 100644 index 0000000000..cf1e94f55d --- /dev/null +++ b/docs/diagrams/AddContactParsing.puml @@ -0,0 +1,16 @@ +@startuml +hide footbox +'https://plantuml.com/sequence-diagram +mainframe sd Detailed Add Contact Parsing +->":AddContactParser":parseContactDetails(\n\tuserInput:String\n) +activate ":AddContactParser" +loop until all fields are parsed +":AddContactParser"->":AddContactParser":parseDetail(\n\tcontactDetails:String[],\n\tdestructuredInputs:String[]\n) +activate ":AddContactParser" +":AddContactParser"-->":AddContactParser" +deactivate ":AddContactParser" +end + +<--":AddContactParser":contactDetails:String[] +deactivate ":AddContactParser" +@enduml \ No newline at end of file diff --git a/docs/images/AddContactParsingSequenceDiagram.png b/docs/images/AddContactParsingSequenceDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..601f69014087f6047f207db7ce9efdbf69480058 GIT binary patch literal 14612 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 BR4D)e literal 0 HcmV?d00001 From ec9cb34459096e5099842df653de6997395f95ac Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 27 Oct 2021 03:20:04 +0800 Subject: [PATCH 527/756] Fix minor grammatical error in user guide --- docs/UserGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 7cf246493e..dfd1bf7594 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -73,7 +73,7 @@ Adds a specified contact to the ConTech Book. Usage: `add -n NAME -g GITHUB -l LINKEDIN -te TELEGRAM -tw TWITTER -e EMAIL` - ConTech is robust and allows you to specify your fields in any order. -- The `-n` name field is the only compulsory field required to add a contact, the rest are optional. +- The `-n` name field is the only compulsory field required to add a contact. The rest are optional. - Up to five other `FLAGS` and `DETAILS` can be specified - ConTech also has built-in duplicate checkers, in case you accidentally add the same contact twice. From 07c30d6fe63351120c6de2f5bf5a3befa51d681d Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 27 Oct 2021 03:20:30 +0800 Subject: [PATCH 528/756] Add implementation hyperlinks to table of contents in DG --- docs/DeveloperGuide.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index b20bd13b55..93265d24ad 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -10,6 +10,13 @@ - [ContactList](#contact-list) - [Storage](#storage) - [Implementation](#implementation) + - [Supported contact details](#supported-details) + - [Adding a contact](#Add) + - [Viewing a contact](#View) + - [Editing a contact](#Edit) + - [Deleting a contact](#Delete) + - [Searching a contact](#Search) + - [Listing all contacts](#List) - [Product Scope](#scope) - [Target user profile](#target) - [Value proposition](#value) From fb5ee649c901f6adaadee9dfdaf8c11dfdbc2024 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 27 Oct 2021 03:20:58 +0800 Subject: [PATCH 529/756] Fix minor UI inconsistency --- docs/DeveloperGuide.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 93265d24ad..482be1c243 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -29,7 +29,7 @@ - Inspiration for App Idea and OOP Structure: AddressBook (Level 2)
    https://github.com/se-edu/addressbook-level2 -- Inspiration for User Guide and Developer Guide: AddressBook (Level 2)
    +- Inspiration for User Guide and Developer Guide: AddressBook (Level 3)
    https://se-education.org/addressbook-level3/DeveloperGuide.html
    https://se-education.org/addressbook-level3/UserGuide.html - Converting text for ConTech:
    @@ -62,7 +62,7 @@ ConTech comprises five main components, namely: **How the architecture components interact with each other** The five main components interact with each other, as shown in the sequence diagram below -for the example "view 2" +for the example: `view 2` ![Sysem Architecture Sequence Diagram](images/SystemArchitectureSequence.png) From 40d028fe686b00208eec59d04a4eba3e4b4a7de8 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 27 Oct 2021 03:21:15 +0800 Subject: [PATCH 530/756] Add MainParser description and sequence diagram --- docs/DeveloperGuide.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 482be1c243..8bf403e5a5 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -69,6 +69,16 @@ for the example: `view 2` ### TextUi ### MainParser +The `MainParser` component is responsible for making sense of the user's inputs. It functions as the +not only the identifier for commands, but also calls its relevant sub-parsers to further destructure +the inputs, allowing ConTech to perform its commands. + +The diagram below shows a sequence diagram of how `MainParser` works, and a reference diagram is used +to indicate that further parsing is done by sub-parsers for each different command type. This reference diagram +will be referred to later on. + +![Main Parser Sequence Diagram](images/MainParserSequenceDiagram.png) + ### Command ### ContactList ### Storage From 8e8e4bcb5535bc0a1a5172c042a0404c8545187e Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 27 Oct 2021 03:21:40 +0800 Subject: [PATCH 531/756] Add currently supported flags and details into a table --- docs/DeveloperGuide.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 8bf403e5a5..6bc3bdf002 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -94,9 +94,18 @@ corresponding `ContactList` and `Contact` objects. It is thus dependent on the c ## Implementation -{Describe the design and implementation of the product. Use UML diagrams and short code snippets where applicable.} +### Supported Contact Details +The currently supported contact details are provided in the table below: + +|Flag|Detail of contact| +|----|------| +|`-n`|Name| +|`-g`|Github username| +|`-l`|LinkedIn handle| +|`-te`|Telegram handle| +|`-tw`|Twitter handle| +|`-e`|Email| -{NOT DONE} ### Viewing a contact: `view` This feature is processed using `ViewContactCommand`. Whenever a user wants to view a specific contact from the From e3e2940d89b7947c785f8c41cf79d4d4d360e79d Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 27 Oct 2021 03:22:04 +0800 Subject: [PATCH 532/756] Change 'list' command to 'ls' as per application --- docs/DeveloperGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 6bc3bdf002..a2a917d128 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -145,7 +145,7 @@ will be created and executed in `Duke`. The sequence diagram below shows how the ![Search Sequence Diagram](images/SearchContactCommandSequenceDiagram.png) -### Listing all contacts: `list` +### Listing all contacts: `ls` This feature is processed using `MainParser`. The control is sent to `ListContactsCommand` under `Command` to execute the command which uses a loop to get the Contact object at every available index and print it using the `printContactWithIndex` function in `TextUi` class. From 5913c82e80bc9867ed40fb8a842ad9701312452b Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 27 Oct 2021 03:22:20 +0800 Subject: [PATCH 533/756] Correct 'edit' to 'search' for search feature in DG --- docs/DeveloperGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index a2a917d128..633ac8eee0 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -135,7 +135,7 @@ diagram below shows how the `execute()` function of `DeleteContactCommand` works ![Delete Sequence Diagram](images/DeleteContactCommandSequenceDiagram.png) -### Searching a contact: `edit` +### Searching a contact: `search` This feature is processed using `SearchContactParser` under `MainParser`. In order to edit a contact in the contact list, a user must enter a command in the form `search [FLAG] [SEARCH QUERY]`. If no flag is specified, the search will be done on contact names buy default. From the user input, the search query and the search flag are obtained from the From 2225e7e6ba7b46850e7d0b887983e63c9cd3992c Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 27 Oct 2021 03:22:56 +0800 Subject: [PATCH 534/756] Add minor UI update to Edt in DG --- docs/DeveloperGuide.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 633ac8eee0..b6b2090606 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -117,11 +117,11 @@ The sequence diagram below illustrates the `execute()` function in `ViewContactC ### Editing a contact: `edit` This feature is processed using `EditContactParser` under `MainParser`. In order to edit a contact in the contact list, -a user must enter a command in the form `edit [CONTACT INDEX] [DETAILS WITH FLAGS]` where the details with flags are -specified in the form `-flag detail` with up to 6 details i.e. `-g github-username -tw twitter_handle`. The user input -will be parsed by `EditContactParser` methods `getIndexToStore` and `parseContactDetails` to obtain a String array with -the details to be edited. An `EditContactCommand` with the specified parameters will then be created and executed in -`Duke`. The sequence diagram below shows how the whole process is carried out. +a user must enter a command in the form `edit [CONTACT INDEX] [DETAILS WITH FLAGS]`, where the details with flags are +specified in the form `- ` with up to 6 details i.e. `-g github-username -tw twitter_handle`. The user +input will be parsed by `EditContactParser` methods `getIndexToStore` and `parseContactDetails` to obtain a String +array with the details to be edited. An `EditContactCommand` with the specified parameters will then be created and +executed in `Duke`. The sequence diagram below shows how the whole process is carried out. ![Edit Sequence Diagram](images/EditContactCommandSequenceDiagram.png) From cb1fb89ad9dfb3c9abfc833480d3391625b28aab Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 27 Oct 2021 03:23:07 +0800 Subject: [PATCH 535/756] Add mass load user story to DG --- docs/DeveloperGuide.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index b6b2090606..7d19c6e611 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -179,6 +179,7 @@ additional devices or platforms. |v1.0|programmer|be able to copy and paste the displayed contact's URLs|visit the contact's accounts| |v2.0|programmer|save my personal details|the application is aware of the user| |v2.0|forgetful user|be able to search for my contacts by name|find their contact details| +|v2.0|programmer|import a list of contacts quickly from an input txt file|save time typing each contact ## Non-Functional Requirements From 5063c1e757a3df9ce7b08a0d940213e540b2171c Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 27 Oct 2021 03:23:23 +0800 Subject: [PATCH 536/756] Add add contact implementation in DG --- docs/DeveloperGuide.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 7d19c6e611..7a4bb990b5 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -106,6 +106,24 @@ The currently supported contact details are provided in the table below: |`-tw`|Twitter handle| |`-e`|Email| +### Adding a contact: `add` +This feature is processed using `AddContactCommand`. This feature allows a user to add a contact to their contact list. +The user is able to add a contact by entering a command in the form of `add [DETAILS WITH FLAGS]`, where +the details with flags are specified in the form `- `. + +The user's input is parsed in `MainParser` and `AddContactParser`, the latter which inherits `ContactParser`. +`ContactParser` inherits `RegexParser` (for regex checks regarding each detail) and implements the `ContactDetails` +interface (which uniquely allows the parsers to easily identify each detail based on their indexes). + +As the contacts are identified by their names, the name field is made compulsory at the `MainParser` level. +The diagram below shows the process of parsing the user's input. + +![Add Contact Parsing](images/AddContactParsingSequenceDiagram.png) + +Upon parsing the user's input, the details are passed to an `AddContactCommand`, and this command will be +executed in `Duke`. The sequence diagram below illustrates the process of executing `AddContactCommand`. + +![Add Sequence Diagram](images/AddContactCommandSequenceDiagram.png) ### Viewing a contact: `view` This feature is processed using `ViewContactCommand`. Whenever a user wants to view a specific contact from the From 4069e03f9e88a2802a2cbb6dab077fbe1b0d62cd Mon Sep 17 00:00:00 2001 From: lezong Date: Wed, 27 Oct 2021 03:24:36 +0800 Subject: [PATCH 537/756] Abstract DeveloperGuide --- docs/DeveloperGuide.md | 4 ++ docs/diagrams/DeleteAllContacts.puml | 49 +++++++++++++++ docs/diagrams/DeleteContactCommand.puml | 50 ++------------- docs/diagrams/DeleteSelectedContact.puml | 59 ++++++++++++++++++ docs/images/DeleteAllContacts.png | Bin 0 -> 30265 bytes .../DeleteContactCommandSequenceDiagram.png | Bin 41809 -> 9347 bytes docs/images/DeleteSelectedContact.png | Bin 0 -> 42011 bytes 7 files changed, 117 insertions(+), 45 deletions(-) create mode 100644 docs/diagrams/DeleteAllContacts.puml create mode 100644 docs/diagrams/DeleteSelectedContact.puml create mode 100644 docs/images/DeleteAllContacts.png create mode 100644 docs/images/DeleteSelectedContact.png diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index b20bd13b55..00c9c6945c 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -108,6 +108,10 @@ diagram below shows how the `execute()` function of `DeleteContactCommand` works ![Delete Sequence Diagram](images/DeleteContactCommandSequenceDiagram.png) +![Delete All Sequence Diagram](images/DeleteAllContacts.png) + +![Delete Selected Sequence Diagram](images/DeleteSelectedContact.png) + ### Searching a contact: `edit` This feature is processed using `SearchContactParser` under `MainParser`. In order to edit a contact in the contact list, diff --git a/docs/diagrams/DeleteAllContacts.puml b/docs/diagrams/DeleteAllContacts.puml new file mode 100644 index 0000000000..bf5340fd0b --- /dev/null +++ b/docs/diagrams/DeleteAllContacts.puml @@ -0,0 +1,49 @@ +@startuml +hide footbox +mainframe sd delete all contacts + +":DeleteContactCommand" -> ":DeleteContactCommand" : deleteAllContacts() +activate ":DeleteContactCommand" + +'confirm delete message +":DeleteContactCommand" -> ":TextUi" :confirmDeleteAllMessage() +activate ":TextUi" +":TextUi" --> ":DeleteContactCommand" +deactivate ":TextUi" + +'get confirmation from user to delete +":DeleteContactCommand" -> ":UserInputTextUi" :getUserConfirmation() +activate ":UserInputTextUi" +":UserInputTextUi" --> ":DeleteContactCommand" : userConfirmation: String +deactivate ":UserInputTextUi" + +alt#gold #lightgreen delete confirmed + 'get size of list for delete message + ":DeleteContactCommand" -> ":ContactList": getListSize() + activate ":ContactList" + ":ContactList" --> ":DeleteContactCommand": contactListSize: int + deactivate ":ContactList" + + 'execute delete for all contacts + ":DeleteContactCommand" -> ":ContactList":deleteAllContacts() + activate ":ContactList" + ":ContactList" --> ":DeleteContactCommand" + deactivate ":ContactList" + + 'Print message to show delete executed + ":DeleteContactCommand" -> ":TextUi": deleteAllContactsMessage(contactListSize: int) + activate ":TextUi" + ":TextUi" --> ":DeleteContactCommand" + deactivate ":TextUi" + +else #lightblue delete cancelled + 'Print message to show delete cancelled + ":DeleteContactCommand" -> ":TextUi":cancelDeleteContactMessage() + activate ":TextUi" + ":TextUi" --> ":DeleteContactCommand" + deactivate ":TextUi" +end + +deactivate ":DeleteContactCommand" + +@enduml \ No newline at end of file diff --git a/docs/diagrams/DeleteContactCommand.puml b/docs/diagrams/DeleteContactCommand.puml index a2c00a9d1c..02dce84bfc 100644 --- a/docs/diagrams/DeleteContactCommand.puml +++ b/docs/diagrams/DeleteContactCommand.puml @@ -3,53 +3,13 @@ hide footbox 'https://plantuml.com/sequence-diagram -> ":DeleteContactCommand": execute() activate ":DeleteContactCommand" +alt#gold #lightgreen delete all contacts + ref over ":DeleteContactCommand", ":DeleteContactCommand" :delete all contacts -":DeleteContactCommand" -> ":IndexParser" :getContactFromIndex(contactIndex:int, contactList: ContactList) -activate ":IndexParser" -":IndexParser" --> ":DeleteContactCommand" :deletedContact:Contact -deactivate ":IndexParser" - -":DeleteContactCommand" -> ":DeleteContactCommand":deleteOnConfirmation(deletedContact:Contact) -activate ":DeleteContactCommand" -":DeleteContactCommand" -> ":TextUi":ConfirmDeleteMessage(deletedContact:Contact, contactIndex:int) -activate ":TextUi" -":TextUi" --> ":DeleteContactCommand" -deactivate ":TextUi" - -":DeleteContactCommand" -> ":UserInputTextUi":getUserConfirmation() -activate ":UserInputTextUi" -":UserInputTextUi" --> ":DeleteContactCommand" :userConfirmation:String -deactivate ":UserInputTextUi" - -alt#gold #lightgreen userConfirmation.equalsIgnoreCase("y") - ":DeleteContactCommand" -> ":ContactList": deleteContact(contactIndex:int) - activate ":ContactList" - ":ContactList" --> ":DeleteContactCommand" - deactivate ":ContactList" - ":DeleteContactCommand" -> ":Contact" :getName() - activate ":Contact" - ":Contact" --> ":DeleteContactCommand":deletedName:String - deactivate ":Contact" - - ":DeleteContactCommand" -> ":ContactList":getListSize() - activate ":ContactList" - ":ContactList" --> ":DeleteContactCommand" :contactListSize:int - deactivate ":ContactList" - - ":DeleteContactCommand" -> ":TextUi":deleteContactMessage(deletedName:String, contactListSize:int) - activate ":TextUi" - ":TextUi" --> ":DeleteContactCommand" - deactivate ":TextUi" - - -else #lightblue else - ":DeleteContactCommand" -> ":TextUi":cancelDeleteContactMessage() - activate ":TextUi" - ":TextUi" --> ":DeleteContactCommand" - deactivate ":TextUi" - +else #lightblue delete selected contact + ref over ":DeleteContactCommand", ":DeleteContactCommand" :delete selected contact end -deactivate ":DeleteContactCommand" + deactivate ":DeleteContactCommand" @enduml \ No newline at end of file diff --git a/docs/diagrams/DeleteSelectedContact.puml b/docs/diagrams/DeleteSelectedContact.puml new file mode 100644 index 0000000000..636e112e5b --- /dev/null +++ b/docs/diagrams/DeleteSelectedContact.puml @@ -0,0 +1,59 @@ +@startuml +hide footbox +mainframe sd delete selected contact +":DeleteContactCommand" -> ":DeleteContactCommand":deleteOnConfirmation(deletedContact:Contact) +activate ":DeleteContactCommand" + +'obtain contact to be deleted using index +":DeleteContactCommand" -> ":IndexParser": getContactFromIndex(contactIndex: int, contactList: ContactList) +activate ":IndexParser" +":IndexParser" --> ":DeleteContactCommand": deletedContact:Contact +deactivate ":IndexParser" + +'confirm delete message +":DeleteContactCommand" -> ":TextUi" :confirmDeleteContactMessage(deletedContact: Contact, contactIndex: int) +activate ":TextUi" +":TextUi" --> ":DeleteContactCommand" +deactivate ":TextUi" + +'get confirmation from user to delete +":DeleteContactCommand" -> ":UserInputTextUi":getUserConfirmation() +activate ":UserInputTextUi" +":UserInputTextUi" --> ":DeleteContactCommand" :userConfirmation:String +deactivate ":UserInputTextUi" + +alt#gold #lightgreen delete confirmed + 'execute delete for selected contact + ":DeleteContactCommand" -> ":ContactList":deleteContact(contactIndex: int) + activate ":ContactList" + ":ContactList" --> ":DeleteContactCommand" + deactivate ":ContactList" + + 'get name of deleted contact + ":DeleteContactCommand" -> ":Contact" :getName() + activate ":Contact" + ":Contact" --> ":DeleteContactCommand":deletedName: String + deactivate ":Contact" + + 'get size of list for delete message + ":DeleteContactCommand" -> ":ContactList": getListSize() + activate ":ContactList" + ":ContactList" --> ":DeleteContactCommand": contactListSize: int + deactivate ":ContactList" + + 'Print message to show delete executed + ":DeleteContactCommand" -> ":TextUi": deleteContactMessage(deletedName: String, contactListSize: int) + activate ":TextUi" + ":TextUi" --> ":DeleteContactCommand" + deactivate ":TextUi" + +else #lightblue delete cancelled + 'Print message to show delete cancelled + ":DeleteContactCommand" -> ":TextUi":cancelDeleteContactMessage() + activate ":TextUi" + ":TextUi" --> ":DeleteContactCommand" + deactivate ":TextUi" +end + +deactivate ":DeleteContactCommand" +@enduml \ No newline at end of file diff --git a/docs/images/DeleteAllContacts.png b/docs/images/DeleteAllContacts.png new file mode 100644 index 0000000000000000000000000000000000000000..f90702878a2e1cc6fd386ad8a1e60593ec6fdbd6 GIT binary patch literal 30265 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 literal 41809 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'cB>a+%Ea$g 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°BKhx6_K=5Sl(dT~;{p#y1g{h{` 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 utU!RQ#fF{K-d?WrlMyWc<9aPpc2Q8cJ%=Dx Date: Wed, 27 Oct 2021 03:34:47 +0800 Subject: [PATCH 538/756] formatting --- docs/DeveloperGuide.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 00c9c6945c..df7509bbac 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -101,9 +101,10 @@ the details to be edited. An `EditContactCommand` with the specified parameters ### Deleting a contact: `rm` -This feature is processed using the `DeleteContactCommand`. Whenever the user wants to remove a contact from the contact -list using the `rm` command, `DeleteContactCommand` is created in the `MainParser` and executed in`Duke`. The sequence -diagram below shows how the `execute()` function of `DeleteContactCommand` works. +This feature is processed using the `DeleteContactCommand`. Whenever the user wants to remove a +from the contact list using the `rm` command, `DeleteContactCommand` is created in the `MainParser` +and executed in`Duke`. The sequence diagram below shows how the `execute()` function of +`DeleteContactCommand` works. ![Delete Sequence Diagram](images/DeleteContactCommandSequenceDiagram.png) From 5e0ac4e67f98eaedbf43a07c150b547bdb070af9 Mon Sep 17 00:00:00 2001 From: lezong Date: Wed, 27 Oct 2021 03:49:59 +0800 Subject: [PATCH 539/756] Edits to rm feature in DG --- docs/DeveloperGuide.md | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 85ff0fea8b..5fa59e8452 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -144,17 +144,27 @@ executed in `Duke`. The sequence diagram below shows how the whole process is ca ![Edit Sequence Diagram](images/EditContactCommandSequenceDiagram.png) -### Deleting a contact: `rm` -This feature is processed using the `DeleteContactCommand`. Whenever the user wants to remove a -from the contact list using the `rm` command, `DeleteContactCommand` is created in the `MainParser` -and executed in`Duke`. The sequence diagram below shows how the `execute()` function of -`DeleteContactCommand` works. - +### Deleting contacts: `rm` +This feature is processed using the `DeleteContactCommand`. `DeleteContactCommand` is created +in the `MainParser`and executed in`Duke`. Users can either delete a specified contact +or delete all contacts at once. ![Delete Sequence Diagram](images/DeleteContactCommandSequenceDiagram.png) +To delete all contacts, a user must enter the command `rm all`. The sequence diagram below +shows how the removal of all contacts works. Before any deletion, the user will be +prompted with a message to confirm deletion. If the user confirms deletion for all contacts, +deletion will be executed, along with a message to show that deletion has been executed. +If user cancels deletion, a message is printed to show that the deletion has been cancelled. + ![Delete All Sequence Diagram](images/DeleteAllContacts.png) +To delete a selected contact, a user must enter a command in the form `rm [INDEX]`. The sequence diagram below +shows how the removal of a contact works. Before any deletion, details of the contact with the specified`INDEX` +will be displayed to the user, along with a prompt to confirm deletion. If the user confirms deletion, +deletion of the selected contact will be executed, along with a message to show that deletion has been executed. +If user cancels deletion, a message is printed to show that the deletion has been cancelled. + ![Delete Selected Sequence Diagram](images/DeleteSelectedContact.png) From 4f011638c6d23712a8171081d560a4e9d64a61af Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 27 Oct 2021 12:58:29 +0800 Subject: [PATCH 540/756] Update comparator to account for different case --- src/main/java/seedu/contact/ContactComparator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/contact/ContactComparator.java b/src/main/java/seedu/contact/ContactComparator.java index 649966cc65..a9d0a3f29c 100644 --- a/src/main/java/seedu/contact/ContactComparator.java +++ b/src/main/java/seedu/contact/ContactComparator.java @@ -6,6 +6,6 @@ public class ContactComparator implements Comparator { public int compare(Contact contact1, Contact contact2) { - return contact1.getName().compareTo(contact2.getName()); + return contact1.getName().toLowerCase().compareTo(contact2.getName().toLowerCase()); } } From abe51bebbc6d14bd59fb5b23d3814aeedc250549 Mon Sep 17 00:00:00 2001 From: Mayank Panjiyara <69447074+mayankp291@users.noreply.github.com> Date: Wed, 27 Oct 2021 19:55:20 +0800 Subject: [PATCH 541/756] Update name regex to only allow one space between words --- src/main/java/seedu/parser/RegexParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/RegexParser.java b/src/main/java/seedu/parser/RegexParser.java index d4ecf8d1c4..9ac3bed423 100644 --- a/src/main/java/seedu/parser/RegexParser.java +++ b/src/main/java/seedu/parser/RegexParser.java @@ -104,7 +104,7 @@ protected void checkGithubUsernameRegex(String detailToParse) throws InvalidGith protected void checkNameRegex(String detailToParse) throws InvalidNameException { //only letters and spaces allowed - String nameRegex = "^[ A-Za-z]+$"; + String nameRegex = "^([a-zA-Z]+\\s)*[a-zA-Z]+$"; if (!detailToParse.matches(nameRegex)) { LOGGER.log(Level.FINE, "Regex check for name failed"); throw new InvalidNameException(); From e39b6c39398f968afda2f62f978180f8618b91a3 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 27 Oct 2021 22:54:53 +0800 Subject: [PATCH 542/756] Add author tags --- src/main/java/seedu/command/AddContactCommand.java | 1 + src/main/java/seedu/command/Command.java | 1 + src/main/java/seedu/command/FailedCommand.java | 1 + src/main/java/seedu/command/ImportContactCommand.java | 1 + src/main/java/seedu/contact/Contact.java | 2 ++ src/main/java/seedu/contact/ContactList.java | 2 ++ src/main/java/seedu/contact/DetailType.java | 1 + src/main/java/seedu/duke/Duke.java | 1 + src/main/java/seedu/parser/AddContactParser.java | 1 + src/main/java/seedu/parser/ContactDetails.java | 1 + src/main/java/seedu/parser/ContactParser.java | 1 + src/main/java/seedu/parser/MainParser.java | 1 + src/main/java/seedu/storage/ContactsDecoder.java | 3 ++- src/main/java/seedu/storage/ContactsEncoder.java | 2 +- src/main/java/seedu/storage/Storage.java | 3 ++- 15 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/command/AddContactCommand.java b/src/main/java/seedu/command/AddContactCommand.java index 74eaba46c7..c76b440c6c 100644 --- a/src/main/java/seedu/command/AddContactCommand.java +++ b/src/main/java/seedu/command/AddContactCommand.java @@ -1,3 +1,4 @@ +//@@author marcusbory package seedu.command; import seedu.contact.Contact; diff --git a/src/main/java/seedu/command/Command.java b/src/main/java/seedu/command/Command.java index 185e6191ce..a71cb8f594 100644 --- a/src/main/java/seedu/command/Command.java +++ b/src/main/java/seedu/command/Command.java @@ -3,6 +3,7 @@ import seedu.contact.Contact; import seedu.contact.ContactList; +//@@author marcusbory public abstract class Command { protected ContactList contactList; protected Contact personalContact; diff --git a/src/main/java/seedu/command/FailedCommand.java b/src/main/java/seedu/command/FailedCommand.java index bf8b80e3e2..038b11d137 100644 --- a/src/main/java/seedu/command/FailedCommand.java +++ b/src/main/java/seedu/command/FailedCommand.java @@ -1,3 +1,4 @@ +//@@author marcusbory package seedu.command; import seedu.parser.FailedCommandType; diff --git a/src/main/java/seedu/command/ImportContactCommand.java b/src/main/java/seedu/command/ImportContactCommand.java index 0ce4a5dc8b..dfab9beb78 100644 --- a/src/main/java/seedu/command/ImportContactCommand.java +++ b/src/main/java/seedu/command/ImportContactCommand.java @@ -1,3 +1,4 @@ +//@@author marcusbory package seedu.command; import seedu.contact.ContactList; diff --git a/src/main/java/seedu/contact/Contact.java b/src/main/java/seedu/contact/Contact.java index 7403356249..d14299768b 100644 --- a/src/main/java/seedu/contact/Contact.java +++ b/src/main/java/seedu/contact/Contact.java @@ -50,6 +50,7 @@ public void editContact(String[] contactDetails) { //control should never reach here assert false; } + //@@author marcusbory } } } @@ -101,6 +102,7 @@ public String getTelegram() { public void setTelegram(String telegram) { this.telegram = telegram; } + //@@author //@@author ng-andre public String[] getContactStringArray() { diff --git a/src/main/java/seedu/contact/ContactList.java b/src/main/java/seedu/contact/ContactList.java index cf286933aa..05770a34b9 100644 --- a/src/main/java/seedu/contact/ContactList.java +++ b/src/main/java/seedu/contact/ContactList.java @@ -1,3 +1,4 @@ +//@@author marcusbory package seedu.contact; import seedu.exception.InvalidFlagException; @@ -60,6 +61,7 @@ public int getIndexOfContact(Contact contact) { } public Contact getContactAtIndex(int index) { + //@@author marcusbory sortContacts(); return contacts.get(index); } diff --git a/src/main/java/seedu/contact/DetailType.java b/src/main/java/seedu/contact/DetailType.java index 4da0277c55..65be6b5bf2 100644 --- a/src/main/java/seedu/contact/DetailType.java +++ b/src/main/java/seedu/contact/DetailType.java @@ -1,3 +1,4 @@ +//@@author marcusbory package seedu.contact; /** diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index ad96c926e8..dec65a116c 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -1,3 +1,4 @@ +//@@author marcusbory package seedu.duke; import seedu.command.Command; diff --git a/src/main/java/seedu/parser/AddContactParser.java b/src/main/java/seedu/parser/AddContactParser.java index 4a652cf78f..b5008636f6 100644 --- a/src/main/java/seedu/parser/AddContactParser.java +++ b/src/main/java/seedu/parser/AddContactParser.java @@ -1,3 +1,4 @@ +//@@author marcusbory package seedu.parser; import seedu.exception.ForbiddenDetailException; diff --git a/src/main/java/seedu/parser/ContactDetails.java b/src/main/java/seedu/parser/ContactDetails.java index bcb5f52c43..7d9e5c4be6 100644 --- a/src/main/java/seedu/parser/ContactDetails.java +++ b/src/main/java/seedu/parser/ContactDetails.java @@ -1,3 +1,4 @@ +//@@author marcusbory package seedu.parser; import seedu.contact.DetailType; diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index bcc9c91c84..4a5b360b66 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -1,3 +1,4 @@ +//@@author marcusbory package seedu.parser; import seedu.exception.ForbiddenDetailException; diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 7a3ac10d4b..409e292d2b 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -163,6 +163,7 @@ private Command parseQueryCommand(String commandWord, String userInput) { return command; } + //@@author marcusbory private Command parseAddContact(String userInput) { contactParser = addContactParser; try { diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index 276891dbb6..ed0a8597b3 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -1,3 +1,4 @@ +//@@author marcusbory package seedu.storage; import seedu.contact.Contact; @@ -86,7 +87,7 @@ private Contact decodePersonalContact(String contactText, Contact contact) { return personalContact; } - //@@author + //@@author marcusbory private void decodeContact(ContactList contactList, String contactText, int lineIndex, String contactFilePath) { // Add the decoded details into the contact list try { diff --git a/src/main/java/seedu/storage/ContactsEncoder.java b/src/main/java/seedu/storage/ContactsEncoder.java index 4834e45ab8..b166aa25f9 100644 --- a/src/main/java/seedu/storage/ContactsEncoder.java +++ b/src/main/java/seedu/storage/ContactsEncoder.java @@ -22,7 +22,7 @@ public void savePersonalContact(String contactFilePath, Contact personalContact) } } - //@@author + //@@author marcusbory public void saveContacts(String contactFilePath, ContactList contactList) throws FileErrorException { try { FileWriter fileWriter = new FileWriter(contactFilePath); diff --git a/src/main/java/seedu/storage/Storage.java b/src/main/java/seedu/storage/Storage.java index 2fa65b360e..dcdf01606a 100644 --- a/src/main/java/seedu/storage/Storage.java +++ b/src/main/java/seedu/storage/Storage.java @@ -1,3 +1,4 @@ +//@@author marcusbory package seedu.storage; import seedu.contact.Contact; @@ -49,7 +50,7 @@ private boolean hasEmptyExistingPersonalContactFile() { return personalContactFile.exists() && personalContactFile.length() == 0; } - //@@author + //@@author marcusbory private boolean hasExistingContactFile() throws FileErrorException { try { if (!contactFile.exists()) { From 6237cf296c71b15033993a44553ad0bdf66b6959 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 27 Oct 2021 22:56:06 +0800 Subject: [PATCH 543/756] Refactor AddContactCommand and EditContactCommand duplicate checks to use getContactStringArray() --- .../java/seedu/command/AddContactCommand.java | 42 ++--------------- .../seedu/command/EditContactCommand.java | 47 ++----------------- 2 files changed, 6 insertions(+), 83 deletions(-) diff --git a/src/main/java/seedu/command/AddContactCommand.java b/src/main/java/seedu/command/AddContactCommand.java index c76b440c6c..1ee627466f 100644 --- a/src/main/java/seedu/command/AddContactCommand.java +++ b/src/main/java/seedu/command/AddContactCommand.java @@ -10,6 +10,7 @@ import seedu.ui.UserInputTextUi; import java.util.ArrayList; +import static seedu.parser.ContactParser.NUMBER_OF_FIELDS; public class AddContactCommand extends Command { private final String name; @@ -18,13 +19,6 @@ public class AddContactCommand extends Command { private final String telegram; private final String twitter; private final String email; - public static final int NUMBER_OF_FIELDS = 6; - public static final int NAME_INDEX = 0; - public static final int GITHUB_INDEX = 1; - public static final int LINKEDIN_INDEX = 2; - public static final int TELEGRAM_INDEX = 3; - public static final int TWITTER_INDEX = 4; - public static final int EMAIL_INDEX = 5; public String getLinkedin() { return linkedin; @@ -76,9 +70,9 @@ public void execute() { //@@author ashrafjfr private boolean hasDuplicates(Contact addedContact, ContactList contactList) throws InvalidFlagException { ArrayList duplicatedIndex = new ArrayList<>(); - String[] addedContactDetails = extractContactDetails(addedContact); + String[] addedContactDetails = addedContact.getContactStringArray(); for (int i = 0; i < contactList.getListSize(); i++) { - String[] currentContactDetails = extractContactDetails(contactList.getContactAtIndex(i)); + String[] currentContactDetails = contactList.getContactAtIndex(i).getContactStringArray(); for (int j = 0; j < NUMBER_OF_FIELDS; j++) { if (addedContactDetails[j] != null && currentContactDetails[j] != null) { if (hasDuplicateField(addedContactDetails[j], currentContactDetails[j])) { @@ -96,36 +90,6 @@ private boolean hasDuplicates(Contact addedContact, ContactList contactList) thr return false; } - private String[] extractContactDetails(Contact contact) throws InvalidFlagException { - String[] contactDetails = new String[NUMBER_OF_FIELDS]; - for (int i = 0; i < NUMBER_OF_FIELDS; i++) { - switch (i) { - case NAME_INDEX: - contactDetails[NAME_INDEX] = contact.getName(); - break; - case GITHUB_INDEX: - contactDetails[GITHUB_INDEX] = contact.getGithub(); - break; - case LINKEDIN_INDEX: - contactDetails[LINKEDIN_INDEX] = contact.getLinkedin(); - break; - case TELEGRAM_INDEX: - contactDetails[TELEGRAM_INDEX] = contact.getTelegram(); - break; - case TWITTER_INDEX: - contactDetails[TWITTER_INDEX] = contact.getTwitter(); - break; - case EMAIL_INDEX: - contactDetails[EMAIL_INDEX] = contact.getEmail(); - break; - default: - assert false; - throw new InvalidFlagException(); - } - } - return contactDetails; - } - private boolean hasDuplicateField(String input, String saved) { return stringCleaner(saved).equals(stringCleaner(input)); } diff --git a/src/main/java/seedu/command/EditContactCommand.java b/src/main/java/seedu/command/EditContactCommand.java index ebb0ad4c5b..9547e59e19 100644 --- a/src/main/java/seedu/command/EditContactCommand.java +++ b/src/main/java/seedu/command/EditContactCommand.java @@ -12,12 +12,6 @@ public class EditContactCommand extends Command { public static final int PERSONAL_CONTACT_INDEX = -1; - public static final int NAME_INDEX = 0; - public static final int GITHUB_INDEX = 1; - public static final int LINKEDIN_INDEX = 2; - public static final int TELEGRAM_INDEX = 3; - public static final int TWITTER_INDEX = 4; - public static final int EMAIL_INDEX = 5; public static final int NUMBER_OF_FIELDS = 6; public static final String EDIT_TYPE = "edit"; String[] contactDetails; @@ -64,16 +58,15 @@ private void updateContact(Contact postEditContact) throws IndexOutOfBoundsExcep } //@@author ashrafjfr - private boolean hasDuplicates(Contact postEditContact, ContactList contactList, int contactIndex) - throws InvalidFlagException { + private boolean hasDuplicates(Contact postEditContact, ContactList contactList, int contactIndex) { ArrayList duplicatedIndex = new ArrayList<>(); boolean[] hasEditedField = hasEditedFields(contactDetails); - String[] postEditContactDetails = extractContactDetails(postEditContact); + String[] postEditContactDetails = postEditContact.getContactStringArray(); for (int i = 0; i < contactList.getListSize(); i++) { if (i == contactIndex) { continue; } - String[] currentContactDetails = extractContactDetails(contactList.getContactAtIndex(i)); + String[] currentContactDetails = contactList.getContactAtIndex(i).getContactStringArray(); for (int j = 0; j < NUMBER_OF_FIELDS; j++) { if (!hasEditedField[j]) { continue; @@ -109,40 +102,6 @@ private String cleanString(String input) { return input.replace(" ", "").toLowerCase(); } - private String[] extractContactDetails(Contact contact) throws InvalidFlagException { - String[] contactDetails = new String[NUMBER_OF_FIELDS]; - for (int i = 0; i < NUMBER_OF_FIELDS; i++) { - switch (i) { - case NAME_INDEX: - contactDetails[NAME_INDEX] = contact.getName(); - break; - case GITHUB_INDEX: - contactDetails[GITHUB_INDEX] = contact.getGithub(); - break; - case LINKEDIN_INDEX: - contactDetails[LINKEDIN_INDEX] = contact.getLinkedin(); - break; - case TELEGRAM_INDEX: - contactDetails[TELEGRAM_INDEX] = contact.getTelegram(); - break; - case TWITTER_INDEX: - contactDetails[TWITTER_INDEX] = contact.getTwitter(); - break; - case EMAIL_INDEX: - contactDetails[EMAIL_INDEX] = contact.getEmail(); - break; - default: - assert false; - throw new InvalidFlagException(); - } - } - return contactDetails; - } - - public int getContactIndex() { - return this.contactIndex; - } - //@@author ng-andre private Contact duplicateContact(Contact contact) { String name = contact.getName(); From 2361b786139743e1dc8dcb70c67934c5dd9c0055 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 27 Oct 2021 22:57:07 +0800 Subject: [PATCH 544/756] Refactor DeleteContactCommand and ViewContactCommand to use getContactAtIndex() --- src/main/java/seedu/command/DeleteContactCommand.java | 4 ++-- src/main/java/seedu/command/ViewContactCommand.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/command/DeleteContactCommand.java b/src/main/java/seedu/command/DeleteContactCommand.java index 4964807a0b..ea5f85f41a 100644 --- a/src/main/java/seedu/command/DeleteContactCommand.java +++ b/src/main/java/seedu/command/DeleteContactCommand.java @@ -33,7 +33,7 @@ public int getContactIndex() { private void deleteSelectedContact() throws IndexOutOfBoundsException { // throws IndexOutOfBoundsException if index is outside of the range - Contact deletedContact = IndexParser.getContactFromIndex(contactIndex, contactList); + Contact deletedContact = contactList.getContactAtIndex(contactIndex); // index must be within range since no exceptions thrown assert contactIndex >= 0 && contactIndex < contactList.getListSize(); // ask for confirmation to delete from user @@ -64,7 +64,7 @@ private void deleteAllContacts() { } private void deleteFields() { - Contact deletedContact = IndexParser.getContactFromIndex(contactIndex, contactList); + Contact deletedContact = contactList.getContactAtIndex(contactIndex); assert contactIndex >= 0 && contactIndex < contactList.getListSize(); if (TextUi.deletedFieldsGenerator(hasDeletedDetail, deletedContact).isEmpty()) { //if no fields exist, return false diff --git a/src/main/java/seedu/command/ViewContactCommand.java b/src/main/java/seedu/command/ViewContactCommand.java index 261875c837..4322e91b5d 100644 --- a/src/main/java/seedu/command/ViewContactCommand.java +++ b/src/main/java/seedu/command/ViewContactCommand.java @@ -20,7 +20,7 @@ public int getIndex() { public void execute() { try { - Contact viewingContact = IndexParser.getContactFromIndex(contactIndex, contactList); + Contact viewingContact = contactList.getContactAtIndex(contactIndex); assert contactIndex >= 0 && contactIndex < contactList.getListSize(); TextUi.viewContactMessage(viewingContact, contactIndex); } catch (IndexOutOfBoundsException e) { From c4d5dd963aa9360cc15f4a3ae05cb41eb9867d99 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 27 Oct 2021 22:57:49 +0800 Subject: [PATCH 545/756] Rename boolean array to hasDeletedDetails --- .../java/seedu/command/DeleteContactCommand.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/seedu/command/DeleteContactCommand.java b/src/main/java/seedu/command/DeleteContactCommand.java index ea5f85f41a..d2793c1c42 100644 --- a/src/main/java/seedu/command/DeleteContactCommand.java +++ b/src/main/java/seedu/command/DeleteContactCommand.java @@ -19,11 +19,11 @@ public class DeleteContactCommand extends Command { public static final int EMAIL_INDEX = 5; private final int contactIndex; - private final boolean[] hasDeletedDetail; + private final boolean[] hasDeletedDetails; - public DeleteContactCommand(int contactIndex, boolean[] hasDeletedDetail) { + public DeleteContactCommand(int contactIndex, boolean[] hasDeletedDetails) { this.contactIndex = contactIndex; - this.hasDeletedDetail = hasDeletedDetail; + this.hasDeletedDetails = hasDeletedDetails; } public int getContactIndex() { @@ -66,12 +66,12 @@ private void deleteAllContacts() { private void deleteFields() { Contact deletedContact = contactList.getContactAtIndex(contactIndex); assert contactIndex >= 0 && contactIndex < contactList.getListSize(); - if (TextUi.deletedFieldsGenerator(hasDeletedDetail, deletedContact).isEmpty()) { + if (TextUi.deletedFieldsGenerator(hasDeletedDetails, deletedContact).isEmpty()) { //if no fields exist, return false TextUi.noDeleteFields(); return; } - TextUi.confirmDeleteFieldMessage(hasDeletedDetail, deletedContact); + TextUi.confirmDeleteFieldMessage(hasDeletedDetails, deletedContact); String userConfirmation = UserInputTextUi.getUserConfirmation(); if (userConfirmation.equalsIgnoreCase(ACKNOWLEDGE_DELETE)) { if (hasDeletedDetail[GITHUB_INDEX]) { @@ -100,7 +100,7 @@ public void execute() { try { if (contactIndex == DELETE_ALL_CONTACTS) { deleteAllContacts(); - } else if (hasDeletedDetail[6]) { //delete entire contact + } else if (hasDeletedDetails[6]) { //delete entire contact deleteSelectedContact(); } else { deleteFields(); From 8f0df19ee6d363b8c9f97f15b37d451c0c841fe4 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 27 Oct 2021 22:58:44 +0800 Subject: [PATCH 546/756] Refactor setDetail as it is shared between edit and delete fields --- src/main/java/seedu/contact/Contact.java | 56 ++++++++++++++---------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/src/main/java/seedu/contact/Contact.java b/src/main/java/seedu/contact/Contact.java index d14299768b..dd5bf0fc41 100644 --- a/src/main/java/seedu/contact/Contact.java +++ b/src/main/java/seedu/contact/Contact.java @@ -23,33 +23,43 @@ public Contact(String name, String github, String linkedin, String telegram, Str this.email = email; } + //@@author ng-andre + public void setDetail(String updatedDetail, int index) { + switch (index) { + case NAME_INDEX: + setName(updatedDetail); + break; + case GITHUB_INDEX: + setGithub(updatedDetail); + break; + case LINKEDIN_INDEX: + setLinkedin(updatedDetail); + break; + case TELEGRAM_INDEX: + setTelegram(updatedDetail); + break; + case TWITTER_INDEX: + setTwitter(updatedDetail); + break; + case EMAIL_INDEX: + setEmail(updatedDetail); + break; + default: + //control should never reach here + assert false; + return; + } + } + //@@author ng-andre public void editContact(String[] contactDetails) { for (int i = 0; i < contactDetails.length; i++) { if (contactDetails[i] != null) { - switch (i) { - case NAME_INDEX: - setName(contactDetails[i]); - break; - case GITHUB_INDEX: - setGithub(contactDetails[i]); - break; - case LINKEDIN_INDEX: - setLinkedin(contactDetails[i]); - break; - case TELEGRAM_INDEX: - setTelegram(contactDetails[i]); - break; - case TWITTER_INDEX: - setTwitter(contactDetails[i]); - break; - case EMAIL_INDEX: - setEmail(contactDetails[i]); - break; - default: - //control should never reach here - assert false; - } + setDetail(contactDetails[i], i); + } + } + } + //@@author marcusbory } } From 750b1b38e0ad5bde5b2831b71769f6adb2458f7f Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 27 Oct 2021 22:59:03 +0800 Subject: [PATCH 547/756] Refactor DeleteContactCommand for detail deletion --- .../seedu/command/DeleteContactCommand.java | 21 +------------------ src/main/java/seedu/contact/Contact.java | 4 ++++ 2 files changed, 5 insertions(+), 20 deletions(-) diff --git a/src/main/java/seedu/command/DeleteContactCommand.java b/src/main/java/seedu/command/DeleteContactCommand.java index d2793c1c42..1de396b486 100644 --- a/src/main/java/seedu/command/DeleteContactCommand.java +++ b/src/main/java/seedu/command/DeleteContactCommand.java @@ -12,11 +12,6 @@ public class DeleteContactCommand extends Command { private static final String ACKNOWLEDGE_DELETE = "y"; private static final int DELETE_ALL_CONTACTS = -2; - public static final int GITHUB_INDEX = 1; - public static final int LINKEDIN_INDEX = 2; - public static final int TELEGRAM_INDEX = 3; - public static final int TWITTER_INDEX = 4; - public static final int EMAIL_INDEX = 5; private final int contactIndex; private final boolean[] hasDeletedDetails; @@ -74,21 +69,7 @@ private void deleteFields() { TextUi.confirmDeleteFieldMessage(hasDeletedDetails, deletedContact); String userConfirmation = UserInputTextUi.getUserConfirmation(); if (userConfirmation.equalsIgnoreCase(ACKNOWLEDGE_DELETE)) { - if (hasDeletedDetail[GITHUB_INDEX]) { - deletedContact.setGithub(null); - } - if (hasDeletedDetail[LINKEDIN_INDEX]) { - deletedContact.setLinkedin(null); - } - if (hasDeletedDetail[TELEGRAM_INDEX]) { - deletedContact.setTelegram(null); - } - if (hasDeletedDetail[TWITTER_INDEX]) { - deletedContact.setTwitter(null); - } - if (hasDeletedDetail[EMAIL_INDEX]) { - deletedContact.setEmail(null); - } + deletedContact.deleteContactFields(hasDeletedDetails); TextUi.deleteFieldsMessage(deletedContact); } else { assert !userConfirmation.equalsIgnoreCase(ACKNOWLEDGE_DELETE); diff --git a/src/main/java/seedu/contact/Contact.java b/src/main/java/seedu/contact/Contact.java index dd5bf0fc41..ae38672026 100644 --- a/src/main/java/seedu/contact/Contact.java +++ b/src/main/java/seedu/contact/Contact.java @@ -61,6 +61,10 @@ public void editContact(String[] contactDetails) { } //@@author marcusbory + public void deleteContactFields(boolean[] hasDeletedDetails) { + for (int i = GITHUB_INDEX; i <= EMAIL_INDEX; i++) { + if (hasDeletedDetails[i]) { + setDetail(null, i); } } } From 447940f1485a90658f1250a76d8e8cfffc74045f Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 27 Oct 2021 22:59:37 +0800 Subject: [PATCH 548/756] Update getContactAtIndex to throw IndexOutOfBoundsException --- src/main/java/seedu/contact/ContactList.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/main/java/seedu/contact/ContactList.java b/src/main/java/seedu/contact/ContactList.java index 05770a34b9..2af77f5bdc 100644 --- a/src/main/java/seedu/contact/ContactList.java +++ b/src/main/java/seedu/contact/ContactList.java @@ -56,12 +56,8 @@ public void searchContact(String query, int detailType) throws InvalidFlagExcept } } - public int getIndexOfContact(Contact contact) { - return contacts.indexOf(contact); - } - - public Contact getContactAtIndex(int index) { //@@author marcusbory + public Contact getContactAtIndex(int index) throws IndexOutOfBoundsException { sortContacts(); return contacts.get(index); } From 6a71dbd46843bd6e0acfee8839771a310a1ce415 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 27 Oct 2021 23:00:02 +0800 Subject: [PATCH 549/756] Remove unnecessary lines --- src/main/java/seedu/parser/ContactParser.java | 4 ---- src/main/java/seedu/parser/IndexParser.java | 7 ------- src/main/java/seedu/parser/MainParser.java | 3 --- 3 files changed, 14 deletions(-) diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index 4a5b360b66..26136e4036 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -13,8 +13,6 @@ import seedu.exception.MissingArgEditException; import seedu.exception.MissingDetailException; -import java.util.logging.Logger; - public abstract class ContactParser extends RegexParser implements ContactDetails { public static final int CONTACT_PARAMS_START_INDEX = 1; public static final int NUMBER_OF_DETAILS = 2; @@ -27,8 +25,6 @@ public abstract class ContactParser extends RegexParser implements ContactDetail public static final int DETAIL_INDEX_IN_DETAILS = 1; public static final int USER_INFO_INDEX = 2; - private static final Logger LOGGER = Logger.getLogger(ContactParser.class.getName()); - public abstract String[] parseContactDetails(String userInput) throws InvalidFlagException, MissingDetailException, ForbiddenDetailException, InvalidNameException, InvalidGithubUsernameException, InvalidTelegramUsernameException, diff --git a/src/main/java/seedu/parser/IndexParser.java b/src/main/java/seedu/parser/IndexParser.java index 4fe784ef1b..8587ebfeeb 100644 --- a/src/main/java/seedu/parser/IndexParser.java +++ b/src/main/java/seedu/parser/IndexParser.java @@ -2,11 +2,8 @@ package seedu.parser; -import seedu.contact.Contact; -import seedu.contact.ContactList; import seedu.exception.MissingIndexException; - public class IndexParser { private static final int COMD_WORD_LENGTH = 1; private static final int INDEX_POSITION = 1; @@ -48,8 +45,4 @@ public static int getIndexFromInput(String userInput) } return index; } - - public static Contact getContactFromIndex(int index, ContactList contactList) throws IndexOutOfBoundsException { - return contactList.getContactAtIndex(index); - } } diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 409e292d2b..3c32aa28f2 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -46,7 +46,6 @@ public class MainParser { private static final int ISOLATE_COMD_WORD = 2; public static final int NAME_INDEX = 0; - private ContactParser contactParser; private final AddContactParser addContactParser = new AddContactParser(); private final EditContactParser editContactParser = new EditContactParser(); private final SearchContactParser searchContactParser = new SearchContactParser(); @@ -165,7 +164,6 @@ private Command parseQueryCommand(String commandWord, String userInput) { //@@author marcusbory private Command parseAddContact(String userInput) { - contactParser = addContactParser; try { String[] details = addContactParser.parseContactDetails(userInput); //check if name is specified in input @@ -187,7 +185,6 @@ private Command parseAddContact(String userInput) { //@@author ng-andre private Command parseEditContact(String userInput) { // userInput is raw user input - contactParser = editContactParser; try { String[] details = editContactParser.parseContactDetails(userInput); int userIndex = IndexParser.getIndexFromInput(userInput); //throws MissingIndexException From ae9040b6b6997f40665652533a3dbb1885bff316 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 27 Oct 2021 23:00:14 +0800 Subject: [PATCH 550/756] Add fallthrough comments for switch cases --- src/main/java/seedu/parser/MainParser.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 3c32aa28f2..9c394584b7 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -80,16 +80,16 @@ public CommandType getCommandType(String userInput) { String commandWord = getCommandWord(userInput); CommandType commandType; switch (commandWord) { - case ADD_CONTACT_COMD: - case EDIT_CONTACT_COMD: - case DELETE_CONTACT_COMD: + case ADD_CONTACT_COMD: // Fallthrough + case EDIT_CONTACT_COMD: // Fallthrough + case DELETE_CONTACT_COMD: // Fallthrough case IMPORT_COMD: commandType = CommandType.MANIPULATION; break; - case VIEW_CONTACT_COMD: - case SEARCH_COMD: - case LIST_COMD: - case HELP_COMD: + case VIEW_CONTACT_COMD: // Fallthrough + case SEARCH_COMD: // Fallthrough + case LIST_COMD: // Fallthrough + case HELP_COMD: // Fallthrough case PERSONAL_CONTACT_COMD: commandType = CommandType.QUERY; break; From 3420fd400a1ce34bed3e13ce3ff120789d942ee7 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 27 Oct 2021 23:00:34 +0800 Subject: [PATCH 551/756] Fix UI bug for deleting contact details --- src/main/java/seedu/ui/TextUi.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/ui/TextUi.java b/src/main/java/seedu/ui/TextUi.java index 82e6a61e7d..94c9b9206f 100644 --- a/src/main/java/seedu/ui/TextUi.java +++ b/src/main/java/seedu/ui/TextUi.java @@ -212,7 +212,7 @@ public static String deletedFieldsGenerator(boolean[] hasDeletedDetail, Contact StringBuilder output = new StringBuilder(); assert hasDeletedDetail.length == 7; String[] contactDetails = contact.getContactStringArray(); - for (int i = GITHUB_INDEX; i < EMAIL_INDEX; i++) { //from GitHub to Email + for (int i = GITHUB_INDEX; i <= EMAIL_INDEX; i++) { //from GitHub to Email if (contactDetails[i] != null && hasDeletedDetail[i]) { output.append(ViewMessageFormatterUi.viewDetailFormatter(contact, i)); } From 4061bd7fd5b3a7780cc25c4d27ae1f1bc83cc090 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 27 Oct 2021 23:00:54 +0800 Subject: [PATCH 552/756] Update IO redirection tests for deleting fields --- text-ui-test/ACTUAL.TXT | 16 ++++++++++++++++ text-ui-test/EXPECTED-UNIX.TXT | 16 ++++++++++++++++ text-ui-test/EXPECTED.TXT | 16 ++++++++++++++++ text-ui-test/input.txt | 3 +++ 4 files changed, 51 insertions(+) diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index 1a3ae732c5..94ede86a5c 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -760,6 +760,22 @@ ____________________________________________________________ 13. yusdhsdsd ____________________________________________________________ +____________________________________________________________ +Delete the following fields for ashraf? (y/n) + +Telegram: t.me/ashrafjfr +Email: ashrafjfr@gmail.com +____________________________________________________________ + +____________________________________________________________ +The specified fields for ashraf have been deleted. +____________________________________________________________ + +____________________________________________________________ +0. ashraf +Github: github.com/ashrafjfr +____________________________________________________________ + ____________________________________________________________ Delete all of your contacts? (y/n) ____________________________________________________________ diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index 1a3ae732c5..94ede86a5c 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -760,6 +760,22 @@ ____________________________________________________________ 13. yusdhsdsd ____________________________________________________________ +____________________________________________________________ +Delete the following fields for ashraf? (y/n) + +Telegram: t.me/ashrafjfr +Email: ashrafjfr@gmail.com +____________________________________________________________ + +____________________________________________________________ +The specified fields for ashraf have been deleted. +____________________________________________________________ + +____________________________________________________________ +0. ashraf +Github: github.com/ashrafjfr +____________________________________________________________ + ____________________________________________________________ Delete all of your contacts? (y/n) ____________________________________________________________ diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 1a3ae732c5..94ede86a5c 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -760,6 +760,22 @@ ____________________________________________________________ 13. yusdhsdsd ____________________________________________________________ +____________________________________________________________ +Delete the following fields for ashraf? (y/n) + +Telegram: t.me/ashrafjfr +Email: ashrafjfr@gmail.com +____________________________________________________________ + +____________________________________________________________ +The specified fields for ashraf have been deleted. +____________________________________________________________ + +____________________________________________________________ +0. ashraf +Github: github.com/ashrafjfr +____________________________________________________________ + ____________________________________________________________ Delete all of your contacts? (y/n) ____________________________________________________________ diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index 811e881f7b..49c900e2fc 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -93,6 +93,9 @@ ls rm all asdsad ls +rm 0 -e -te -tw +y +view 0 rm all y ls From 9b61e5a93efd1520d0ee7f68557f0f2bbf287eaa Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 27 Oct 2021 23:20:06 +0800 Subject: [PATCH 553/756] Add DuplicateDetailException --- src/main/java/seedu/exception/DuplicateDetailException.java | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/main/java/seedu/exception/DuplicateDetailException.java diff --git a/src/main/java/seedu/exception/DuplicateDetailException.java b/src/main/java/seedu/exception/DuplicateDetailException.java new file mode 100644 index 0000000000..4beff2317e --- /dev/null +++ b/src/main/java/seedu/exception/DuplicateDetailException.java @@ -0,0 +1,4 @@ +package seedu.exception; + +public class DuplicateDetailException extends Exception { +} From 7266ff810def13a84ed425e11943f5b383d65f44 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 27 Oct 2021 23:20:27 +0800 Subject: [PATCH 554/756] Implement error message for duplicated detail flags --- src/main/java/seedu/command/FailedCommand.java | 4 ++++ src/main/java/seedu/ui/ExceptionTextUi.java | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/src/main/java/seedu/command/FailedCommand.java b/src/main/java/seedu/command/FailedCommand.java index 038b11d137..21e297f4f4 100644 --- a/src/main/java/seedu/command/FailedCommand.java +++ b/src/main/java/seedu/command/FailedCommand.java @@ -27,6 +27,7 @@ public void execute() { case NUM_OUT_OF_BOUND: // Fallthrough case NUM_OUT_OF_BOUND_EDIT: // Fallthrough case INVALID_DELETE: //Fallthrough + case DUPLICATE_DETAIL: invalidUserInputExecute(); break; case MISSING_ARGS_EDIT: // Fallthrough @@ -65,6 +66,9 @@ private void invalidUserInputExecute() { case INVALID_DELETE: ExceptionTextUi.invalidDeleteFlag(); break; + case DUPLICATE_DETAIL: + ExceptionTextUi.duplicateDetailMessage(); + break; default: return; } diff --git a/src/main/java/seedu/ui/ExceptionTextUi.java b/src/main/java/seedu/ui/ExceptionTextUi.java index 7829efb2f5..baf489d18e 100644 --- a/src/main/java/seedu/ui/ExceptionTextUi.java +++ b/src/main/java/seedu/ui/ExceptionTextUi.java @@ -255,6 +255,12 @@ public static void forbiddenDetailMessage() { printDoubleLineMessage(message); } + public static void duplicateDetailMessage() { + String message = "There appears to be duplicated flags in your command.\n" + + "Please kindly remove them to prevent any ambiguous action performed."; + printDoubleLineMessage(message); + } + public static void invalidLoadedLineMessage(int lineIndex, String contactFilePath) { System.out.println(contactFilePath + ":" + lineIndex + " - There is an invalid field."); } From 8f29e2f69a6cfad7ea72a465a0cc20fd291b56ac Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 27 Oct 2021 23:21:15 +0800 Subject: [PATCH 555/756] Update contact parsers to handle duplicated detail flags --- src/main/java/seedu/parser/AddContactParser.java | 3 ++- src/main/java/seedu/parser/ContactParser.java | 8 ++++++-- src/main/java/seedu/parser/EditContactParser.java | 4 +++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/main/java/seedu/parser/AddContactParser.java b/src/main/java/seedu/parser/AddContactParser.java index b5008636f6..c23f1b7b31 100644 --- a/src/main/java/seedu/parser/AddContactParser.java +++ b/src/main/java/seedu/parser/AddContactParser.java @@ -1,6 +1,7 @@ //@@author marcusbory package seedu.parser; +import seedu.exception.DuplicateDetailException; import seedu.exception.ForbiddenDetailException; import seedu.exception.InvalidEmailException; import seedu.exception.InvalidFlagException; @@ -29,7 +30,7 @@ public class AddContactParser extends ContactParser { public String[] parseContactDetails(String userInput) throws InvalidFlagException, MissingArgAddException, InvalidNameException, InvalidGithubUsernameException, InvalidTelegramUsernameException, - InvalidLinkedinUsernameException, InvalidTwitterUsernameException, + InvalidLinkedinUsernameException, InvalidTwitterUsernameException, DuplicateDetailException, InvalidEmailException, MissingDetailException, ForbiddenDetailException { String[] contactDetails = new String[NUMBER_OF_FIELDS]; String[] destructuredInputs = userInput.split(DETAIL_SEPARATOR); diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index 26136e4036..bbaba252b2 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -1,6 +1,7 @@ //@@author marcusbory package seedu.parser; +import seedu.exception.DuplicateDetailException; import seedu.exception.ForbiddenDetailException; import seedu.exception.InvalidEmailException; import seedu.exception.InvalidFlagException; @@ -29,7 +30,7 @@ public abstract String[] parseContactDetails(String userInput) throws InvalidFlagException, MissingDetailException, ForbiddenDetailException, InvalidNameException, InvalidGithubUsernameException, InvalidTelegramUsernameException, InvalidLinkedinUsernameException, InvalidTwitterUsernameException, InvalidEmailException, - MissingArgEditException, MissingArgAddException; + MissingArgEditException, MissingArgAddException, DuplicateDetailException; /** * This method takes in the contactDetails array and populates it with contact @@ -43,7 +44,7 @@ public abstract String[] parseContactDetails(String userInput) public void parseDetail(String[] contactDetails, String detail) throws InvalidFlagException, MissingDetailException, ForbiddenDetailException, InvalidNameException, InvalidGithubUsernameException, InvalidTelegramUsernameException, InvalidLinkedinUsernameException, - InvalidTwitterUsernameException, InvalidEmailException { + InvalidTwitterUsernameException, InvalidEmailException, DuplicateDetailException { String[] destructuredDetails = detail.split(" ", NUMBER_OF_DETAILS); // for commands that specify a flag, but do not specify any argument for that // flag @@ -60,6 +61,9 @@ public void parseDetail(String[] contactDetails, String detail) } checkRegex(flag, detailToStore); int indexToStore = getIndexToStore(flag); + if (contactDetails[indexToStore] != null) { + throw new DuplicateDetailException(); + } contactDetails[indexToStore] = detailToStore; } } diff --git a/src/main/java/seedu/parser/EditContactParser.java b/src/main/java/seedu/parser/EditContactParser.java index 61c4f98ddc..be0ec9dc57 100644 --- a/src/main/java/seedu/parser/EditContactParser.java +++ b/src/main/java/seedu/parser/EditContactParser.java @@ -1,5 +1,6 @@ package seedu.parser; +import seedu.exception.DuplicateDetailException; import seedu.exception.ForbiddenDetailException; import seedu.exception.InvalidEmailException; import seedu.exception.InvalidFlagException; @@ -17,7 +18,8 @@ public class EditContactParser extends ContactParser { public String[] parseContactDetails(String userInput) throws InvalidFlagException, MissingDetailException, ForbiddenDetailException, InvalidNameException, InvalidGithubUsernameException, InvalidTelegramUsernameException, InvalidLinkedinUsernameException, - InvalidTwitterUsernameException, InvalidEmailException, MissingArgEditException { + InvalidTwitterUsernameException, InvalidEmailException, MissingArgEditException, + DuplicateDetailException { String[] inputDetails = userInput.split(" ", NUMBER_OF_EDIT_ARGS); if (inputDetails.length < NUMBER_OF_EDIT_ARGS) { From 3735be164c30ca0fec3972684c7ad1c9d6ea5ba3 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 27 Oct 2021 23:21:37 +0800 Subject: [PATCH 556/756] Update main parser to account for duplicated detail failedcommandtype --- src/main/java/seedu/parser/FailedCommandType.java | 3 ++- src/main/java/seedu/parser/MainParser.java | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/parser/FailedCommandType.java b/src/main/java/seedu/parser/FailedCommandType.java index 83b0b866ae..91c045d20f 100644 --- a/src/main/java/seedu/parser/FailedCommandType.java +++ b/src/main/java/seedu/parser/FailedCommandType.java @@ -5,5 +5,6 @@ public enum FailedCommandType { MISSING_DETAIL, MISSING_INDEX, INVALID_NUM, INVALID_FORMAT, NUM_OUT_OF_BOUND, NUM_OUT_OF_BOUND_EDIT, INVALID_INDEX, MISSING_NAME, FORBIDDEN_DETAIL, INVALID_NAME, INVALID_GITHUB_USERNAME, - INVALID_LINKEDIN, INVALID_TELEGRAM, INVALID_MAIL, INVALID_TWITTER, INVALID_DELETE + INVALID_LINKEDIN, INVALID_TELEGRAM, INVALID_MAIL, INVALID_TWITTER, INVALID_DELETE, + DUPLICATE_DETAIL } diff --git a/src/main/java/seedu/parser/MainParser.java b/src/main/java/seedu/parser/MainParser.java index 9c394584b7..f73e215ab6 100644 --- a/src/main/java/seedu/parser/MainParser.java +++ b/src/main/java/seedu/parser/MainParser.java @@ -13,6 +13,7 @@ import seedu.command.PersonalContactCommand; import seedu.command.SearchContactCommand; import seedu.command.ViewContactCommand; +import seedu.exception.DuplicateDetailException; import seedu.exception.ForbiddenDetailException; import seedu.exception.InvalidDeleteDetailException; import seedu.exception.InvalidEmailException; @@ -176,6 +177,8 @@ private Command parseAddContact(String userInput) { return new FailedCommand(FailedCommandType.INVALID_FLAG); } catch (MissingDetailException | MissingArgAddException e) { return new FailedCommand(FailedCommandType.MISSING_ARGS_ADD); + } catch (DuplicateDetailException e) { + return new FailedCommand(FailedCommandType.DUPLICATE_DETAIL); } catch (InvalidNameException | InvalidGithubUsernameException | InvalidEmailException | InvalidLinkedinUsernameException | InvalidTelegramUsernameException | InvalidTwitterUsernameException | ForbiddenDetailException e) { @@ -196,6 +199,8 @@ private Command parseEditContact(String userInput) { // userInput is raw user in return new FailedCommand(FailedCommandType.MISSING_ARGS_EDIT); } catch (NumberFormatException e) { return new FailedCommand(FailedCommandType.NUM_OUT_OF_BOUND_EDIT); + } catch (DuplicateDetailException e) { + return new FailedCommand(FailedCommandType.DUPLICATE_DETAIL); } catch (InvalidNameException | InvalidGithubUsernameException | InvalidEmailException | InvalidLinkedinUsernameException | InvalidTelegramUsernameException | InvalidTwitterUsernameException | ForbiddenDetailException e) { From 700d87e70e324bb89b25fd7d8d0b5f19e2b54bfb Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 27 Oct 2021 23:22:03 +0800 Subject: [PATCH 557/756] Update JUnit tests due to changes to contact parsers --- src/test/java/seedu/parser/AddContactParserTest.java | 8 +++++--- src/test/java/seedu/parser/EditContactParserTest.java | 5 +++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/test/java/seedu/parser/AddContactParserTest.java b/src/test/java/seedu/parser/AddContactParserTest.java index 95c3c70069..619b654e57 100644 --- a/src/test/java/seedu/parser/AddContactParserTest.java +++ b/src/test/java/seedu/parser/AddContactParserTest.java @@ -3,6 +3,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import seedu.contact.DetailType; +import seedu.exception.DuplicateDetailException; import seedu.exception.ForbiddenDetailException; import seedu.exception.InvalidEmailException; import seedu.exception.InvalidFlagException; @@ -38,7 +39,8 @@ public void setUp() { void parseContactDetails_inputsWithIrregularSpacing_expectCorrectDetails() throws InvalidFlagException, MissingDetailException, ForbiddenDetailException, InvalidTelegramUsernameException, InvalidNameException, InvalidLinkedinUsernameException, InvalidGithubUsernameException, - InvalidTwitterUsernameException, InvalidEmailException, MissingArgAddException { + InvalidTwitterUsernameException, InvalidEmailException, MissingArgAddException, + DuplicateDetailException { inputUserInput = " add -n andre -g ng-andre -l linkedin -tw twit -te tel69 -e yoyo@gmail.com"; actualOutput = addContactParser.parseContactDetails(inputUserInput); expectedOutput = new String[]{"andre", "ng-andre", "linkedin", "tel69", "twit", "yoyo@gmail.com"}; @@ -89,7 +91,7 @@ void parseDetail_invalidFlagUsed_expectException() { void parseDetail_inputsWithTrailingSpaces_expectNewContactDetail() throws InvalidFlagException, MissingDetailException, ForbiddenDetailException, InvalidTelegramUsernameException, InvalidNameException, InvalidLinkedinUsernameException, InvalidGithubUsernameException, - InvalidTwitterUsernameException, InvalidEmailException { + InvalidTwitterUsernameException, InvalidEmailException, DuplicateDetailException { inputDetail = "n andre"; addContactParser.parseDetail(inputContactDetails, inputDetail); assertEquals("andre", inputContactDetails[DetailType.NAME.getIndex()]); @@ -99,7 +101,7 @@ void parseDetail_inputsWithTrailingSpaces_expectNewContactDetail() throws Invali void parseDetail_inputsWithSpaceInDetail_expectNewContactDetail() throws InvalidFlagException, MissingDetailException, ForbiddenDetailException, InvalidTelegramUsernameException, InvalidNameException, InvalidLinkedinUsernameException, InvalidGithubUsernameException, - InvalidTwitterUsernameException, InvalidEmailException { + InvalidTwitterUsernameException, InvalidEmailException, DuplicateDetailException { inputDetail = "n Marcus Bory"; addContactParser.parseDetail(inputContactDetails, inputDetail); assertEquals("Marcus Bory", inputContactDetails[DetailType.NAME.getIndex()]); diff --git a/src/test/java/seedu/parser/EditContactParserTest.java b/src/test/java/seedu/parser/EditContactParserTest.java index 0abde21ea7..18808313c8 100644 --- a/src/test/java/seedu/parser/EditContactParserTest.java +++ b/src/test/java/seedu/parser/EditContactParserTest.java @@ -2,6 +2,7 @@ import org.junit.jupiter.api.Test; +import seedu.exception.DuplicateDetailException; import seedu.exception.ForbiddenDetailException; import seedu.exception.InvalidEmailException; import seedu.exception.InvalidFlagException; @@ -24,7 +25,7 @@ class EditContactParserTest { void parseContactDetails() throws MissingDetailException, MissingArgEditException, InvalidFlagException, ForbiddenDetailException, InvalidTelegramUsernameException, InvalidNameException, InvalidLinkedinUsernameException, InvalidGithubUsernameException, - InvalidTwitterUsernameException, InvalidEmailException { + InvalidTwitterUsernameException, InvalidEmailException, DuplicateDetailException { String[] expectedResult = {null, "github", null, null, null, null}; String testInput = "edit 1 -g github"; String[] actualResult = editContactParser.parseContactDetails(testInput); @@ -36,7 +37,7 @@ void parseContactDetails() throws MissingDetailException, void parseEditCommand_inputAllFields_expectOutput() throws MissingDetailException, MissingArgEditException, InvalidFlagException, ForbiddenDetailException, InvalidTelegramUsernameException, InvalidNameException, InvalidLinkedinUsernameException, InvalidGithubUsernameException, - InvalidTwitterUsernameException, InvalidEmailException { + InvalidTwitterUsernameException, InvalidEmailException, DuplicateDetailException { String[] expectedResult = {"akshay", "topcoder", "akshay123", "akshay123", "akshay123", "akshay@gmail.com"}; String testInput = "edit 1 -n akshay -g topcoder -l akshay123 -te akshay123 -tw akshay123 -e akshay@gmail.com"; String[] actualResult = editContactParser.parseContactDetails(testInput); From 0f8f69a6d6c1f995f8666be66a5ece0640c675b3 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 27 Oct 2021 23:22:21 +0800 Subject: [PATCH 558/756] Update IO redirection tests for duplicated details --- text-ui-test/ACTUAL.TXT | 10 ++++++++++ text-ui-test/EXPECTED-UNIX.TXT | 10 ++++++++++ text-ui-test/EXPECTED.TXT | 10 ++++++++++ text-ui-test/input.txt | 2 ++ 4 files changed, 32 insertions(+) diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index 94ede86a5c..8c25fac00c 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -776,6 +776,16 @@ ____________________________________________________________ Github: github.com/ashrafjfr ____________________________________________________________ +____________________________________________________________ +There appears to be duplicated flags in your command. +Please kindly remove them to prevent any ambiguous action performed. +____________________________________________________________ + +____________________________________________________________ +There appears to be duplicated flags in your command. +Please kindly remove them to prevent any ambiguous action performed. +____________________________________________________________ + ____________________________________________________________ Delete all of your contacts? (y/n) ____________________________________________________________ diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index 94ede86a5c..8c25fac00c 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -776,6 +776,16 @@ ____________________________________________________________ Github: github.com/ashrafjfr ____________________________________________________________ +____________________________________________________________ +There appears to be duplicated flags in your command. +Please kindly remove them to prevent any ambiguous action performed. +____________________________________________________________ + +____________________________________________________________ +There appears to be duplicated flags in your command. +Please kindly remove them to prevent any ambiguous action performed. +____________________________________________________________ + ____________________________________________________________ Delete all of your contacts? (y/n) ____________________________________________________________ diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 94ede86a5c..8c25fac00c 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -776,6 +776,16 @@ ____________________________________________________________ Github: github.com/ashrafjfr ____________________________________________________________ +____________________________________________________________ +There appears to be duplicated flags in your command. +Please kindly remove them to prevent any ambiguous action performed. +____________________________________________________________ + +____________________________________________________________ +There appears to be duplicated flags in your command. +Please kindly remove them to prevent any ambiguous action performed. +____________________________________________________________ + ____________________________________________________________ Delete all of your contacts? (y/n) ____________________________________________________________ diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index 49c900e2fc..05c57de392 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -96,6 +96,8 @@ ls rm 0 -e -te -tw y view 0 +add -n marcus -n lezaimun +edit 4 -g github -g guthib rm all y ls From 4dfc91e09b34cf56cdae3c1df8249177421640e6 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Wed, 27 Oct 2021 23:28:38 +0800 Subject: [PATCH 559/756] Update for checkstyle --- src/main/java/seedu/command/AddContactCommand.java | 1 + src/main/java/seedu/command/FailedCommand.java | 1 + src/main/java/seedu/command/ImportContactCommand.java | 1 + src/main/java/seedu/contact/ContactList.java | 1 + src/main/java/seedu/contact/DetailType.java | 1 + src/main/java/seedu/duke/Duke.java | 1 + src/main/java/seedu/parser/AddContactParser.java | 1 + src/main/java/seedu/parser/ContactDetails.java | 1 + src/main/java/seedu/parser/ContactParser.java | 1 + src/main/java/seedu/storage/ContactsDecoder.java | 1 + src/main/java/seedu/storage/Storage.java | 1 + 11 files changed, 11 insertions(+) diff --git a/src/main/java/seedu/command/AddContactCommand.java b/src/main/java/seedu/command/AddContactCommand.java index 1ee627466f..caddda004c 100644 --- a/src/main/java/seedu/command/AddContactCommand.java +++ b/src/main/java/seedu/command/AddContactCommand.java @@ -1,4 +1,5 @@ //@@author marcusbory + package seedu.command; import seedu.contact.Contact; diff --git a/src/main/java/seedu/command/FailedCommand.java b/src/main/java/seedu/command/FailedCommand.java index 21e297f4f4..fc9f818747 100644 --- a/src/main/java/seedu/command/FailedCommand.java +++ b/src/main/java/seedu/command/FailedCommand.java @@ -1,4 +1,5 @@ //@@author marcusbory + package seedu.command; import seedu.parser.FailedCommandType; diff --git a/src/main/java/seedu/command/ImportContactCommand.java b/src/main/java/seedu/command/ImportContactCommand.java index dfab9beb78..0225c6fd8a 100644 --- a/src/main/java/seedu/command/ImportContactCommand.java +++ b/src/main/java/seedu/command/ImportContactCommand.java @@ -1,4 +1,5 @@ //@@author marcusbory + package seedu.command; import seedu.contact.ContactList; diff --git a/src/main/java/seedu/contact/ContactList.java b/src/main/java/seedu/contact/ContactList.java index 2af77f5bdc..bbb2b767c9 100644 --- a/src/main/java/seedu/contact/ContactList.java +++ b/src/main/java/seedu/contact/ContactList.java @@ -1,4 +1,5 @@ //@@author marcusbory + package seedu.contact; import seedu.exception.InvalidFlagException; diff --git a/src/main/java/seedu/contact/DetailType.java b/src/main/java/seedu/contact/DetailType.java index 65be6b5bf2..9cfce5194a 100644 --- a/src/main/java/seedu/contact/DetailType.java +++ b/src/main/java/seedu/contact/DetailType.java @@ -1,4 +1,5 @@ //@@author marcusbory + package seedu.contact; /** diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index dec65a116c..3f4cf840d2 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -1,4 +1,5 @@ //@@author marcusbory + package seedu.duke; import seedu.command.Command; diff --git a/src/main/java/seedu/parser/AddContactParser.java b/src/main/java/seedu/parser/AddContactParser.java index c23f1b7b31..a230841e77 100644 --- a/src/main/java/seedu/parser/AddContactParser.java +++ b/src/main/java/seedu/parser/AddContactParser.java @@ -1,4 +1,5 @@ //@@author marcusbory + package seedu.parser; import seedu.exception.DuplicateDetailException; diff --git a/src/main/java/seedu/parser/ContactDetails.java b/src/main/java/seedu/parser/ContactDetails.java index 7d9e5c4be6..dc6daef66d 100644 --- a/src/main/java/seedu/parser/ContactDetails.java +++ b/src/main/java/seedu/parser/ContactDetails.java @@ -1,4 +1,5 @@ //@@author marcusbory + package seedu.parser; import seedu.contact.DetailType; diff --git a/src/main/java/seedu/parser/ContactParser.java b/src/main/java/seedu/parser/ContactParser.java index bbaba252b2..9bb772896c 100644 --- a/src/main/java/seedu/parser/ContactParser.java +++ b/src/main/java/seedu/parser/ContactParser.java @@ -1,4 +1,5 @@ //@@author marcusbory + package seedu.parser; import seedu.exception.DuplicateDetailException; diff --git a/src/main/java/seedu/storage/ContactsDecoder.java b/src/main/java/seedu/storage/ContactsDecoder.java index ed0a8597b3..434d5d6705 100644 --- a/src/main/java/seedu/storage/ContactsDecoder.java +++ b/src/main/java/seedu/storage/ContactsDecoder.java @@ -1,4 +1,5 @@ //@@author marcusbory + package seedu.storage; import seedu.contact.Contact; diff --git a/src/main/java/seedu/storage/Storage.java b/src/main/java/seedu/storage/Storage.java index dcdf01606a..c4893d9170 100644 --- a/src/main/java/seedu/storage/Storage.java +++ b/src/main/java/seedu/storage/Storage.java @@ -1,4 +1,5 @@ //@@author marcusbory + package seedu.storage; import seedu.contact.Contact; From d75772c96efde0d14dd003286b972c95f4d35285 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Fri, 29 Oct 2021 01:46:57 +0800 Subject: [PATCH 560/756] Enable emojis --- docs/_config.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/_config.yml b/docs/_config.yml index c741881743..213386adf1 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -1 +1,3 @@ -theme: jekyll-theme-slate \ No newline at end of file +theme: jekyll-theme-slate +plugins: + - jemoji From 366b9cf1816d5aa8017055aad2c1d2e72a4a9784 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Fri, 29 Oct 2021 01:47:47 +0800 Subject: [PATCH 561/756] Update introduction of UG --- docs/UserGuide.md | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index dfd1bf7594..7a09bfdd01 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -1,15 +1,20 @@ -# User Guide +# ConTech User Guide ## Introduction -**ConTech** is a **Command Line Interface (CLI) application for managing computing-related contacts**. +**ConTech** (pronounced as Contact) is a **Command Line Interface (CLI) application for managing computing-related +contacts**. Specially designed to be optimised for use on the CLI, **ConTech** allows you to seamlessly **add**, **edit**, +**view**, **list**, **search**, and **import** your contacts. + If you are a computing professional that often uses the command line for work, **ConTech** can get your contact management tasks done faster than any traditional GUI app. -With our various [features](#features) such as `add`, `edit`, `view`, and other commands, you can easily perform such -actions on your **ConTech** Book in a quick and efficient manner. **ConTech** is optimised for computing-related contacts -such as saving a colleague's GitHub username or even mass-loading from a list of contacts. **ConTech** aims to improve your -efficiency at work by cutting down the time required to look up for various usernames when working with colleagues. +This guide serves to introduce our various [features](#features) such as `add`, `edit`, `view`, and other commands, +and guide you to easily manage your **ConTech** Book. + +**ConTech** aims to improve your efficiency at work, be it by cutting down the time required to look up for various +usernames when working with colleagues, or by importing hundreds of contacts with just one simple command. +
    * **[Quick Start](#start)** * **[Features](#features)** From 197719a55c63992fea7a2288ae92fbe15bd35842 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Fri, 29 Oct 2021 01:48:04 +0800 Subject: [PATCH 562/756] Add section for how to use UG --- docs/UserGuide.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 7a09bfdd01..396f004b9d 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -16,6 +16,15 @@ and guide you to easily manage your **ConTech** Book. usernames when working with colleagues, or by importing hundreds of contacts with just one simple command.
    +## How to use the User Guide + +To make full use of the user guide, we have provided a table of contents with their hyperlinks. This would allow you +to quickly access portions of the guide you require. + +However, for first time users, you are highly encouraged to go through the user guide in order, from the top to +bottom. This is because the guide is also written in a specific order to allow you to maximise your understanding +when learning how to use **ConTech**. + * **[Quick Start](#start)** * **[Features](#features)** * **[Contact flags : `-flag`](#flag)** From 112e35af7e7303f8a51f9abfd0d2930127096581 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Fri, 29 Oct 2021 01:48:43 +0800 Subject: [PATCH 563/756] Move `help` command to bottom --- docs/UserGuide.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 396f004b9d..9cb5cf4b1c 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -28,7 +28,6 @@ when learning how to use **ConTech**. * **[Quick Start](#start)** * **[Features](#features)** * **[Contact flags : `-flag`](#flag)** - * **[Viewing help : `help`](#help)** * **[Adding a contact : `add`](#add)** * **[Listing all contacts : `ls`](#list)** * **[Viewing a contact : `view`](#view)** @@ -37,8 +36,8 @@ when learning how to use **ConTech**. * **[Editing a contact : `edit`](#edit)** * **[Searching for a contact : `search`](#search)** * **[Importing a contact : `import`](#import)** + * **[Viewing help : `help`](#help)** * **[Exiting the program : `exit`](#exit)** - * **[FAQ](#faq)** * **[Command Summary](#summary)** From b0153ad3a472291f8c97ded30113ca0c7e256187 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Fri, 29 Oct 2021 01:50:00 +0800 Subject: [PATCH 564/756] Move contact flags portion to before features --- docs/UserGuide.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 9cb5cf4b1c..4cab7e2daf 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -26,8 +26,8 @@ bottom. This is because the guide is also written in a specific order to allow y when learning how to use **ConTech**. * **[Quick Start](#start)** +* **[Contact flags : `-flag`](#flag)** * **[Features](#features)** - * **[Contact flags : `-flag`](#flag)** * **[Adding a contact : `add`](#add)** * **[Listing all contacts : `ls`](#list)** * **[Viewing a contact : `view`](#view)** @@ -66,10 +66,11 @@ when learning how to use **ConTech**. ### Contact flags: `-flag` -When using commands such as `add`,`edit` and `search`, the user can specify details with the use of flags in the form `-FLAG`. +When using commands such as `add`,`edit` and `search`, you can specify details with the use of flags in the form: +`-flag`. -ConTech currently supports six `FLAGS` and has in built checkers to check if the format of the `DETAILS` fulfill -the fields. These `flags` include: +**ConTech** currently supports six `flags` and has in built checkers to check if the format of the `details` are +fulfilled. These `flags` include: - `-n`: for your contact's name - `-g`: for your contact's GitHub account username - `-l`: for your contact's LinkedIn handle From 02d051175382639cec21f03ad53c90b3d6740b32 Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Fri, 29 Oct 2021 01:51:00 +0800 Subject: [PATCH 565/756] Introduce common notations section before features --- docs/UserGuide.md | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 4cab7e2daf..83cfea2654 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -25,8 +25,11 @@ However, for first time users, you are highly encouraged to go through the user bottom. This is because the guide is also written in a specific order to allow you to maximise your understanding when learning how to use **ConTech**. +### Table Of Contents + * **[Quick Start](#start)** * **[Contact flags : `-flag`](#flag)** +* **[Common notations used](#notations)** * **[Features](#features)** * **[Adding a contact : `add`](#add)** * **[Listing all contacts : `ls`](#list)** @@ -61,8 +64,12 @@ when learning how to use **ConTech**. 1. Refer to the [Features](#features) below for details of each command. - -## Features +Before moving on to the features of **ConTech**, we have prepared some documentation regarding some common notations +that will be used throughout this guide. + +However, if you would like to, you can refer to the [Features](#features) below for details of each feature and +its respective command. + ### Contact flags: `-flag` @@ -78,6 +85,27 @@ fulfilled. These `flags` include: - `-tw`: for your contact's Twitter handle - `-e`: for your contact's email address + +### Common notations used +Throughout the user guide, you will find the following notations: +- Words in `UPPER_CASE` are meant to be parameters that you can supply to your commands. + - e.g. When adding a contact, in the command `add -n NAME -g GITHUB`, `NAME` and `GITHUB` are parameters which you + can specify, such as `add -n Le Zong -g lezongmun`. + - e.g. When viewing a contact's details, in the command `view INDEX`, `INDEX` is a number (integer) representing + your contact's index in the **ConTech** book which you can specify, such as `view 2`. +- Items in curly braces `{}` are optional. +- Items in angle braces `<>` are mandatory. + - e.g. When specified in the format `<-n> {-g }`, it means that: + - The `-n` flag and `NAME` detail are mandatory fields, without which the command would not execute. + - The `-g` flag is optional, however, if used, a `GITHUB` detail would have to be specified. +- Items specified with a pipe `|` denote an either-or field. + - e.g. For `{-n | -g | -l | -te | -tw | -e}`, only **up to** one `flag` is allowed, but there are **six** choices. + +Do familiarise yourself with these notations to better utilise the user guide. +
    + + +## Features ### Adding a contact: `add` From 7d24a4ab85d056158f0f1017dd167f7768c040ba Mon Sep 17 00:00:00 2001 From: Marcus Ong <58963565+marcusbory@users.noreply.github.com> Date: Fri, 29 Oct 2021 01:51:16 +0800 Subject: [PATCH 566/756] Update quick start with extra notes --- docs/UserGuide.md | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 83cfea2654..c99b6ec2a6 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -44,15 +44,20 @@ when learning how to use **ConTech**. * **[FAQ](#faq)** * **[Command Summary](#summary)** +
    + ## Quick Start +This section aims to get you started with using **ConTech**. + 1. Ensure that you have Java `11` or above installed in your Computer. -1. Download the latest version of `contech.jar` from [here](https://github.com/AY2122S1-CS2113T-T09-1/tp/releases). -1. Copy the `contech.jar` file to the folder you want to use as the _home folder_ for **ConTech**. -1. Open your desired _Command Line Interface_ from the folder with `contech.jar` and enter the following code: +2. Download the latest version of `contech.jar` from [here](https://github.com/AY2122S1-CS2113T-T09-1/tp/releases). +3. Copy the `contech.jar` file to the folder you want to use as the _home folder_ for **ConTech**. +4. Open your desired _Command Line Interface_ from the folder with `contech.jar` and enter the following code: `java -jar contech.jar`. -1. Type a command in the command box and press _Enter_ to execute it. e.g., typing `help` and pressing _Enter_ will +5. As a first time user, you would be required to type in your personal details. +6. Type a command in the command box and press _Enter_ to execute it. e.g., typing `help` and pressing _Enter_ will display the help message.
    Some example commands you can try: * `add -n Alex Lee -g alexlee -e alex.lee@contech.sg -te alexl33`: Adds a contact named `Alex Lee` @@ -61,8 +66,11 @@ when learning how to use **ConTech**. * `view 1`: Displays all the details of the contact at index `1`. * `rm 1`: Deletes the contact at index `1` in the list. * `exit`: Exits the program. + +If you have reached this step without any issues, congratulations! You have successfully set up **ConTech**. -1. Refer to the [Features](#features) below for details of each command. +