From 7189ddaba55f308e3f9eb782dabfc335c3da1574 Mon Sep 17 00:00:00 2001 From: tingxuanp Date: Mon, 14 Oct 2024 13:06:36 +0800 Subject: [PATCH 01/33] Update Find command to parse name prefix --- .../address/logic/commands/FindCommand.java | 51 ++----------- .../logic/commands/FindNameCommand.java | 74 +++++++++++++++++++ .../logic/parser/FindCommandParser.java | 33 ++++++++- .../logic/commands/FindCommandTest.java | 30 ++++---- .../logic/parser/AddressBookParserTest.java | 7 +- .../logic/parser/FindCommandParserTest.java | 18 +++-- 6 files changed, 144 insertions(+), 69 deletions(-) create mode 100644 src/main/java/seedu/address/logic/commands/FindNameCommand.java diff --git a/src/main/java/seedu/address/logic/commands/FindCommand.java b/src/main/java/seedu/address/logic/commands/FindCommand.java index c8d2140ff54..b0106b5d83e 100644 --- a/src/main/java/seedu/address/logic/commands/FindCommand.java +++ b/src/main/java/seedu/address/logic/commands/FindCommand.java @@ -1,16 +1,11 @@ package seedu.address.logic.commands; -import static java.util.Objects.requireNonNull; - -import seedu.address.commons.util.ToStringBuilder; -import seedu.address.model.Model; -import seedu.address.model.person.NameContainsKeywordsPredicate; /** * Finds and lists all persons in address book whose name contains any of the argument keywords. * Keyword matching is case-insensitive and allows partial matching. */ -public class FindCommand extends Command { +public abstract class FindCommand extends Command { public static final String COMMAND_WORD = "find"; @@ -23,43 +18,11 @@ public class FindCommand extends Command { public static final String MESSAGE_FIND_PERSON_UNSUCCESSFUL = "No contacts found."; - private final NameContainsKeywordsPredicate predicate; - - public FindCommand(NameContainsKeywordsPredicate predicate) { - this.predicate = predicate; - } - - @Override - public CommandResult execute(Model model) { - requireNonNull(model); - model.updateFilteredPersonList(predicate); - - if (!model.getFilteredPersonList().isEmpty()) { - return new CommandResult(String.format(MESSAGE_FIND_PERSON_SUCCESS, predicate.getDisplayString())); - } else { - return new CommandResult(MESSAGE_FIND_PERSON_UNSUCCESSFUL); - } - } - - @Override - public boolean equals(Object other) { - if (other == this) { - return true; - } - - // instanceof handles nulls - if (!(other instanceof FindCommand)) { - return false; - } - - FindCommand otherFindCommand = (FindCommand) other; - return predicate.equals(otherFindCommand.predicate); - } - @Override - public String toString() { - return new ToStringBuilder(this) - .add("predicate", predicate) - .toString(); - } + //@Override + //public String toString() { + // return new ToStringBuilder(this) + // .add("predicate", predicate) + // .toString(); + //} } diff --git a/src/main/java/seedu/address/logic/commands/FindNameCommand.java b/src/main/java/seedu/address/logic/commands/FindNameCommand.java new file mode 100644 index 00000000000..13c579a7651 --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/FindNameCommand.java @@ -0,0 +1,74 @@ +package seedu.address.logic.commands; + +import static java.util.Objects.requireNonNull; + +import seedu.address.commons.util.ToStringBuilder; +import seedu.address.model.Model; +import seedu.address.model.person.NameContainsKeywordsPredicate; + +/** + * Finds and lists all persons in address book whose name contains any of the argument keywords. + * Keyword matching is case-insensitive and allows partial matching. + */ +public class FindNameCommand extends FindCommand { + + public static final String COMMAND_WORD = "find"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all persons whose names contain any of " + + "the specified keywords (case-insensitive) and displays them as a list with index numbers.\n" + + "Parameters: KEYWORD [MORE_KEYWORDS]...\n" + + "Example: " + COMMAND_WORD + " alice bob charlie"; + + public static final String MESSAGE_FIND_NAME_PERSON_SUCCESS = "Search for \"%s\" by name was successful. " + + " Showing results:"; + + public static final String MESSAGE_FIND_NAME_PERSON_UNSUCCESSFUL = "No contacts found."; + + private final NameContainsKeywordsPredicate predicate; + + /** + * Command to filter contacts in WedLinker based on names using partial matching. + * This command allows users to search for contacts by providing one or more keywords. + * The search is case-insensitive and matches any part of the contact names. + * + * @param predicate Keywords used to filter contacts by name. + */ + public FindNameCommand(NameContainsKeywordsPredicate predicate) { + super(); + this.predicate = predicate; + } + + @Override + public CommandResult execute(Model model) { + requireNonNull(model); + model.updateFilteredPersonList(predicate); + + if (!model.getFilteredPersonList().isEmpty()) { + return new CommandResult(String.format(MESSAGE_FIND_NAME_PERSON_SUCCESS, predicate.getDisplayString())); + } else { + return new CommandResult(MESSAGE_FIND_NAME_PERSON_UNSUCCESSFUL); + } + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + // instanceof handles nulls + if (!(other instanceof FindNameCommand)) { + return false; + } + + FindNameCommand otherFindCommand = (FindNameCommand) other; + return predicate.equals(otherFindCommand.predicate); + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .add("predicate", predicate) + .toString(); + } +} diff --git a/src/main/java/seedu/address/logic/parser/FindCommandParser.java b/src/main/java/seedu/address/logic/parser/FindCommandParser.java index 2867bde857b..81d480a76db 100644 --- a/src/main/java/seedu/address/logic/parser/FindCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/FindCommandParser.java @@ -1,10 +1,18 @@ package seedu.address.logic.parser; +import static java.util.Objects.requireNonNull; import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS; +import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL; +import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; +import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; +import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; import java.util.Arrays; +import java.util.List; import seedu.address.logic.commands.FindCommand; +import seedu.address.logic.commands.FindNameCommand; import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.person.NameContainsKeywordsPredicate; @@ -13,21 +21,42 @@ */ public class FindCommandParser implements Parser { + + + /** * Parses the given {@code String} of arguments in the context of the FindCommand * and returns a FindCommand object for execution. * @throws ParseException if the user input does not conform the expected format */ public FindCommand parse(String args) throws ParseException { + requireNonNull(args); + ArgumentMultimap argMultimap = + ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TAG); + + argMultimap.verifyNoDuplicatePrefixesFor(PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS); + + String trimmedArgs = args.trim(); if (trimmedArgs.isEmpty()) { throw new ParseException( String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE)); } - String[] nameKeywords = trimmedArgs.split("\\s+"); + // Check for the presence of any prefix + boolean hasNamePrefix = argMultimap.getValue(PREFIX_NAME).isPresent(); + boolean hasPhonePrefix = argMultimap.getValue(PREFIX_PHONE).isPresent(); + boolean hasEmailPrefix = argMultimap.getValue(PREFIX_EMAIL).isPresent(); + boolean hasAddressPrefix = argMultimap.getValue(PREFIX_ADDRESS).isPresent(); + + if (hasNamePrefix) { + String nameInput = argMultimap.getValue(PREFIX_NAME).get().trim(); // Get the actual name input + List nameKeywords = Arrays.asList(nameInput.split("\\s+")); + return new FindNameCommand(new NameContainsKeywordsPredicate((nameKeywords))); + } - return new FindCommand(new NameContainsKeywordsPredicate(Arrays.asList(nameKeywords))); + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE)); } } + diff --git a/src/test/java/seedu/address/logic/commands/FindCommandTest.java b/src/test/java/seedu/address/logic/commands/FindCommandTest.java index 10ceb7effd4..d58f128bd98 100644 --- a/src/test/java/seedu/address/logic/commands/FindCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/FindCommandTest.java @@ -4,8 +4,8 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; -import static seedu.address.logic.commands.FindCommand.MESSAGE_FIND_PERSON_SUCCESS; import static seedu.address.logic.commands.FindCommand.MESSAGE_FIND_PERSON_UNSUCCESSFUL; +import static seedu.address.logic.commands.FindNameCommand.MESSAGE_FIND_NAME_PERSON_SUCCESS; import static seedu.address.testutil.TypicalPersons.ALICE; import static seedu.address.testutil.TypicalPersons.BENSON; import static seedu.address.testutil.TypicalPersons.CARL; @@ -39,14 +39,14 @@ public void equals() { NameContainsKeywordsPredicate secondPredicate = new NameContainsKeywordsPredicate(Collections.singletonList("second")); - FindCommand findFirstCommand = new FindCommand(firstPredicate); - FindCommand findSecondCommand = new FindCommand(secondPredicate); + FindNameCommand findFirstCommand = new FindNameCommand(firstPredicate); + FindNameCommand findSecondCommand = new FindNameCommand(secondPredicate); // same object -> returns true assertTrue(findFirstCommand.equals(findFirstCommand)); // same values -> returns true - FindCommand findFirstCommandCopy = new FindCommand(firstPredicate); + FindCommand findFirstCommandCopy = new FindNameCommand(firstPredicate); assertTrue(findFirstCommand.equals(findFirstCommandCopy)); // different types -> returns false @@ -63,7 +63,7 @@ public void equals() { public void execute_zeroKeywords_noPersonFound() { String expectedMessage = MESSAGE_FIND_PERSON_UNSUCCESSFUL; NameContainsKeywordsPredicate predicate = preparePredicate(" "); - FindCommand command = new FindCommand(predicate); + FindNameCommand command = new FindNameCommand(predicate); expectedModel.updateFilteredPersonList(predicate); assertCommandSuccess(command, model, expectedMessage, expectedModel); assertEquals(Collections.emptyList(), model.getFilteredPersonList()); @@ -72,8 +72,8 @@ public void execute_zeroKeywords_noPersonFound() { @Test public void execute_multipleKeywords_multiplePersonsFound() { NameContainsKeywordsPredicate predicate = preparePredicate("Kurz Elle Kunz"); - String expectedMessage = String.format(MESSAGE_FIND_PERSON_SUCCESS, predicate.getDisplayString()); - FindCommand command = new FindCommand(predicate); + String expectedMessage = String.format(MESSAGE_FIND_NAME_PERSON_SUCCESS, predicate.getDisplayString()); + FindNameCommand command = new FindNameCommand(predicate); expectedModel.updateFilteredPersonList(predicate); assertCommandSuccess(command, model, expectedMessage, expectedModel); assertEquals(Arrays.asList(CARL, ELLE, FIONA), model.getFilteredPersonList()); @@ -82,8 +82,8 @@ public void execute_multipleKeywords_multiplePersonsFound() { @Test public void execute_partialMatchKeyword_correctPersonFound() { NameContainsKeywordsPredicate predicate = preparePredicate("ell"); - String expectedMessage = String.format(MESSAGE_FIND_PERSON_SUCCESS, predicate.getDisplayString()); - FindCommand command = new FindCommand(predicate); + String expectedMessage = String.format(MESSAGE_FIND_NAME_PERSON_SUCCESS, predicate.getDisplayString()); + FindNameCommand command = new FindNameCommand(predicate); expectedModel.updateFilteredPersonList(predicate); assertCommandSuccess(command, model, expectedMessage, expectedModel); assertEquals(Arrays.asList(ELLE), model.getFilteredPersonList()); @@ -92,8 +92,8 @@ public void execute_partialMatchKeyword_correctPersonFound() { @Test public void execute_partialMatchKeyword_multiplePersonsFound() { NameContainsKeywordsPredicate predicate = preparePredicate("e"); - String expectedMessage = String.format(MESSAGE_FIND_PERSON_SUCCESS, predicate.getDisplayString()); - FindCommand command = new FindCommand(predicate); + String expectedMessage = String.format(MESSAGE_FIND_NAME_PERSON_SUCCESS, predicate.getDisplayString()); + FindNameCommand command = new FindNameCommand(predicate); expectedModel.updateFilteredPersonList(predicate); assertCommandSuccess(command, model, expectedMessage, expectedModel); assertEquals(Arrays.asList(ALICE, BENSON, DANIEL, ELLE, GEORGE), model.getFilteredPersonList()); @@ -103,7 +103,7 @@ public void execute_partialMatchKeyword_multiplePersonsFound() { public void execute_absentPartialMatchKeyword_noPersonFound() { NameContainsKeywordsPredicate predicate = preparePredicate("x"); String expectedMessage = MESSAGE_FIND_PERSON_UNSUCCESSFUL; - FindCommand command = new FindCommand(predicate); + FindNameCommand command = new FindNameCommand(predicate); expectedModel.updateFilteredPersonList(predicate); assertCommandSuccess(command, model, expectedMessage, expectedModel); assertEquals(Collections.emptyList(), model.getFilteredPersonList()); @@ -112,9 +112,9 @@ public void execute_absentPartialMatchKeyword_noPersonFound() { @Test public void toStringMethod() { NameContainsKeywordsPredicate predicate = new NameContainsKeywordsPredicate(Arrays.asList("keyword")); - FindCommand findCommand = new FindCommand(predicate); - String expected = FindCommand.class.getCanonicalName() + "{predicate=" + predicate + "}"; - assertEquals(expected, findCommand.toString()); + FindNameCommand findNameCommand = new FindNameCommand(predicate); + String expected = FindNameCommand.class.getCanonicalName() + "{predicate=" + predicate + "}"; + assertEquals(expected, findNameCommand.toString()); } /** diff --git a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java b/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java index 0a99011f4dc..ffe05aca784 100644 --- a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java +++ b/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java @@ -22,6 +22,7 @@ import seedu.address.logic.commands.ExitCommand; import seedu.address.logic.commands.FilterCommand; import seedu.address.logic.commands.FindCommand; +import seedu.address.logic.commands.FindNameCommand; import seedu.address.logic.commands.HelpCommand; import seedu.address.logic.commands.ListCommand; import seedu.address.logic.commands.TagCommand; @@ -76,9 +77,9 @@ public void parseCommand_exit() throws Exception { @Test public void parseCommand_find() throws Exception { List keywords = Arrays.asList("foo", "bar", "baz"); - FindCommand command = (FindCommand) parser.parseCommand( - FindCommand.COMMAND_WORD + " " + keywords.stream().collect(Collectors.joining(" "))); - assertEquals(new FindCommand(new NameContainsKeywordsPredicate(keywords)), command); + FindNameCommand command = (FindNameCommand) parser.parseCommand( + FindCommand.COMMAND_WORD + " n/" + keywords.stream().collect(Collectors.joining(" "))); + assertEquals(new FindNameCommand(new NameContainsKeywordsPredicate(keywords)), command); } @Test diff --git a/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java b/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java index d92e64d12f9..9e9d0fde8db 100644 --- a/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java @@ -9,6 +9,7 @@ import org.junit.jupiter.api.Test; import seedu.address.logic.commands.FindCommand; +import seedu.address.logic.commands.FindNameCommand; import seedu.address.model.person.NameContainsKeywordsPredicate; public class FindCommandParserTest { @@ -17,18 +18,25 @@ public class FindCommandParserTest { @Test public void parse_emptyArg_throwsParseException() { - assertParseFailure(parser, " ", String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE)); + assertParseFailure(parser, " ", + String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE)); + } + + @Test + public void parse_missingNamePrefix_throwsParseException() { + assertParseFailure(parser, "find amy", + String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE)); } @Test public void parse_validArgs_returnsFindCommand() { // no leading and trailing whitespaces - FindCommand expectedFindCommand = - new FindCommand(new NameContainsKeywordsPredicate(Arrays.asList("Alice", "Bob"))); - assertParseSuccess(parser, "Alice Bob", expectedFindCommand); + FindNameCommand expectedFindCommand = + new FindNameCommand(new NameContainsKeywordsPredicate(Arrays.asList("Alice", "Bob"))); + assertParseSuccess(parser, "find n/Alice Bob", expectedFindCommand); // multiple whitespaces between keywords - assertParseSuccess(parser, " \n Alice \n \t Bob \t", expectedFindCommand); + assertParseSuccess(parser, "find n/ \n Alice \n \t Bob \t", expectedFindCommand); } } From cd4d46e51c563ffc8d03d4f626d228585fb7f01f Mon Sep 17 00:00:00 2001 From: tingxuanp Date: Mon, 14 Oct 2024 16:13:33 +0800 Subject: [PATCH 02/33] Implement search by phone number --- .../address/commons/util/StringUtil.java | 19 ++++++ .../logic/commands/FindNameCommand.java | 9 +-- .../logic/commands/FindPhoneCommand.java | 68 +++++++++++++++++++ .../logic/parser/FindCommandParser.java | 13 ++-- .../PhoneContainsKeywordsPredicate.java | 48 +++++++++++++ ...mandTest.java => FindNameCommandTest.java} | 2 +- 6 files changed, 146 insertions(+), 13 deletions(-) create mode 100644 src/main/java/seedu/address/logic/commands/FindPhoneCommand.java create mode 100644 src/main/java/seedu/address/model/person/PhoneContainsKeywordsPredicate.java rename src/test/java/seedu/address/logic/commands/{FindCommandTest.java => FindNameCommandTest.java} (99%) diff --git a/src/main/java/seedu/address/commons/util/StringUtil.java b/src/main/java/seedu/address/commons/util/StringUtil.java index 8805b3f5a2a..fe10250fcfc 100644 --- a/src/main/java/seedu/address/commons/util/StringUtil.java +++ b/src/main/java/seedu/address/commons/util/StringUtil.java @@ -60,6 +60,25 @@ public static boolean containsPartialWordIgnoreCase(String sentence, String word return preppedSentence.contains(preppedWord); } + /** + * Returns true if the {@code phoneNumber} contains the {@code searchNumber}. + * Only a partial match is required. + *
examples:
+     *       containsPhoneNumber("99209378", "92") == true // partial match
+     *       containsPhoneNumber("99209378", "9378") == true // partial match
+     *       containsPhoneNumber("82810284", "82810284") == true // full match
+     *       containsPhoneNumber("99209378", "86") == false // no partial match with number
+     *       
+ * @param phoneNumber cannot be null + * @param searchNumber cannot be null, cannot be empty + */ + public static boolean containsPhoneNumber(String phoneNumber, String searchNumber) { + requireNonNull(phoneNumber); + requireNonNull(searchNumber); + checkArgument(!searchNumber.isEmpty(), "Phone number parameter cannot be empty"); + return phoneNumber.toLowerCase().contains(searchNumber.toLowerCase()); + } + /** * Returns a detailed message of the t, including the stack trace. */ diff --git a/src/main/java/seedu/address/logic/commands/FindNameCommand.java b/src/main/java/seedu/address/logic/commands/FindNameCommand.java index 13c579a7651..a62626a94b8 100644 --- a/src/main/java/seedu/address/logic/commands/FindNameCommand.java +++ b/src/main/java/seedu/address/logic/commands/FindNameCommand.java @@ -12,14 +12,7 @@ */ public class FindNameCommand extends FindCommand { - public static final String COMMAND_WORD = "find"; - - public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all persons whose names contain any of " - + "the specified keywords (case-insensitive) and displays them as a list with index numbers.\n" - + "Parameters: KEYWORD [MORE_KEYWORDS]...\n" - + "Example: " + COMMAND_WORD + " alice bob charlie"; - - public static final String MESSAGE_FIND_NAME_PERSON_SUCCESS = "Search for \"%s\" by name was successful. " + public static final String MESSAGE_FIND_NAME_PERSON_SUCCESS = "Search for name containing \"%s\" was successful. " + " Showing results:"; public static final String MESSAGE_FIND_NAME_PERSON_UNSUCCESSFUL = "No contacts found."; diff --git a/src/main/java/seedu/address/logic/commands/FindPhoneCommand.java b/src/main/java/seedu/address/logic/commands/FindPhoneCommand.java new file mode 100644 index 00000000000..90ea60e6023 --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/FindPhoneCommand.java @@ -0,0 +1,68 @@ +package seedu.address.logic.commands; + +import static java.util.Objects.requireNonNull; + +import seedu.address.commons.util.ToStringBuilder; +import seedu.address.model.Model; +import seedu.address.model.person.PhoneContainsKeywordsPredicate; + +/** + * Finds and lists all persons in address book whose phone number contains any of the argument keywords. + * Keyword matching allows partial matching. + */ +public class FindPhoneCommand extends FindCommand { + + public static final String MESSAGE_FIND_PHONE_PERSON_SUCCESS = "Search for phone number containing \"%s\" " + + " was successful. Showing results:"; + + public static final String MESSAGE_FIND_PHONE_PERSON_UNSUCCESSFUL = "No contacts found."; + + private final PhoneContainsKeywordsPredicate predicate; + + /** + * Command to filter contacts in WedLinker based on phone numbers. + * The search matches any parts of the phone numbers. + * + * @param predicate Keywords used to filter contacts by their phone number. + */ + public FindPhoneCommand(PhoneContainsKeywordsPredicate predicate) { + super(); + this.predicate = predicate; + } + + @Override + public CommandResult execute(Model model) { + requireNonNull(model); + model.updateFilteredPersonList(predicate); + + if (!model.getFilteredPersonList().isEmpty()) { + return new CommandResult(String.format(MESSAGE_FIND_PHONE_PERSON_SUCCESS, predicate.getDisplayString())); + } else { + return new CommandResult(MESSAGE_FIND_PHONE_PERSON_UNSUCCESSFUL); + } + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + // instanceof handles nulls + if (!(other instanceof FindPhoneCommand)) { + return false; + } + + FindPhoneCommand otherFindCommand = (FindPhoneCommand) other; + return predicate.equals(otherFindCommand.predicate); + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .add("predicate", predicate) + .toString(); + } + + +} diff --git a/src/main/java/seedu/address/logic/parser/FindCommandParser.java b/src/main/java/seedu/address/logic/parser/FindCommandParser.java index 81d480a76db..7cfad641c40 100644 --- a/src/main/java/seedu/address/logic/parser/FindCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/FindCommandParser.java @@ -13,17 +13,16 @@ import seedu.address.logic.commands.FindCommand; import seedu.address.logic.commands.FindNameCommand; +import seedu.address.logic.commands.FindPhoneCommand; import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.person.NameContainsKeywordsPredicate; +import seedu.address.model.person.PhoneContainsKeywordsPredicate; /** * Parses input arguments and creates a new FindCommand object */ public class FindCommandParser implements Parser { - - - /** * Parses the given {@code String} of arguments in the context of the FindCommand * and returns a FindCommand object for execution. @@ -52,7 +51,13 @@ public FindCommand parse(String args) throws ParseException { if (hasNamePrefix) { String nameInput = argMultimap.getValue(PREFIX_NAME).get().trim(); // Get the actual name input List nameKeywords = Arrays.asList(nameInput.split("\\s+")); - return new FindNameCommand(new NameContainsKeywordsPredicate((nameKeywords))); + return new FindNameCommand(new NameContainsKeywordsPredicate(nameKeywords)); + } + + if (hasPhonePrefix) { + String phoneNumberInput = argMultimap.getValue(PREFIX_PHONE).get().trim(); // Get the actual phone input + List phoneKeywords = Arrays.asList(phoneNumberInput.split("\\s+")); + return new FindPhoneCommand(new PhoneContainsKeywordsPredicate(phoneKeywords)); } throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE)); diff --git a/src/main/java/seedu/address/model/person/PhoneContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/person/PhoneContainsKeywordsPredicate.java new file mode 100644 index 00000000000..3a4505419e4 --- /dev/null +++ b/src/main/java/seedu/address/model/person/PhoneContainsKeywordsPredicate.java @@ -0,0 +1,48 @@ +package seedu.address.model.person; + +import java.util.List; +import java.util.function.Predicate; + +import seedu.address.commons.util.StringUtil; +import seedu.address.commons.util.ToStringBuilder; + +/** + * Tests that a {@code Person}'s {@code Phone} matches any of the keywords given. + */ +public class PhoneContainsKeywordsPredicate implements Predicate { + private final List keywords; + + public PhoneContainsKeywordsPredicate(List keywords) { + this.keywords = keywords; + } + + @Override + public boolean test(Person person) { + return keywords.stream() + .anyMatch(keyword -> StringUtil.containsPhoneNumber(person.getPhone().value, keyword)); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + // instanceof handles nulls + if (!(other instanceof PhoneContainsKeywordsPredicate)) { + return false; + } + + PhoneContainsKeywordsPredicate otherNameContainsKeywordsPredicate = (PhoneContainsKeywordsPredicate) other; + return keywords.equals(otherNameContainsKeywordsPredicate.keywords); + } + + @Override + public String toString() { + return new ToStringBuilder(this).add("keywords", keywords).toString(); + } + + public String getDisplayString() { + return String.join(", ", keywords); + } +} diff --git a/src/test/java/seedu/address/logic/commands/FindCommandTest.java b/src/test/java/seedu/address/logic/commands/FindNameCommandTest.java similarity index 99% rename from src/test/java/seedu/address/logic/commands/FindCommandTest.java rename to src/test/java/seedu/address/logic/commands/FindNameCommandTest.java index d58f128bd98..6098608452b 100644 --- a/src/test/java/seedu/address/logic/commands/FindCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/FindNameCommandTest.java @@ -28,7 +28,7 @@ /** * Contains integration tests (interaction with the Model) for {@code FindCommand}. */ -public class FindCommandTest { +public class FindNameCommandTest { private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); private Model expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs()); From 18db59ec479197c8cb8602cda748765dcf7e2cb2 Mon Sep 17 00:00:00 2001 From: tingxuanp Date: Mon, 14 Oct 2024 16:25:34 +0800 Subject: [PATCH 03/33] Implement search by address --- .../logic/commands/FindAddressCommand.java | 67 +++++++++++++++++++ .../logic/parser/FindCommandParser.java | 8 +++ .../AddressContainsKeywordsPredicate.java | 48 +++++++++++++ 3 files changed, 123 insertions(+) create mode 100644 src/main/java/seedu/address/logic/commands/FindAddressCommand.java create mode 100644 src/main/java/seedu/address/model/person/AddressContainsKeywordsPredicate.java diff --git a/src/main/java/seedu/address/logic/commands/FindAddressCommand.java b/src/main/java/seedu/address/logic/commands/FindAddressCommand.java new file mode 100644 index 00000000000..93d89a1cbe8 --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/FindAddressCommand.java @@ -0,0 +1,67 @@ +package seedu.address.logic.commands; + +import static java.util.Objects.requireNonNull; + +import seedu.address.commons.util.ToStringBuilder; +import seedu.address.model.Model; +import seedu.address.model.person.AddressContainsKeywordsPredicate; + +/** + * Finds and lists all persons in address book whose address contains any of the argument keywords. + * Keyword matching is case-insensitive and allows partial matching. + */ +public class FindAddressCommand extends FindCommand { + + public static final String MESSAGE_FIND_ADDRESS_PERSON_SUCCESS = "Search for address containing \"%s\" " + + " was successful. Showing results:"; + + public static final String MESSAGE_FIND_ADDRESS_PERSON_UNSUCCESSFUL = "No contacts found."; + + private final AddressContainsKeywordsPredicate predicate; + + /** + * Command to filter contacts in WedLinker based on phone numbers. + * The search matches any parts of the phone numbers. + * + * @param predicate Keywords used to filter contacts by their phone number. + */ + public FindAddressCommand(AddressContainsKeywordsPredicate predicate) { + super(); + this.predicate = predicate; + } + + @Override + public CommandResult execute(Model model) { + requireNonNull(model); + model.updateFilteredPersonList(predicate); + + if (!model.getFilteredPersonList().isEmpty()) { + return new CommandResult(String.format(MESSAGE_FIND_ADDRESS_PERSON_SUCCESS, predicate.getDisplayString())); + } else { + return new CommandResult(MESSAGE_FIND_ADDRESS_PERSON_UNSUCCESSFUL); + } + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + // instanceof handles nulls + if (!(other instanceof FindAddressCommand)) { + return false; + } + + FindAddressCommand otherFindCommand = (FindAddressCommand) other; + return predicate.equals(otherFindCommand.predicate); + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .add("predicate", predicate) + .toString(); + } + +} diff --git a/src/main/java/seedu/address/logic/parser/FindCommandParser.java b/src/main/java/seedu/address/logic/parser/FindCommandParser.java index 7cfad641c40..f03db9fb28b 100644 --- a/src/main/java/seedu/address/logic/parser/FindCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/FindCommandParser.java @@ -11,10 +11,12 @@ import java.util.Arrays; import java.util.List; +import seedu.address.logic.commands.FindAddressCommand; import seedu.address.logic.commands.FindCommand; import seedu.address.logic.commands.FindNameCommand; import seedu.address.logic.commands.FindPhoneCommand; import seedu.address.logic.parser.exceptions.ParseException; +import seedu.address.model.person.AddressContainsKeywordsPredicate; import seedu.address.model.person.NameContainsKeywordsPredicate; import seedu.address.model.person.PhoneContainsKeywordsPredicate; @@ -60,6 +62,12 @@ public FindCommand parse(String args) throws ParseException { return new FindPhoneCommand(new PhoneContainsKeywordsPredicate(phoneKeywords)); } + if (hasAddressPrefix) { + String addressInput = argMultimap.getValue(PREFIX_ADDRESS).get().trim(); // Get the actual address input + List addressKeywords = Arrays.asList(addressInput.split("\\s+")); + return new FindAddressCommand(new AddressContainsKeywordsPredicate(addressKeywords)); + } + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE)); } diff --git a/src/main/java/seedu/address/model/person/AddressContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/person/AddressContainsKeywordsPredicate.java new file mode 100644 index 00000000000..6ee15ccef2f --- /dev/null +++ b/src/main/java/seedu/address/model/person/AddressContainsKeywordsPredicate.java @@ -0,0 +1,48 @@ +package seedu.address.model.person; + +import java.util.List; +import java.util.function.Predicate; + +import seedu.address.commons.util.StringUtil; +import seedu.address.commons.util.ToStringBuilder; + +/** + * Tests that a {@code Person}'s {@code Address} matches any of the keywords given. + */ +public class AddressContainsKeywordsPredicate implements Predicate { + private final List keywords; + + public AddressContainsKeywordsPredicate(List keywords) { + this.keywords = keywords; + } + + @Override + public boolean test(Person person) { + return keywords.stream() + .anyMatch(keyword -> StringUtil.containsPartialWordIgnoreCase(person.getAddress().value, keyword)); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + // instanceof handles nulls + if (!(other instanceof AddressContainsKeywordsPredicate)) { + return false; + } + + AddressContainsKeywordsPredicate otherNameContainsKeywordsPredicate = (AddressContainsKeywordsPredicate) other; + return keywords.equals(otherNameContainsKeywordsPredicate.keywords); + } + + @Override + public String toString() { + return new ToStringBuilder(this).add("keywords", keywords).toString(); + } + + public String getDisplayString() { + return String.join(", ", keywords); + } +} From a1fee8c4920a074c7fbc909e9d0992a79d27a34e Mon Sep 17 00:00:00 2001 From: tingxuanp Date: Mon, 14 Oct 2024 16:38:45 +0800 Subject: [PATCH 04/33] Implement search by email --- .../logic/commands/FindAddressCommand.java | 4 +- .../address/logic/commands/FindCommand.java | 2 - .../logic/commands/FindEmailCommand.java | 64 +++++++++++++++++++ .../logic/commands/FindNameCommand.java | 4 +- .../logic/commands/FindPhoneCommand.java | 4 +- .../logic/parser/FindCommandParser.java | 9 +++ .../EmailContainsKeywordsPredicate.java | 48 ++++++++++++++ 7 files changed, 124 insertions(+), 11 deletions(-) create mode 100644 src/main/java/seedu/address/logic/commands/FindEmailCommand.java create mode 100644 src/main/java/seedu/address/model/person/EmailContainsKeywordsPredicate.java diff --git a/src/main/java/seedu/address/logic/commands/FindAddressCommand.java b/src/main/java/seedu/address/logic/commands/FindAddressCommand.java index 93d89a1cbe8..0c8b737a09e 100644 --- a/src/main/java/seedu/address/logic/commands/FindAddressCommand.java +++ b/src/main/java/seedu/address/logic/commands/FindAddressCommand.java @@ -15,8 +15,6 @@ public class FindAddressCommand extends FindCommand { public static final String MESSAGE_FIND_ADDRESS_PERSON_SUCCESS = "Search for address containing \"%s\" " + " was successful. Showing results:"; - public static final String MESSAGE_FIND_ADDRESS_PERSON_UNSUCCESSFUL = "No contacts found."; - private final AddressContainsKeywordsPredicate predicate; /** @@ -38,7 +36,7 @@ public CommandResult execute(Model model) { if (!model.getFilteredPersonList().isEmpty()) { return new CommandResult(String.format(MESSAGE_FIND_ADDRESS_PERSON_SUCCESS, predicate.getDisplayString())); } else { - return new CommandResult(MESSAGE_FIND_ADDRESS_PERSON_UNSUCCESSFUL); + return new CommandResult(MESSAGE_FIND_PERSON_UNSUCCESSFUL); } } diff --git a/src/main/java/seedu/address/logic/commands/FindCommand.java b/src/main/java/seedu/address/logic/commands/FindCommand.java index b0106b5d83e..428b2037452 100644 --- a/src/main/java/seedu/address/logic/commands/FindCommand.java +++ b/src/main/java/seedu/address/logic/commands/FindCommand.java @@ -14,8 +14,6 @@ public abstract class FindCommand extends Command { + "Parameters: KEYWORD [MORE_KEYWORDS]...\n" + "Example: " + COMMAND_WORD + " alice bob charlie"; - public static final String MESSAGE_FIND_PERSON_SUCCESS = "Search for \"%s\" was successful. Showing results:"; - public static final String MESSAGE_FIND_PERSON_UNSUCCESSFUL = "No contacts found."; diff --git a/src/main/java/seedu/address/logic/commands/FindEmailCommand.java b/src/main/java/seedu/address/logic/commands/FindEmailCommand.java new file mode 100644 index 00000000000..51058594a5d --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/FindEmailCommand.java @@ -0,0 +1,64 @@ +package seedu.address.logic.commands; + +import static java.util.Objects.requireNonNull; + +import seedu.address.commons.util.ToStringBuilder; +import seedu.address.model.Model; +import seedu.address.model.person.EmailContainsKeywordsPredicate; + +/** + * Finds and lists all persons in address book whose email contains any of the argument keywords. + * Keyword matching is case-insensitive and allows partial matching, including numbers and symbols. + */ +public class FindEmailCommand extends FindCommand { + public static final String MESSAGE_FIND_EMAIL_PERSON_SUCCESS = "Search for email containing \"%s\" was successful. " + + " Showing results:"; + + private final EmailContainsKeywordsPredicate predicate; + + /** + * Command to filter contacts in WedLinker based on names using partial matching. + * This command allows users to search for contacts by providing one or more keywords. + * The search is case-insensitive and matches any part of the contact names. + * + * @param predicate Keywords used to filter contacts by name. + */ + public FindEmailCommand(EmailContainsKeywordsPredicate predicate) { + super(); + this.predicate = predicate; + } + + @Override + public CommandResult execute(Model model) { + requireNonNull(model); + model.updateFilteredPersonList(predicate); + + if (!model.getFilteredPersonList().isEmpty()) { + return new CommandResult(String.format(MESSAGE_FIND_EMAIL_PERSON_SUCCESS, predicate.getDisplayString())); + } else { + return new CommandResult(MESSAGE_FIND_PERSON_UNSUCCESSFUL); + } + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + // instanceof handles nulls + if (!(other instanceof FindEmailCommand)) { + return false; + } + + FindEmailCommand otherFindCommand = (FindEmailCommand) other; + return predicate.equals(otherFindCommand.predicate); + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .add("predicate", predicate) + .toString(); + } +} diff --git a/src/main/java/seedu/address/logic/commands/FindNameCommand.java b/src/main/java/seedu/address/logic/commands/FindNameCommand.java index a62626a94b8..6b0cff89910 100644 --- a/src/main/java/seedu/address/logic/commands/FindNameCommand.java +++ b/src/main/java/seedu/address/logic/commands/FindNameCommand.java @@ -15,8 +15,6 @@ public class FindNameCommand extends FindCommand { public static final String MESSAGE_FIND_NAME_PERSON_SUCCESS = "Search for name containing \"%s\" was successful. " + " Showing results:"; - public static final String MESSAGE_FIND_NAME_PERSON_UNSUCCESSFUL = "No contacts found."; - private final NameContainsKeywordsPredicate predicate; /** @@ -39,7 +37,7 @@ public CommandResult execute(Model model) { if (!model.getFilteredPersonList().isEmpty()) { return new CommandResult(String.format(MESSAGE_FIND_NAME_PERSON_SUCCESS, predicate.getDisplayString())); } else { - return new CommandResult(MESSAGE_FIND_NAME_PERSON_UNSUCCESSFUL); + return new CommandResult(MESSAGE_FIND_PERSON_UNSUCCESSFUL); } } diff --git a/src/main/java/seedu/address/logic/commands/FindPhoneCommand.java b/src/main/java/seedu/address/logic/commands/FindPhoneCommand.java index 90ea60e6023..12813e8681a 100644 --- a/src/main/java/seedu/address/logic/commands/FindPhoneCommand.java +++ b/src/main/java/seedu/address/logic/commands/FindPhoneCommand.java @@ -15,8 +15,6 @@ public class FindPhoneCommand extends FindCommand { public static final String MESSAGE_FIND_PHONE_PERSON_SUCCESS = "Search for phone number containing \"%s\" " + " was successful. Showing results:"; - public static final String MESSAGE_FIND_PHONE_PERSON_UNSUCCESSFUL = "No contacts found."; - private final PhoneContainsKeywordsPredicate predicate; /** @@ -38,7 +36,7 @@ public CommandResult execute(Model model) { if (!model.getFilteredPersonList().isEmpty()) { return new CommandResult(String.format(MESSAGE_FIND_PHONE_PERSON_SUCCESS, predicate.getDisplayString())); } else { - return new CommandResult(MESSAGE_FIND_PHONE_PERSON_UNSUCCESSFUL); + return new CommandResult(MESSAGE_FIND_PERSON_UNSUCCESSFUL); } } diff --git a/src/main/java/seedu/address/logic/parser/FindCommandParser.java b/src/main/java/seedu/address/logic/parser/FindCommandParser.java index f03db9fb28b..0c6ed134401 100644 --- a/src/main/java/seedu/address/logic/parser/FindCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/FindCommandParser.java @@ -13,13 +13,16 @@ import seedu.address.logic.commands.FindAddressCommand; import seedu.address.logic.commands.FindCommand; +import seedu.address.logic.commands.FindEmailCommand; import seedu.address.logic.commands.FindNameCommand; import seedu.address.logic.commands.FindPhoneCommand; import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.person.AddressContainsKeywordsPredicate; +import seedu.address.model.person.EmailContainsKeywordsPredicate; import seedu.address.model.person.NameContainsKeywordsPredicate; import seedu.address.model.person.PhoneContainsKeywordsPredicate; + /** * Parses input arguments and creates a new FindCommand object */ @@ -62,6 +65,12 @@ public FindCommand parse(String args) throws ParseException { return new FindPhoneCommand(new PhoneContainsKeywordsPredicate(phoneKeywords)); } + if (hasEmailPrefix) { + String emailInput = argMultimap.getValue(PREFIX_EMAIL).get().trim(); // Get the actual email input + List emailKeywords = Arrays.asList(emailInput.split("\\s+")); + return new FindEmailCommand(new EmailContainsKeywordsPredicate(emailKeywords)); + } + if (hasAddressPrefix) { String addressInput = argMultimap.getValue(PREFIX_ADDRESS).get().trim(); // Get the actual address input List addressKeywords = Arrays.asList(addressInput.split("\\s+")); diff --git a/src/main/java/seedu/address/model/person/EmailContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/person/EmailContainsKeywordsPredicate.java new file mode 100644 index 00000000000..da51cf71780 --- /dev/null +++ b/src/main/java/seedu/address/model/person/EmailContainsKeywordsPredicate.java @@ -0,0 +1,48 @@ +package seedu.address.model.person; + +import java.util.List; +import java.util.function.Predicate; + +import seedu.address.commons.util.StringUtil; +import seedu.address.commons.util.ToStringBuilder; + +/** + * Tests that a {@code Person}'s {@code Email} matches any of the keywords given. + */ +public class EmailContainsKeywordsPredicate implements Predicate { + private final List keywords; + + public EmailContainsKeywordsPredicate(List keywords) { + this.keywords = keywords; + } + + @Override + public boolean test(Person person) { + return keywords.stream() + .anyMatch(keyword -> StringUtil.containsPartialWordIgnoreCase(person.getEmail().value, keyword)); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + // instanceof handles nulls + if (!(other instanceof EmailContainsKeywordsPredicate)) { + return false; + } + + EmailContainsKeywordsPredicate otherNameContainsKeywordsPredicate = (EmailContainsKeywordsPredicate) other; + return keywords.equals(otherNameContainsKeywordsPredicate.keywords); + } + + @Override + public String toString() { + return new ToStringBuilder(this).add("keywords", keywords).toString(); + } + + public String getDisplayString() { + return String.join(", ", keywords); + } +} From a35bf0c52c04fa1e8c62aad4b4f7ed6479867552 Mon Sep 17 00:00:00 2001 From: DanzaSeah Date: Mon, 14 Oct 2024 21:47:59 +0800 Subject: [PATCH 05/33] Refactor TagCommandParser and UntagCommandParser to use TaggingCommandParserUtil --- .../address/logic/commands/TagCommand.java | 3 ++ .../address/logic/commands/UntagCommand.java | 3 ++ .../logic/parser/TagCommandParser.java | 31 ++--------- .../parser/TaggingCommandParserUtil.java | 53 ++++++++++++++++++ .../logic/parser/UntagCommandParser.java | 31 ++--------- .../logic/parser/TagCommandParserTest.java | 9 ++-- .../parser/TaggingCommandParserUtilTest.java | 54 +++++++++++++++++++ .../logic/parser/UntagCommandParserTest.java | 9 +++- 8 files changed, 137 insertions(+), 56 deletions(-) create mode 100644 src/main/java/seedu/address/logic/parser/TaggingCommandParserUtil.java create mode 100644 src/test/java/seedu/address/logic/parser/TaggingCommandParserUtilTest.java diff --git a/src/main/java/seedu/address/logic/commands/TagCommand.java b/src/main/java/seedu/address/logic/commands/TagCommand.java index e25dbfbf5b3..a765323b913 100644 --- a/src/main/java/seedu/address/logic/commands/TagCommand.java +++ b/src/main/java/seedu/address/logic/commands/TagCommand.java @@ -1,5 +1,6 @@ package seedu.address.logic.commands; +import static java.util.Objects.requireNonNull; import static seedu.address.logic.Messages.MESSAGE_ADD_TAG_SUCCESS; import static seedu.address.logic.Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX; import static seedu.address.logic.Messages.MESSAGE_TAG_NOT_FOUND; @@ -41,6 +42,8 @@ public class TagCommand extends Command { * @param tagsToAdd The list of tags to be added. */ public TagCommand(Index index, HashSet tagsToAdd) { + requireNonNull(index); + requireNonNull(tagsToAdd); this.index = index; this.tagsToAdd = tagsToAdd; } diff --git a/src/main/java/seedu/address/logic/commands/UntagCommand.java b/src/main/java/seedu/address/logic/commands/UntagCommand.java index c87651ccff8..99c2d7e15d4 100644 --- a/src/main/java/seedu/address/logic/commands/UntagCommand.java +++ b/src/main/java/seedu/address/logic/commands/UntagCommand.java @@ -1,5 +1,6 @@ package seedu.address.logic.commands; +import static java.util.Objects.requireNonNull; import static seedu.address.logic.Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX; import static seedu.address.logic.Messages.MESSAGE_TAG_NOT_FOUND_IN_CONTACT; @@ -42,6 +43,8 @@ public class UntagCommand extends Command { * @param tagsToRemove The list of tags to be removed. */ public UntagCommand(Index index, HashSet tagsToRemove) { + requireNonNull(index); + requireNonNull(tagsToRemove); this.index = index; this.tagsToRemove = tagsToRemove; } diff --git a/src/main/java/seedu/address/logic/parser/TagCommandParser.java b/src/main/java/seedu/address/logic/parser/TagCommandParser.java index c42979ca4c8..ef97990d178 100644 --- a/src/main/java/seedu/address/logic/parser/TagCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/TagCommandParser.java @@ -1,19 +1,16 @@ package seedu.address.logic.parser; import static java.util.Objects.requireNonNull; -import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; import java.util.HashSet; -import java.util.List; -import java.util.stream.Collectors; +import java.util.Set; +import javafx.util.Pair; import seedu.address.commons.core.index.Index; -import seedu.address.commons.exceptions.IllegalValueException; import seedu.address.logic.commands.TagCommand; import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.tag.Tag; -import seedu.address.model.tag.TagName; /** * Parses input arguments and creates a new TagCommand object. @@ -32,27 +29,9 @@ public TagCommand parse(String args) throws ParseException { requireNonNull(args); ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_TAG); + Pair> indexAndTags = TaggingCommandParserUtil.parseIndexAndTags(argMultimap, + TagCommand.MESSAGE_USAGE); - Index index; - - try { - // Parse the index from the preamble - index = ParserUtil.parseIndex(argMultimap.getPreamble()); - } catch (IllegalValueException ive) { - throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, TagCommand.MESSAGE_USAGE), ive); - } - - List tagValues = argMultimap.getAllValues(PREFIX_TAG); - if (tagValues.isEmpty()) { - throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, TagCommand.MESSAGE_USAGE)); - } - - // Convert tag values to Tag objects - HashSet tags = new HashSet<>(tagValues.stream() - .map(TagName::new) // Convert each string to a TagName object - .map(Tag::new) - .collect(Collectors.toList())); - - return new TagCommand(index, tags); + return new TagCommand(indexAndTags.getKey(), new HashSet<>(indexAndTags.getValue())); } } diff --git a/src/main/java/seedu/address/logic/parser/TaggingCommandParserUtil.java b/src/main/java/seedu/address/logic/parser/TaggingCommandParserUtil.java new file mode 100644 index 00000000000..18627ec4f97 --- /dev/null +++ b/src/main/java/seedu/address/logic/parser/TaggingCommandParserUtil.java @@ -0,0 +1,53 @@ +package seedu.address.logic.parser; + +import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; + +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Stream; + +import javafx.util.Pair; +import seedu.address.commons.core.index.Index; +import seedu.address.logic.parser.exceptions.ParseException; +import seedu.address.model.tag.Tag; + +/** + * A utility class that provides methods for parsing input arguments related to + * tagging commands, such as extracting the index and tags from user input. + */ +public class TaggingCommandParserUtil { + + /** + * Parses the index and tags from the argument map. + * + * @param argMultimap the argument multimap containing the preamble and tags + * @return a pair consisting of the parsed index and tag list + * @throws ParseException if the index or tags are invalid + */ + public static Pair> parseIndexAndTags(ArgumentMultimap argMultimap, String messageUsage) + throws ParseException { + Index index; + if (!arePrefixesPresent(argMultimap, PREFIX_TAG)) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, messageUsage)); + } + + try { + index = ParserUtil.parseIndex(argMultimap.getPreamble()); + } catch (ParseException pe) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, messageUsage), pe); + } + Set tagValues = ParserUtil.parseTags(argMultimap.getAllValues(PREFIX_TAG)); + + + return new Pair<>(index, new HashSet<>(tagValues)); + } + + /** + * Returns true if none of the prefixes contains empty {@code Optional} values in the given + * {@code ArgumentMultimap}. + */ + private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) { + return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent()); + } +} diff --git a/src/main/java/seedu/address/logic/parser/UntagCommandParser.java b/src/main/java/seedu/address/logic/parser/UntagCommandParser.java index a016a82a232..984e66bd907 100644 --- a/src/main/java/seedu/address/logic/parser/UntagCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/UntagCommandParser.java @@ -1,19 +1,16 @@ package seedu.address.logic.parser; import static java.util.Objects.requireNonNull; -import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; import java.util.HashSet; -import java.util.List; -import java.util.stream.Collectors; +import java.util.Set; +import javafx.util.Pair; import seedu.address.commons.core.index.Index; -import seedu.address.commons.exceptions.IllegalValueException; import seedu.address.logic.commands.UntagCommand; import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.tag.Tag; -import seedu.address.model.tag.TagName; /** * Parses input arguments and creates a new UntagCommand object. @@ -32,27 +29,9 @@ public UntagCommand parse(String args) throws ParseException { requireNonNull(args); ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_TAG); + Pair> indexAndTags = TaggingCommandParserUtil + .parseIndexAndTags(argMultimap, UntagCommand.MESSAGE_USAGE); - Index index; - - try { - // Parse the index from the preamble - index = ParserUtil.parseIndex(argMultimap.getPreamble()); - } catch (IllegalValueException ive) { - throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, UntagCommand.MESSAGE_USAGE), ive); - } - - List tagValues = argMultimap.getAllValues(PREFIX_TAG); - if (tagValues.isEmpty()) { - throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, UntagCommand.MESSAGE_USAGE)); - } - - // Convert tag values to Tag objects - List tags = tagValues.stream() - .map(TagName::new) - .map(Tag::new) - .collect(Collectors.toList()); - - return new UntagCommand(index, new HashSet<>(tags)); + return new UntagCommand(indexAndTags.getKey(), new HashSet<>(indexAndTags.getValue())); } } diff --git a/src/test/java/seedu/address/logic/parser/TagCommandParserTest.java b/src/test/java/seedu/address/logic/parser/TagCommandParserTest.java index fd80f223830..fb368ef87d1 100644 --- a/src/test/java/seedu/address/logic/parser/TagCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/TagCommandParserTest.java @@ -39,12 +39,15 @@ public void parse_invalidArgs_throwsParseException() { assertParseFailure(parser, "a t/colleague", String.format(MESSAGE_INVALID_COMMAND_FORMAT, TagCommand.MESSAGE_USAGE)); + // Index missing + assertParseFailure(parser, "t/colleague t/gym", String.format(MESSAGE_INVALID_COMMAND_FORMAT, + TagCommand.MESSAGE_USAGE)); + // Missing tags (no tags specified) assertParseFailure(parser, "1", String.format(MESSAGE_INVALID_COMMAND_FORMAT, TagCommand.MESSAGE_USAGE)); - // Index missing - assertParseFailure(parser, "t/colleague t/gym", String.format(MESSAGE_INVALID_COMMAND_FORMAT, - TagCommand.MESSAGE_USAGE)); + // Tags not in alphanumeric and space format + assertParseFailure(parser, "1 t/colleague_", TagName.MESSAGE_CONSTRAINTS); } } diff --git a/src/test/java/seedu/address/logic/parser/TaggingCommandParserUtilTest.java b/src/test/java/seedu/address/logic/parser/TaggingCommandParserUtilTest.java new file mode 100644 index 00000000000..cf0e2f737d6 --- /dev/null +++ b/src/test/java/seedu/address/logic/parser/TaggingCommandParserUtilTest.java @@ -0,0 +1,54 @@ +package seedu.address.logic.parser; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; + +import java.util.HashSet; +import java.util.Set; + +import org.junit.jupiter.api.Test; + +import javafx.util.Pair; +import seedu.address.commons.core.index.Index; +import seedu.address.logic.parser.exceptions.ParseException; +import seedu.address.model.tag.Tag; +import seedu.address.model.tag.TagName; + +public class TaggingCommandParserUtilTest { + + @Test + public void parseIndexAndTags_validInput_returnsPair() throws Exception { + String userInput = "1 " + PREFIX_TAG + "friend " + PREFIX_TAG + "colleague"; + ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(userInput, PREFIX_TAG); + + Pair> result = TaggingCommandParserUtil.parseIndexAndTags(argMultimap, "dummy usage message"); + + Set expectedTags = new HashSet<>(); + expectedTags.add(new Tag(new TagName("friend"))); + expectedTags.add(new Tag(new TagName("colleague"))); + + assertEquals(Index.fromOneBased(1), result.getKey()); + assertEquals(expectedTags, result.getValue()); + } + + @Test + public void parseIndexAndTags_invalidIndex_throwsParseException() { + String userInput = "a " + PREFIX_TAG + "friend"; + ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(userInput, PREFIX_TAG); + + assertThrows(ParseException.class, () -> + TaggingCommandParserUtil.parseIndexAndTags(argMultimap, "dummy usage message") + ); + } + + @Test + public void parseIndexAndTags_missingTags_throwsParseException() { + String userInput = "1"; + ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(userInput, PREFIX_TAG); + + assertThrows(ParseException.class, () -> + TaggingCommandParserUtil.parseIndexAndTags(argMultimap, "dummy usage message") + ); + } +} diff --git a/src/test/java/seedu/address/logic/parser/UntagCommandParserTest.java b/src/test/java/seedu/address/logic/parser/UntagCommandParserTest.java index d5d9b99868e..4bd2ee06eef 100644 --- a/src/test/java/seedu/address/logic/parser/UntagCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/UntagCommandParserTest.java @@ -36,11 +36,18 @@ public void parse_validArgs_returnsUntagCommand() { @Test public void parse_invalidArgs_throwsParseException() { // Invalid index (non-numeric) - assertParseFailure(parser, "a t/friends", String.format(MESSAGE_INVALID_COMMAND_FORMAT, + assertParseFailure(parser, "a t/colleague", String.format(MESSAGE_INVALID_COMMAND_FORMAT, + UntagCommand.MESSAGE_USAGE)); + + // Index missing + assertParseFailure(parser, "t/colleague t/gym", String.format(MESSAGE_INVALID_COMMAND_FORMAT, UntagCommand.MESSAGE_USAGE)); // Missing tags (no tags specified) assertParseFailure(parser, "1", String.format(MESSAGE_INVALID_COMMAND_FORMAT, UntagCommand.MESSAGE_USAGE)); + + // Tags not in alphanumeric and space format + assertParseFailure(parser, "1 t/colleague_", TagName.MESSAGE_CONSTRAINTS); } } From 056d1e5bcfd9aede7d7a1fb16bc2c205d5968074 Mon Sep 17 00:00:00 2001 From: DanzaSeah Date: Tue, 15 Oct 2024 00:02:19 +0800 Subject: [PATCH 06/33] Add support for updating of Tag counts --- .../address/logic/commands/TagCommand.java | 4 ++++ .../address/logic/commands/UntagCommand.java | 9 +++++---- .../logic/parser/TaggingCommandParserUtil.java | 4 ++++ .../address/logic/commands/TagCommandTest.java | 12 ++++++++---- .../logic/commands/UntagCommandTest.java | 18 +++++++++++++----- 5 files changed, 34 insertions(+), 13 deletions(-) diff --git a/src/main/java/seedu/address/logic/commands/TagCommand.java b/src/main/java/seedu/address/logic/commands/TagCommand.java index a765323b913..f8027cde5d7 100644 --- a/src/main/java/seedu/address/logic/commands/TagCommand.java +++ b/src/main/java/seedu/address/logic/commands/TagCommand.java @@ -77,6 +77,10 @@ public CommandResult execute(Model model) throws CommandException { } } + for (Tag tag : tagsToAdd) { + tag.increaseTaggedCount(); + } + Set updatedTags = new HashSet<>(personToEdit.getTags()); updatedTags.addAll(tagsToAdd); diff --git a/src/main/java/seedu/address/logic/commands/UntagCommand.java b/src/main/java/seedu/address/logic/commands/UntagCommand.java index 99c2d7e15d4..2376a37506f 100644 --- a/src/main/java/seedu/address/logic/commands/UntagCommand.java +++ b/src/main/java/seedu/address/logic/commands/UntagCommand.java @@ -78,15 +78,16 @@ public CommandResult execute(Model model) throws CommandException { throw new CommandException(MESSAGE_TAG_NOT_FOUND_IN_CONTACT); } - if (tagsToRemove.isEmpty()) { - throw new CommandException(MESSAGE_TAG_NOT_FOUND_IN_CONTACT); - } - if (!updatedTags.containsAll(tagsToRemove)) { throw new CommandException(MESSAGE_TAG_NOT_FOUND_IN_CONTACT); } + updatedTags.removeAll(tagsToRemove); + for (Tag tag : tagsToRemove) { + tag.decreaseTaggedCount(); + } + Person editedPerson = new Person( personToEdit.getName(), personToEdit.getPhone(), diff --git a/src/main/java/seedu/address/logic/parser/TaggingCommandParserUtil.java b/src/main/java/seedu/address/logic/parser/TaggingCommandParserUtil.java index 18627ec4f97..97762411647 100644 --- a/src/main/java/seedu/address/logic/parser/TaggingCommandParserUtil.java +++ b/src/main/java/seedu/address/logic/parser/TaggingCommandParserUtil.java @@ -39,6 +39,10 @@ public static Pair> parseIndexAndTags(ArgumentMultimap argMultim } Set tagValues = ParserUtil.parseTags(argMultimap.getAllValues(PREFIX_TAG)); + if (tagValues.isEmpty()) { + System.out.println("No tags provided, throwing exception"); + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, messageUsage)); + } return new Pair<>(index, new HashSet<>(tagValues)); } diff --git a/src/test/java/seedu/address/logic/commands/TagCommandTest.java b/src/test/java/seedu/address/logic/commands/TagCommandTest.java index 453727d5748..e374d1ab8e3 100644 --- a/src/test/java/seedu/address/logic/commands/TagCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/TagCommandTest.java @@ -14,7 +14,11 @@ import seedu.address.model.Model; import seedu.address.model.ModelManager; import seedu.address.model.UserPrefs; +import seedu.address.model.person.Address; +import seedu.address.model.person.Email; +import seedu.address.model.person.Name; import seedu.address.model.person.Person; +import seedu.address.model.person.Phone; import seedu.address.model.tag.Tag; import seedu.address.model.tag.TagName; @@ -53,10 +57,10 @@ public void execute_validTagsUnfilteredList_success() { @Test public void execute_validMultipleTagsUnfilteredList_success() { Person personWithTags = new Person( - new seedu.address.model.person.Name("Test Person"), - new seedu.address.model.person.Phone("99999999"), - new seedu.address.model.person.Email("test@example.com"), - new seedu.address.model.person.Address("123, Test Street"), + new Name("Test Person"), + new Phone("99999999"), + new Email("test@example.com"), + new Address("123, Test Street"), new HashSet<>(Arrays.asList(new Tag(new TagName("family")))) ); model.addTag(new Tag(new TagName("family"))); diff --git a/src/test/java/seedu/address/logic/commands/UntagCommandTest.java b/src/test/java/seedu/address/logic/commands/UntagCommandTest.java index 7b34b0b3b78..98847914404 100644 --- a/src/test/java/seedu/address/logic/commands/UntagCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/UntagCommandTest.java @@ -1,5 +1,7 @@ package seedu.address.logic.commands; +import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static seedu.address.testutil.Assert.assertThrows; import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON; import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; @@ -12,6 +14,8 @@ import seedu.address.commons.core.index.Index; import seedu.address.logic.Messages; +import seedu.address.logic.parser.UntagCommandParser; +import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.Model; import seedu.address.model.ModelManager; import seedu.address.model.UserPrefs; @@ -92,11 +96,15 @@ public void execute_nonExistentTag_failure() { @Test public void execute_noTagsSpecified_failure() { - // No tags specified to remove - HashSet emptyTagsToRemove = new HashSet<>(Arrays.asList()); - UntagCommand untagCommand = new UntagCommand(INDEX_FIRST_PERSON, emptyTagsToRemove); - String expectedMessage = Messages.MESSAGE_TAG_NOT_FOUND_IN_CONTACT; - CommandTestUtil.assertCommandFailure(untagCommand, model, expectedMessage); + // No tags specified (input is "untag 1") + String userInput = "1"; // Only index is provided, no tags + UntagCommandParser parser = new UntagCommandParser(); + + String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, UntagCommand.MESSAGE_USAGE); + assertThrows(ParseException.class, expectedMessage, () -> { + parser.parse(userInput); + }); + } From a7e8b2d26ef45cc868170ced4f4d9d0786a53cad Mon Sep 17 00:00:00 2001 From: DanzaSeah Date: Tue, 15 Oct 2024 00:04:49 +0800 Subject: [PATCH 07/33] Remove redundant check --- .../seedu/address/logic/parser/TaggingCommandParserUtil.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/main/java/seedu/address/logic/parser/TaggingCommandParserUtil.java b/src/main/java/seedu/address/logic/parser/TaggingCommandParserUtil.java index 97762411647..f3f305fe478 100644 --- a/src/main/java/seedu/address/logic/parser/TaggingCommandParserUtil.java +++ b/src/main/java/seedu/address/logic/parser/TaggingCommandParserUtil.java @@ -39,11 +39,6 @@ public static Pair> parseIndexAndTags(ArgumentMultimap argMultim } Set tagValues = ParserUtil.parseTags(argMultimap.getAllValues(PREFIX_TAG)); - if (tagValues.isEmpty()) { - System.out.println("No tags provided, throwing exception"); - throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, messageUsage)); - } - return new Pair<>(index, new HashSet<>(tagValues)); } From c19a404111d63a81ecaaa044fc1a6849a61ce41f Mon Sep 17 00:00:00 2001 From: tingxuanp Date: Tue, 15 Oct 2024 00:47:36 +0800 Subject: [PATCH 08/33] Add test cases for find command --- .../logic/commands/FindAddressCommand.java | 1 - .../address/logic/commands/FindCommand.java | 11 +- .../logic/commands/FindEmailCommand.java | 1 - .../logic/commands/FindNameCommand.java | 1 - .../logic/commands/FindPhoneCommand.java | 1 - .../logic/parser/FindCommandParser.java | 13 +- .../AddressContainsKeywordsPredicate.java | 2 +- .../commands/FindAddressCommandTest.java | 136 ++++++++++++++++ .../logic/commands/FindEmailCommandTest.java | 142 ++++++++++++++++ .../logic/commands/FindNameCommandTest.java | 2 +- .../logic/commands/FindPhoneCommandTest.java | 153 ++++++++++++++++++ .../logic/parser/FindCommandParserTest.java | 5 +- 12 files changed, 451 insertions(+), 17 deletions(-) create mode 100644 src/test/java/seedu/address/logic/commands/FindAddressCommandTest.java create mode 100644 src/test/java/seedu/address/logic/commands/FindEmailCommandTest.java create mode 100644 src/test/java/seedu/address/logic/commands/FindPhoneCommandTest.java diff --git a/src/main/java/seedu/address/logic/commands/FindAddressCommand.java b/src/main/java/seedu/address/logic/commands/FindAddressCommand.java index 0c8b737a09e..2e72a747c57 100644 --- a/src/main/java/seedu/address/logic/commands/FindAddressCommand.java +++ b/src/main/java/seedu/address/logic/commands/FindAddressCommand.java @@ -24,7 +24,6 @@ public class FindAddressCommand extends FindCommand { * @param predicate Keywords used to filter contacts by their phone number. */ public FindAddressCommand(AddressContainsKeywordsPredicate predicate) { - super(); this.predicate = predicate; } diff --git a/src/main/java/seedu/address/logic/commands/FindCommand.java b/src/main/java/seedu/address/logic/commands/FindCommand.java index 428b2037452..4c6b8187f50 100644 --- a/src/main/java/seedu/address/logic/commands/FindCommand.java +++ b/src/main/java/seedu/address/logic/commands/FindCommand.java @@ -1,5 +1,7 @@ package seedu.address.logic.commands; +import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; +import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; /** * Finds and lists all persons in address book whose name contains any of the argument keywords. @@ -12,15 +14,8 @@ public abstract class FindCommand extends Command { public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all persons whose names contain any of " + "the specified keywords (case-insensitive) and displays them as a list with index numbers.\n" + "Parameters: KEYWORD [MORE_KEYWORDS]...\n" - + "Example: " + COMMAND_WORD + " alice bob charlie"; + + "Example: " + COMMAND_WORD + " " + PREFIX_PHONE + " alice charlie"; public static final String MESSAGE_FIND_PERSON_UNSUCCESSFUL = "No contacts found."; - - //@Override - //public String toString() { - // return new ToStringBuilder(this) - // .add("predicate", predicate) - // .toString(); - //} } diff --git a/src/main/java/seedu/address/logic/commands/FindEmailCommand.java b/src/main/java/seedu/address/logic/commands/FindEmailCommand.java index 51058594a5d..95c180da618 100644 --- a/src/main/java/seedu/address/logic/commands/FindEmailCommand.java +++ b/src/main/java/seedu/address/logic/commands/FindEmailCommand.java @@ -24,7 +24,6 @@ public class FindEmailCommand extends FindCommand { * @param predicate Keywords used to filter contacts by name. */ public FindEmailCommand(EmailContainsKeywordsPredicate predicate) { - super(); this.predicate = predicate; } diff --git a/src/main/java/seedu/address/logic/commands/FindNameCommand.java b/src/main/java/seedu/address/logic/commands/FindNameCommand.java index 6b0cff89910..802b1c86733 100644 --- a/src/main/java/seedu/address/logic/commands/FindNameCommand.java +++ b/src/main/java/seedu/address/logic/commands/FindNameCommand.java @@ -25,7 +25,6 @@ public class FindNameCommand extends FindCommand { * @param predicate Keywords used to filter contacts by name. */ public FindNameCommand(NameContainsKeywordsPredicate predicate) { - super(); this.predicate = predicate; } diff --git a/src/main/java/seedu/address/logic/commands/FindPhoneCommand.java b/src/main/java/seedu/address/logic/commands/FindPhoneCommand.java index 12813e8681a..63e8c739123 100644 --- a/src/main/java/seedu/address/logic/commands/FindPhoneCommand.java +++ b/src/main/java/seedu/address/logic/commands/FindPhoneCommand.java @@ -24,7 +24,6 @@ public class FindPhoneCommand extends FindCommand { * @param predicate Keywords used to filter contacts by their phone number. */ public FindPhoneCommand(PhoneContainsKeywordsPredicate predicate) { - super(); this.predicate = predicate; } diff --git a/src/main/java/seedu/address/logic/parser/FindCommandParser.java b/src/main/java/seedu/address/logic/parser/FindCommandParser.java index 0c6ed134401..8374a05b2ac 100644 --- a/src/main/java/seedu/address/logic/parser/FindCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/FindCommandParser.java @@ -40,7 +40,6 @@ public FindCommand parse(String args) throws ParseException { argMultimap.verifyNoDuplicatePrefixesFor(PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS); - String trimmedArgs = args.trim(); if (trimmedArgs.isEmpty()) { throw new ParseException( @@ -55,24 +54,36 @@ public FindCommand parse(String args) throws ParseException { if (hasNamePrefix) { String nameInput = argMultimap.getValue(PREFIX_NAME).get().trim(); // Get the actual name input + if (nameInput.isEmpty()) { + throw new ParseException("Name cannot be empty!"); + } List nameKeywords = Arrays.asList(nameInput.split("\\s+")); return new FindNameCommand(new NameContainsKeywordsPredicate(nameKeywords)); } if (hasPhonePrefix) { String phoneNumberInput = argMultimap.getValue(PREFIX_PHONE).get().trim(); // Get the actual phone input + if (phoneNumberInput.isEmpty()) { + throw new ParseException("Phone number cannot be empty!"); + } List phoneKeywords = Arrays.asList(phoneNumberInput.split("\\s+")); return new FindPhoneCommand(new PhoneContainsKeywordsPredicate(phoneKeywords)); } if (hasEmailPrefix) { String emailInput = argMultimap.getValue(PREFIX_EMAIL).get().trim(); // Get the actual email input + if (emailInput.isEmpty()) { + throw new ParseException("Email address cannot be empty!"); + } List emailKeywords = Arrays.asList(emailInput.split("\\s+")); return new FindEmailCommand(new EmailContainsKeywordsPredicate(emailKeywords)); } if (hasAddressPrefix) { String addressInput = argMultimap.getValue(PREFIX_ADDRESS).get().trim(); // Get the actual address input + if (addressInput.isEmpty()) { + throw new ParseException("Address cannot be empty!"); + } List addressKeywords = Arrays.asList(addressInput.split("\\s+")); return new FindAddressCommand(new AddressContainsKeywordsPredicate(addressKeywords)); } diff --git a/src/main/java/seedu/address/model/person/AddressContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/person/AddressContainsKeywordsPredicate.java index 6ee15ccef2f..567131e221c 100644 --- a/src/main/java/seedu/address/model/person/AddressContainsKeywordsPredicate.java +++ b/src/main/java/seedu/address/model/person/AddressContainsKeywordsPredicate.java @@ -19,7 +19,7 @@ public AddressContainsKeywordsPredicate(List keywords) { @Override public boolean test(Person person) { return keywords.stream() - .anyMatch(keyword -> StringUtil.containsPartialWordIgnoreCase(person.getAddress().value, keyword)); + .allMatch(keyword -> StringUtil.containsPartialWordIgnoreCase(person.getAddress().value, keyword)); } @Override diff --git a/src/test/java/seedu/address/logic/commands/FindAddressCommandTest.java b/src/test/java/seedu/address/logic/commands/FindAddressCommandTest.java new file mode 100644 index 00000000000..88f9a042669 --- /dev/null +++ b/src/test/java/seedu/address/logic/commands/FindAddressCommandTest.java @@ -0,0 +1,136 @@ +package seedu.address.logic.commands; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; +import static seedu.address.logic.commands.FindAddressCommand.MESSAGE_FIND_ADDRESS_PERSON_SUCCESS; +import static seedu.address.logic.commands.FindCommand.MESSAGE_FIND_PERSON_UNSUCCESSFUL; +import static seedu.address.testutil.TypicalPersons.*; + +import java.util.Arrays; +import java.util.Collections; + +import org.junit.jupiter.api.Test; + +import seedu.address.model.Model; +import seedu.address.model.ModelManager; +import seedu.address.model.UserPrefs; +import seedu.address.model.person.AddressContainsKeywordsPredicate; + +public class FindAddressCommandTest { + private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + private Model expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + + @Test + public void equals() { + AddressContainsKeywordsPredicate firstPredicate = + new AddressContainsKeywordsPredicate(Collections.singletonList("Bedok Block 16 #04-02")); + AddressContainsKeywordsPredicate secondPredicate = + new AddressContainsKeywordsPredicate(Collections.singletonList("Ang Mo Kio Street 10")); + + FindAddressCommand findFirstCommand = new FindAddressCommand(firstPredicate); + FindAddressCommand findSecondCommand = new FindAddressCommand(secondPredicate); + + // same object -> returns true + assertTrue(findFirstCommand.equals(findFirstCommand)); + + // same values -> returns true + FindCommand findFirstCommandCopy = new FindAddressCommand(firstPredicate); + assertTrue(findFirstCommand.equals(findFirstCommandCopy)); + + // different types -> returns false + assertFalse(findFirstCommand.equals(1)); + + // null -> returns false + assertFalse(findFirstCommand.equals(null)); + + // different person -> returns false + assertFalse(findFirstCommand.equals(findSecondCommand)); + } + +// @Test +// public void execute_emptyString_noPersonFound() { +// String expectedMessage = MESSAGE_FIND_PERSON_UNSUCCESSFUL; +// AddressContainsKeywordsPredicate predicate = preparePredicate(" "); +// FindAddressCommand command = new FindAddressCommand(predicate); +// expectedModel.updateFilteredPersonList(predicate); +// assertCommandSuccess(command, model, expectedMessage, expectedModel); +// assertEquals(Collections.emptyList(), model.getFilteredPersonList()); +// } + + @Test + public void execute_fullMatch_singlePersonFound() { + AddressContainsKeywordsPredicate predicate = preparePredicate("311, Clementi Ave 2, #02-25"); + String expectedMessage = String.format(MESSAGE_FIND_ADDRESS_PERSON_SUCCESS, predicate.getDisplayString()); + FindAddressCommand command = new FindAddressCommand(predicate); + expectedModel.updateFilteredPersonList(predicate); + assertCommandSuccess(command, model, expectedMessage, expectedModel); + assertEquals(Arrays.asList(BENSON), model.getFilteredPersonList()); + } + + @Test + public void execute_partialMatch_singlePersonFound() { + AddressContainsKeywordsPredicate predicate = preparePredicate("Jurong"); + String expectedMessage = String.format(MESSAGE_FIND_ADDRESS_PERSON_SUCCESS, predicate.getDisplayString()); + FindAddressCommand command = new FindAddressCommand(predicate); + expectedModel.updateFilteredPersonList(predicate); + assertCommandSuccess(command, model, expectedMessage, expectedModel); + assertEquals(Arrays.asList(ALICE), model.getFilteredPersonList()); + } + + @Test + public void execute_partialMatch2_singlePersonFound() { + AddressContainsKeywordsPredicate predicate = preparePredicate("wall str"); + String expectedMessage = String.format(MESSAGE_FIND_ADDRESS_PERSON_SUCCESS, predicate.getDisplayString()); + FindAddressCommand command = new FindAddressCommand(predicate); + expectedModel.updateFilteredPersonList(predicate); + assertCommandSuccess(command, model, expectedMessage, expectedModel); + assertEquals(Arrays.asList(CARL), model.getFilteredPersonList()); + } + + @Test + public void execute_partialMatch_multiplePersonsFound() { + AddressContainsKeywordsPredicate predicate = preparePredicate("ave"); + String expectedMessage = String.format(MESSAGE_FIND_ADDRESS_PERSON_SUCCESS, predicate.getDisplayString()); + FindAddressCommand command = new FindAddressCommand(predicate); + expectedModel.updateFilteredPersonList(predicate); + assertCommandSuccess(command, model, expectedMessage, expectedModel); + assertEquals(Arrays.asList(ALICE, BENSON, ELLE), model.getFilteredPersonList()); + } + + @Test + public void execute_absentPartialMatchKeyword_noPersonFound() { + AddressContainsKeywordsPredicate predicate = preparePredicate("x"); + String expectedMessage = MESSAGE_FIND_PERSON_UNSUCCESSFUL; + FindAddressCommand command = new FindAddressCommand(predicate); + expectedModel.updateFilteredPersonList(predicate); + assertCommandSuccess(command, model, expectedMessage, expectedModel); + assertEquals(Collections.emptyList(), model.getFilteredPersonList()); + } + + @Test + public void execute_absentPartialMatchKeyword2_noPersonFound() { + AddressContainsKeywordsPredicate predicate = preparePredicate("834 Bukit Batok"); + String expectedMessage = MESSAGE_FIND_PERSON_UNSUCCESSFUL; + FindAddressCommand command = new FindAddressCommand(predicate); + expectedModel.updateFilteredPersonList(predicate); + assertCommandSuccess(command, model, expectedMessage, expectedModel); + assertEquals(Collections.emptyList(), model.getFilteredPersonList()); + } + + @Test + public void toStringMethod() { + AddressContainsKeywordsPredicate predicate = new AddressContainsKeywordsPredicate(Arrays.asList("34 Tanah Merah")); + FindAddressCommand findPhoneCommand = new FindAddressCommand(predicate); + String expected = FindAddressCommand.class.getCanonicalName() + "{predicate=" + predicate + "}"; + assertEquals(expected, findPhoneCommand.toString()); + } + + /** + * Parses {@code userInput} into a {@code AddressContainsKeywordsPredicate}. + */ + private AddressContainsKeywordsPredicate preparePredicate(String userInput) { + return new AddressContainsKeywordsPredicate(Arrays.asList(userInput.split("\\s+"))); + } +} diff --git a/src/test/java/seedu/address/logic/commands/FindEmailCommandTest.java b/src/test/java/seedu/address/logic/commands/FindEmailCommandTest.java new file mode 100644 index 00000000000..76cf393c6c4 --- /dev/null +++ b/src/test/java/seedu/address/logic/commands/FindEmailCommandTest.java @@ -0,0 +1,142 @@ +package seedu.address.logic.commands; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; +import static seedu.address.logic.commands.FindCommand.MESSAGE_FIND_PERSON_UNSUCCESSFUL; +import static seedu.address.logic.commands.FindEmailCommand.MESSAGE_FIND_EMAIL_PERSON_SUCCESS; +import static seedu.address.testutil.TypicalPersons.ALICE; +import static seedu.address.testutil.TypicalPersons.BENSON; +import static seedu.address.testutil.TypicalPersons.CARL; +import static seedu.address.testutil.TypicalPersons.DANIEL; +import static seedu.address.testutil.TypicalPersons.FIONA; +import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; + +import java.util.Arrays; +import java.util.Collections; + +import org.junit.jupiter.api.Test; + +import seedu.address.model.Model; +import seedu.address.model.ModelManager; +import seedu.address.model.UserPrefs; +import seedu.address.model.person.EmailContainsKeywordsPredicate; + +public class FindEmailCommandTest { + + private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + private Model expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + + @Test + public void equals() { + EmailContainsKeywordsPredicate firstPredicate = + new EmailContainsKeywordsPredicate(Collections.singletonList("bob@yahoo.com")); + EmailContainsKeywordsPredicate secondPredicate = + new EmailContainsKeywordsPredicate(Collections.singletonList("sally@gmail.com")); + + FindEmailCommand findFirstCommand = new FindEmailCommand(firstPredicate); + FindEmailCommand findSecondCommand = new FindEmailCommand(secondPredicate); + + // same object -> returns true + assertTrue(findFirstCommand.equals(findFirstCommand)); + + // same values -> returns true + FindCommand findFirstCommandCopy = new FindEmailCommand(firstPredicate); + assertTrue(findFirstCommand.equals(findFirstCommandCopy)); + + // different types -> returns false + assertFalse(findFirstCommand.equals(1)); + + // null -> returns false + assertFalse(findFirstCommand.equals(null)); + + // different person -> returns false + assertFalse(findFirstCommand.equals(findSecondCommand)); + } + + @Test + public void execute_emptyString_noPersonFound() { + String expectedMessage = MESSAGE_FIND_PERSON_UNSUCCESSFUL; + EmailContainsKeywordsPredicate predicate = preparePredicate(" "); + FindEmailCommand command = new FindEmailCommand(predicate); + expectedModel.updateFilteredPersonList(predicate); + assertCommandSuccess(command, model, expectedMessage, expectedModel); + assertEquals(Collections.emptyList(), model.getFilteredPersonList()); + } + + @Test + public void execute_fullMatchEmail_singlePersonFound() { + EmailContainsKeywordsPredicate predicate = preparePredicate("alice@example.com"); + String expectedMessage = String.format(MESSAGE_FIND_EMAIL_PERSON_SUCCESS, predicate.getDisplayString()); + FindEmailCommand command = new FindEmailCommand(predicate); + expectedModel.updateFilteredPersonList(predicate); + assertCommandSuccess(command, model, expectedMessage, expectedModel); + assertEquals(Arrays.asList(ALICE), model.getFilteredPersonList()); + } + + @Test + public void execute_multipleFullMatchEmails_multiplePersonsFound() { + EmailContainsKeywordsPredicate predicate = preparePredicate("lydia@example.com heinz@example.com"); + String expectedMessage = String.format(MESSAGE_FIND_EMAIL_PERSON_SUCCESS, predicate.getDisplayString()); + FindEmailCommand command = new FindEmailCommand(predicate); + expectedModel.updateFilteredPersonList(predicate); + assertCommandSuccess(command, model, expectedMessage, expectedModel); + assertEquals(Arrays.asList(CARL, FIONA), model.getFilteredPersonList()); + } + + @Test + public void execute_singlePartialMatchNumber_singlePersonFound() { + EmailContainsKeywordsPredicate predicate = preparePredicate("hnd"); + String expectedMessage = String.format(MESSAGE_FIND_EMAIL_PERSON_SUCCESS, predicate.getDisplayString()); + FindEmailCommand command = new FindEmailCommand(predicate); + expectedModel.updateFilteredPersonList(predicate); + assertCommandSuccess(command, model, expectedMessage, expectedModel); + assertEquals(Arrays.asList(BENSON), model.getFilteredPersonList()); + } + + @Test + public void execute_singlePartialMatchNumber_multiplePersonsFound() { + EmailContainsKeywordsPredicate predicate = preparePredicate("ia"); + String expectedMessage = String.format(MESSAGE_FIND_EMAIL_PERSON_SUCCESS, predicate.getDisplayString()); + FindEmailCommand command = new FindEmailCommand(predicate); + expectedModel.updateFilteredPersonList(predicate); + assertCommandSuccess(command, model, expectedMessage, expectedModel); + assertEquals(Arrays.asList(DANIEL, FIONA), model.getFilteredPersonList()); + } + + @Test + public void execute_absentPartialMatchKeyword_noPersonFound() { + EmailContainsKeywordsPredicate predicate = preparePredicate("xXx"); + String expectedMessage = MESSAGE_FIND_PERSON_UNSUCCESSFUL; + FindEmailCommand command = new FindEmailCommand(predicate); + expectedModel.updateFilteredPersonList(predicate); + assertCommandSuccess(command, model, expectedMessage, expectedModel); + assertEquals(Collections.emptyList(), model.getFilteredPersonList()); + } + + @Test + public void execute_absentPartialMatchKeyword2_noPersonFound() { + EmailContainsKeywordsPredicate predicate = preparePredicate("allen"); + String expectedMessage = MESSAGE_FIND_PERSON_UNSUCCESSFUL; + FindEmailCommand command = new FindEmailCommand(predicate); + expectedModel.updateFilteredPersonList(predicate); + assertCommandSuccess(command, model, expectedMessage, expectedModel); + assertEquals(Collections.emptyList(), model.getFilteredPersonList()); + } + + @Test + public void toStringMethod() { + EmailContainsKeywordsPredicate predicate = new EmailContainsKeywordsPredicate(Arrays.asList("amy@gmail.com")); + FindEmailCommand findPhoneCommand = new FindEmailCommand(predicate); + String expected = FindEmailCommand.class.getCanonicalName() + "{predicate=" + predicate + "}"; + assertEquals(expected, findPhoneCommand.toString()); + } + + /** + * Parses {@code userInput} into a {@code EmailContainsKeywordsPredicate}. + */ + private EmailContainsKeywordsPredicate preparePredicate(String userInput) { + return new EmailContainsKeywordsPredicate(Arrays.asList(userInput.split("\\s+"))); + } +} diff --git a/src/test/java/seedu/address/logic/commands/FindNameCommandTest.java b/src/test/java/seedu/address/logic/commands/FindNameCommandTest.java index 6098608452b..50a40b1dfc0 100644 --- a/src/test/java/seedu/address/logic/commands/FindNameCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/FindNameCommandTest.java @@ -26,7 +26,7 @@ import seedu.address.model.person.NameContainsKeywordsPredicate; /** - * Contains integration tests (interaction with the Model) for {@code FindCommand}. + * Contains integration tests (interaction with the Model) for {@code FindNameCommand}. */ public class FindNameCommandTest { private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); diff --git a/src/test/java/seedu/address/logic/commands/FindPhoneCommandTest.java b/src/test/java/seedu/address/logic/commands/FindPhoneCommandTest.java new file mode 100644 index 00000000000..32e8b42f6b7 --- /dev/null +++ b/src/test/java/seedu/address/logic/commands/FindPhoneCommandTest.java @@ -0,0 +1,153 @@ +package seedu.address.logic.commands; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; +import static seedu.address.logic.commands.FindCommand.MESSAGE_FIND_PERSON_UNSUCCESSFUL; +import static seedu.address.logic.commands.FindPhoneCommand.MESSAGE_FIND_PHONE_PERSON_SUCCESS; +import static seedu.address.testutil.TypicalPersons.ALICE; +import static seedu.address.testutil.TypicalPersons.BENSON; +import static seedu.address.testutil.TypicalPersons.CARL; +import static seedu.address.testutil.TypicalPersons.DANIEL; +import static seedu.address.testutil.TypicalPersons.ELLE; +import static seedu.address.testutil.TypicalPersons.FIONA; +import static seedu.address.testutil.TypicalPersons.GEORGE; +import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; + +import java.util.Arrays; +import java.util.Collections; + +import org.junit.jupiter.api.Test; + +import seedu.address.model.Model; +import seedu.address.model.ModelManager; +import seedu.address.model.UserPrefs; +import seedu.address.model.person.PhoneContainsKeywordsPredicate; + +public class FindPhoneCommandTest { + private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + private Model expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + + @Test + public void equals() { + PhoneContainsKeywordsPredicate firstPredicate = + new PhoneContainsKeywordsPredicate(Collections.singletonList("99891000")); + PhoneContainsKeywordsPredicate secondPredicate = + new PhoneContainsKeywordsPredicate(Collections.singletonList("88203928")); + + FindPhoneCommand findFirstCommand = new FindPhoneCommand(firstPredicate); + FindPhoneCommand findSecondCommand = new FindPhoneCommand(secondPredicate); + + // same object -> returns true + assertTrue(findFirstCommand.equals(findFirstCommand)); + + // same values -> returns true + FindCommand findFirstCommandCopy = new FindPhoneCommand(firstPredicate); + assertTrue(findFirstCommand.equals(findFirstCommandCopy)); + + // different types -> returns false + assertFalse(findFirstCommand.equals(1)); + + // null -> returns false + assertFalse(findFirstCommand.equals(null)); + + // different person -> returns false + assertFalse(findFirstCommand.equals(findSecondCommand)); + } + + @Test + public void execute_emptyString_noPersonFound() { + String expectedMessage = MESSAGE_FIND_PERSON_UNSUCCESSFUL; + PhoneContainsKeywordsPredicate predicate = preparePredicate(" "); + FindPhoneCommand command = new FindPhoneCommand(predicate); + expectedModel.updateFilteredPersonList(predicate); + assertCommandSuccess(command, model, expectedMessage, expectedModel); + assertEquals(Collections.emptyList(), model.getFilteredPersonList()); + } + + @Test + public void execute_fullMatch_singlePersonFound() { + PhoneContainsKeywordsPredicate predicate = preparePredicate("9482442"); + String expectedMessage = String.format(MESSAGE_FIND_PHONE_PERSON_SUCCESS, predicate.getDisplayString()); + FindPhoneCommand command = new FindPhoneCommand(predicate); + expectedModel.updateFilteredPersonList(predicate); + assertCommandSuccess(command, model, expectedMessage, expectedModel); + assertEquals(Arrays.asList(GEORGE), model.getFilteredPersonList()); + } + + @Test + public void execute_multipleFullMatchNumbers_multiplePersonsFound() { + PhoneContainsKeywordsPredicate predicate = preparePredicate("95352563 9482427"); + String expectedMessage = String.format(MESSAGE_FIND_PHONE_PERSON_SUCCESS, predicate.getDisplayString()); + FindPhoneCommand command = new FindPhoneCommand(predicate); + expectedModel.updateFilteredPersonList(predicate); + assertCommandSuccess(command, model, expectedMessage, expectedModel); + assertEquals(Arrays.asList(CARL, FIONA), model.getFilteredPersonList()); + } + + @Test + public void execute_singlePartialMatchNumber_singlePersonFound() { + PhoneContainsKeywordsPredicate predicate = preparePredicate("2224"); + String expectedMessage = String.format(MESSAGE_FIND_PHONE_PERSON_SUCCESS, predicate.getDisplayString()); + FindPhoneCommand command = new FindPhoneCommand(predicate); + expectedModel.updateFilteredPersonList(predicate); + assertCommandSuccess(command, model, expectedMessage, expectedModel); + assertEquals(Arrays.asList(ELLE), model.getFilteredPersonList()); + } + + @Test + public void execute_singlePartialMatchNumber2_singlePersonFound() { + PhoneContainsKeywordsPredicate predicate = preparePredicate("5253"); + String expectedMessage = String.format(MESSAGE_FIND_PHONE_PERSON_SUCCESS, predicate.getDisplayString()); + FindPhoneCommand command = new FindPhoneCommand(predicate); + expectedModel.updateFilteredPersonList(predicate); + assertCommandSuccess(command, model, expectedMessage, expectedModel); + assertEquals(Arrays.asList(DANIEL), model.getFilteredPersonList()); + } + + @Test + public void execute_singlePartialMatchNumber_multiplePersonsFound() { + PhoneContainsKeywordsPredicate predicate = preparePredicate("9"); + String expectedMessage = String.format(MESSAGE_FIND_PHONE_PERSON_SUCCESS, predicate.getDisplayString()); + FindPhoneCommand command = new FindPhoneCommand(predicate); + expectedModel.updateFilteredPersonList(predicate); + assertCommandSuccess(command, model, expectedMessage, expectedModel); + assertEquals(Arrays.asList(ALICE, BENSON, CARL, ELLE, FIONA, GEORGE), model.getFilteredPersonList()); + } + + @Test + public void execute_absentPartialMatchKeyword_noPersonFound() { + PhoneContainsKeywordsPredicate predicate = preparePredicate("0"); + String expectedMessage = MESSAGE_FIND_PERSON_UNSUCCESSFUL; + FindPhoneCommand command = new FindPhoneCommand(predicate); + expectedModel.updateFilteredPersonList(predicate); + assertCommandSuccess(command, model, expectedMessage, expectedModel); + assertEquals(Collections.emptyList(), model.getFilteredPersonList()); + } + + @Test + public void execute_absentPartialMatchKeyword2_noPersonFound() { + PhoneContainsKeywordsPredicate predicate = preparePredicate("54321"); + String expectedMessage = MESSAGE_FIND_PERSON_UNSUCCESSFUL; + FindPhoneCommand command = new FindPhoneCommand(predicate); + expectedModel.updateFilteredPersonList(predicate); + assertCommandSuccess(command, model, expectedMessage, expectedModel); + assertEquals(Collections.emptyList(), model.getFilteredPersonList()); + } + + @Test + public void toStringMethod() { + PhoneContainsKeywordsPredicate predicate = new PhoneContainsKeywordsPredicate(Arrays.asList("989739")); + FindPhoneCommand findPhoneCommand = new FindPhoneCommand(predicate); + String expected = FindPhoneCommand.class.getCanonicalName() + "{predicate=" + predicate + "}"; + assertEquals(expected, findPhoneCommand.toString()); + } + + /** + * Parses {@code userInput} into a {@code PhoneContainsKeywordsPredicate}. + */ + private PhoneContainsKeywordsPredicate preparePredicate(String userInput) { + return new PhoneContainsKeywordsPredicate(Arrays.asList(userInput.split("\\s+"))); + } +} diff --git a/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java b/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java index 9e9d0fde8db..32a37968d24 100644 --- a/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java @@ -23,13 +23,14 @@ public void parse_emptyArg_throwsParseException() { } @Test - public void parse_missingNamePrefix_throwsParseException() { + public void parse_missingPrefix_throwsParseException() { assertParseFailure(parser, "find amy", String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE)); } + @Test - public void parse_validArgs_returnsFindCommand() { + public void parse_validFindNameArgs_returnsFindNameCommand() { // no leading and trailing whitespaces FindNameCommand expectedFindCommand = new FindNameCommand(new NameContainsKeywordsPredicate(Arrays.asList("Alice", "Bob"))); From a79a35192874ed6d370b08e412c4a282d2a87483 Mon Sep 17 00:00:00 2001 From: tingxuanp Date: Tue, 15 Oct 2024 00:49:35 +0800 Subject: [PATCH 09/33] Fix checkstyle violations --- .../address/logic/commands/FindCommand.java | 1 - .../commands/FindAddressCommandTest.java | 19 +++++++------------ 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/src/main/java/seedu/address/logic/commands/FindCommand.java b/src/main/java/seedu/address/logic/commands/FindCommand.java index 4c6b8187f50..43eba662163 100644 --- a/src/main/java/seedu/address/logic/commands/FindCommand.java +++ b/src/main/java/seedu/address/logic/commands/FindCommand.java @@ -1,6 +1,5 @@ package seedu.address.logic.commands; -import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; /** diff --git a/src/test/java/seedu/address/logic/commands/FindAddressCommandTest.java b/src/test/java/seedu/address/logic/commands/FindAddressCommandTest.java index 88f9a042669..68eb6ec05a2 100644 --- a/src/test/java/seedu/address/logic/commands/FindAddressCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/FindAddressCommandTest.java @@ -6,7 +6,11 @@ import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; import static seedu.address.logic.commands.FindAddressCommand.MESSAGE_FIND_ADDRESS_PERSON_SUCCESS; import static seedu.address.logic.commands.FindCommand.MESSAGE_FIND_PERSON_UNSUCCESSFUL; -import static seedu.address.testutil.TypicalPersons.*; +import static seedu.address.testutil.TypicalPersons.ALICE; +import static seedu.address.testutil.TypicalPersons.BENSON; +import static seedu.address.testutil.TypicalPersons.CARL; +import static seedu.address.testutil.TypicalPersons.ELLE; +import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; import java.util.Arrays; import java.util.Collections; @@ -49,16 +53,6 @@ public void equals() { assertFalse(findFirstCommand.equals(findSecondCommand)); } -// @Test -// public void execute_emptyString_noPersonFound() { -// String expectedMessage = MESSAGE_FIND_PERSON_UNSUCCESSFUL; -// AddressContainsKeywordsPredicate predicate = preparePredicate(" "); -// FindAddressCommand command = new FindAddressCommand(predicate); -// expectedModel.updateFilteredPersonList(predicate); -// assertCommandSuccess(command, model, expectedMessage, expectedModel); -// assertEquals(Collections.emptyList(), model.getFilteredPersonList()); -// } - @Test public void execute_fullMatch_singlePersonFound() { AddressContainsKeywordsPredicate predicate = preparePredicate("311, Clementi Ave 2, #02-25"); @@ -121,7 +115,8 @@ public void execute_absentPartialMatchKeyword2_noPersonFound() { @Test public void toStringMethod() { - AddressContainsKeywordsPredicate predicate = new AddressContainsKeywordsPredicate(Arrays.asList("34 Tanah Merah")); + AddressContainsKeywordsPredicate predicate = + new AddressContainsKeywordsPredicate(Arrays.asList("34 Tanah Merah")); FindAddressCommand findPhoneCommand = new FindAddressCommand(predicate); String expected = FindAddressCommand.class.getCanonicalName() + "{predicate=" + predicate + "}"; assertEquals(expected, findPhoneCommand.toString()); From 159cfce40b6caa763b23ead60ac2da1ce9117501 Mon Sep 17 00:00:00 2001 From: Ricco Lim Date: Tue, 15 Oct 2024 01:53:37 +0800 Subject: [PATCH 10/33] WIP Combine `Filter` into `Find` --- .../address/logic/commands/FindCommand.java | 15 ++++--- .../person/NameContainsKeywordsPredicate.java | 19 ++------- .../person/TagContainsKeywordsPredicate.java | 14 ++----- .../TraitContainsKeywordsPredicate.java | 42 +++++++++++++++++++ 4 files changed, 58 insertions(+), 32 deletions(-) create mode 100644 src/main/java/seedu/address/model/person/TraitContainsKeywordsPredicate.java diff --git a/src/main/java/seedu/address/logic/commands/FindCommand.java b/src/main/java/seedu/address/logic/commands/FindCommand.java index c8d2140ff54..e68f19c582b 100644 --- a/src/main/java/seedu/address/logic/commands/FindCommand.java +++ b/src/main/java/seedu/address/logic/commands/FindCommand.java @@ -5,6 +5,8 @@ import seedu.address.commons.util.ToStringBuilder; import seedu.address.model.Model; import seedu.address.model.person.NameContainsKeywordsPredicate; +import seedu.address.model.person.TagContainsKeywordsPredicate; +import seedu.address.model.person.TraitContainsKeywordsPredicate; /** * Finds and lists all persons in address book whose name contains any of the argument keywords. @@ -23,16 +25,20 @@ public class FindCommand extends Command { public static final String MESSAGE_FIND_PERSON_UNSUCCESSFUL = "No contacts found."; - private final NameContainsKeywordsPredicate predicate; + private final TraitContainsKeywordsPredicate predicate; - public FindCommand(NameContainsKeywordsPredicate predicate) { + public FindCommand(TraitContainsKeywordsPredicate predicate) { this.predicate = predicate; } @Override public CommandResult execute(Model model) { requireNonNull(model); - model.updateFilteredPersonList(predicate); + if (predicate instanceof NameContainsKeywordsPredicate namePredicate) { + model.updateFilteredPersonList(namePredicate); + } else if (predicate instanceof TagContainsKeywordsPredicate tagPredicate) { + model.updateFilteredPersonListByTag(tagPredicate); + } if (!model.getFilteredPersonList().isEmpty()) { return new CommandResult(String.format(MESSAGE_FIND_PERSON_SUCCESS, predicate.getDisplayString())); @@ -48,11 +54,10 @@ public boolean equals(Object other) { } // instanceof handles nulls - if (!(other instanceof FindCommand)) { + if (!(other instanceof FindCommand otherFindCommand)) { return false; } - FindCommand otherFindCommand = (FindCommand) other; return predicate.equals(otherFindCommand.predicate); } diff --git a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java index 732e74c5ebe..abd7ce89166 100644 --- a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java +++ b/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java @@ -1,19 +1,16 @@ package seedu.address.model.person; import java.util.List; -import java.util.function.Predicate; import seedu.address.commons.util.StringUtil; -import seedu.address.commons.util.ToStringBuilder; /** * Tests that a {@code Person}'s {@code Name} matches any of the keywords given. */ -public class NameContainsKeywordsPredicate implements Predicate { - private final List keywords; +public class NameContainsKeywordsPredicate extends TraitContainsKeywordsPredicate { public NameContainsKeywordsPredicate(List keywords) { - this.keywords = keywords; + super(keywords); } @Override @@ -29,20 +26,10 @@ public boolean equals(Object other) { } // instanceof handles nulls - if (!(other instanceof NameContainsKeywordsPredicate)) { + if (!(other instanceof NameContainsKeywordsPredicate otherNameContainsKeywordsPredicate)) { return false; } - NameContainsKeywordsPredicate otherNameContainsKeywordsPredicate = (NameContainsKeywordsPredicate) other; return keywords.equals(otherNameContainsKeywordsPredicate.keywords); } - - @Override - public String toString() { - return new ToStringBuilder(this).add("keywords", keywords).toString(); - } - - public String getDisplayString() { - return String.join(", ", keywords); - } } diff --git a/src/main/java/seedu/address/model/person/TagContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/person/TagContainsKeywordsPredicate.java index 361bb2fca7a..3bd564acff3 100644 --- a/src/main/java/seedu/address/model/person/TagContainsKeywordsPredicate.java +++ b/src/main/java/seedu/address/model/person/TagContainsKeywordsPredicate.java @@ -1,20 +1,17 @@ package seedu.address.model.person; import java.util.List; -import java.util.function.Predicate; import seedu.address.commons.util.StringUtil; -import seedu.address.commons.util.ToStringBuilder; import seedu.address.model.tag.Tag; /** - * Tests that a {@code Person}'s {@code Tag } matches any of the keywords given. + * Tests that a {@code Person}'s {@code Tag} matches any of the keywords given. */ -public class TagContainsKeywordsPredicate implements Predicate { - private final List keywords; +public class TagContainsKeywordsPredicate extends TraitContainsKeywordsPredicate { public TagContainsKeywordsPredicate(List keywords) { - this.keywords = keywords; + super(keywords); } @Override @@ -36,9 +33,4 @@ public boolean equals(Object other) { return keywords.equals(otherNameContainsKeywordsPredicate.keywords); } - - @Override - public String toString() { - return new ToStringBuilder(this).add("keywords", keywords).toString(); - } } diff --git a/src/main/java/seedu/address/model/person/TraitContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/person/TraitContainsKeywordsPredicate.java new file mode 100644 index 00000000000..7355a34393f --- /dev/null +++ b/src/main/java/seedu/address/model/person/TraitContainsKeywordsPredicate.java @@ -0,0 +1,42 @@ +package seedu.address.model.person; + +import java.util.List; +import java.util.function.Predicate; + +import seedu.address.commons.util.ToStringBuilder; + +/** + * Tests that a {@code Person}'s trait (eg: Tag, Name) matches any of the keywords given. + */ +public abstract class TraitContainsKeywordsPredicate implements Predicate { + protected final List keywords; + public TraitContainsKeywordsPredicate(List keywords) { + this.keywords = keywords; + } + + @Override + public abstract boolean test(T t); + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + // instanceof handles nulls + if (!(other instanceof TraitContainsKeywordsPredicate otherNameContainsKeywordsPredicate)) { + return false; + } + + return keywords.equals(otherNameContainsKeywordsPredicate.keywords); + } + + @Override + public String toString() { + return new ToStringBuilder(this).add("keywords", keywords).toString(); + } + + public String getDisplayString() { + return String.join(", ", keywords); + } +} From 40bcb0ad62df0f86cb2e006823d6e5869c5b4120 Mon Sep 17 00:00:00 2001 From: tingxuanp Date: Wed, 16 Oct 2024 00:15:38 +0800 Subject: [PATCH 11/33] Add predicate tests --- .../parser/FindAddressCommandParser.java | 7 ++ .../logic/parser/FindEmailCommandParser.java | 7 ++ .../logic/parser/FindNameCommandParser.java | 7 ++ .../logic/parser/FindPhoneCommandParser.java | 7 ++ .../AddressContainsKeywordsPredicateTest.java | 82 +++++++++++++++++ .../EmailContainsKeywordsPredicateTest.java | 89 +++++++++++++++++++ .../PhoneContainsKeywordsPredicateTest.java | 89 +++++++++++++++++++ 7 files changed, 288 insertions(+) create mode 100644 src/main/java/seedu/address/logic/parser/FindAddressCommandParser.java create mode 100644 src/main/java/seedu/address/logic/parser/FindEmailCommandParser.java create mode 100644 src/main/java/seedu/address/logic/parser/FindNameCommandParser.java create mode 100644 src/main/java/seedu/address/logic/parser/FindPhoneCommandParser.java create mode 100644 src/test/java/seedu/address/model/person/AddressContainsKeywordsPredicateTest.java create mode 100644 src/test/java/seedu/address/model/person/EmailContainsKeywordsPredicateTest.java create mode 100644 src/test/java/seedu/address/model/person/PhoneContainsKeywordsPredicateTest.java diff --git a/src/main/java/seedu/address/logic/parser/FindAddressCommandParser.java b/src/main/java/seedu/address/logic/parser/FindAddressCommandParser.java new file mode 100644 index 00000000000..44d5aee1952 --- /dev/null +++ b/src/main/java/seedu/address/logic/parser/FindAddressCommandParser.java @@ -0,0 +1,7 @@ +package seedu.address.logic.parser; + +/** + * Parses input arguments and creates a new FindAddressCommand object + */ +public class FindAddressCommandParser { +} diff --git a/src/main/java/seedu/address/logic/parser/FindEmailCommandParser.java b/src/main/java/seedu/address/logic/parser/FindEmailCommandParser.java new file mode 100644 index 00000000000..caa9017317a --- /dev/null +++ b/src/main/java/seedu/address/logic/parser/FindEmailCommandParser.java @@ -0,0 +1,7 @@ +package seedu.address.logic.parser; + +/** + * Parses input arguments and creates a new FindEmailCommand object + */ +public class FindEmailCommandParser { +} diff --git a/src/main/java/seedu/address/logic/parser/FindNameCommandParser.java b/src/main/java/seedu/address/logic/parser/FindNameCommandParser.java new file mode 100644 index 00000000000..0be234117df --- /dev/null +++ b/src/main/java/seedu/address/logic/parser/FindNameCommandParser.java @@ -0,0 +1,7 @@ +package seedu.address.logic.parser; + +/** + * Parses input arguments and creates a new FindNameCommand object + */ +public class FindNameCommandParser { +} diff --git a/src/main/java/seedu/address/logic/parser/FindPhoneCommandParser.java b/src/main/java/seedu/address/logic/parser/FindPhoneCommandParser.java new file mode 100644 index 00000000000..e25a4afc282 --- /dev/null +++ b/src/main/java/seedu/address/logic/parser/FindPhoneCommandParser.java @@ -0,0 +1,7 @@ +package seedu.address.logic.parser; + +/** + * Parses input arguments and creates a new FindPhoneCommand object + */ +public class FindPhoneCommandParser { +} diff --git a/src/test/java/seedu/address/model/person/AddressContainsKeywordsPredicateTest.java b/src/test/java/seedu/address/model/person/AddressContainsKeywordsPredicateTest.java new file mode 100644 index 00000000000..5278431cb7e --- /dev/null +++ b/src/test/java/seedu/address/model/person/AddressContainsKeywordsPredicateTest.java @@ -0,0 +1,82 @@ +package seedu.address.model.person; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.junit.jupiter.api.Test; + +import seedu.address.testutil.PersonBuilder; + +public class AddressContainsKeywordsPredicateTest { + + @Test + public void equals() { + List firstPredicateKeywordList = Collections.singletonList("5, Tampines Street 13, #02-03"); + List secondPredicateKeywordList = Arrays.asList("Main street", "Dhoby Ghaut Street 11"); + + AddressContainsKeywordsPredicate firstPredicate = + new AddressContainsKeywordsPredicate(firstPredicateKeywordList); + AddressContainsKeywordsPredicate secondPredicate = + new AddressContainsKeywordsPredicate(secondPredicateKeywordList); + + // same object -> returns true + assertTrue(firstPredicate.equals(firstPredicate)); + + // same values -> returns true + AddressContainsKeywordsPredicate firstPredicateCopy = + new AddressContainsKeywordsPredicate(firstPredicateKeywordList); + assertTrue(firstPredicate.equals(firstPredicateCopy)); + + // different types -> returns false + assertFalse(firstPredicate.equals(1)); + + // null -> returns false + assertFalse(firstPredicate.equals(null)); + + // different person -> returns false + assertFalse(firstPredicate.equals(secondPredicate)); + } + + @Test + public void test_addressContainsKeywords_returnsTrue() { + // One full-matching keyword + AddressContainsKeywordsPredicate predicate = + new AddressContainsKeywordsPredicate(Arrays.asList("74 University Town, #04-02")); + assertTrue(predicate.test(new PersonBuilder().withAddress("74 University Town, #04-02").build())); + + // One full-matching keyword + predicate = new AddressContainsKeywordsPredicate(Arrays.asList("73 Jurong Island, #02-04")); + assertTrue(predicate.test(new PersonBuilder().withAddress("73 Jurong Island, #02-04").build())); + + // One partial-matching keyword + predicate = new AddressContainsKeywordsPredicate(Arrays.asList("University Town")); + assertTrue(predicate.test(new PersonBuilder().withAddress("74 University Town, #04-02").build())); + } + + @Test + public void test_addressDoesNotContainKeywords_returnsFalse() { + // Non-matching keyword + AddressContainsKeywordsPredicate predicate = new AddressContainsKeywordsPredicate(Arrays.asList("Sentosa")); + assertFalse(predicate.test(new PersonBuilder().withAddress("8 Little India #02-04").build())); + + // Keywords match name, email and phone, but does not match address + predicate = new AddressContainsKeywordsPredicate(Arrays.asList("Alice", "12345", + "alice@email.com", "West", "Street")); + assertFalse(predicate.test(new PersonBuilder().withName("Alice").withPhone("12345") + .withEmail("alice@email.com").withAddress("Main Street").build())); + } + + @Test + public void toStringMethod() { + List keywords = List.of("58 Eunos Link, #02-04", "364 Ubi Avenue 3"); + AddressContainsKeywordsPredicate predicate = new AddressContainsKeywordsPredicate(keywords); + + String expected = AddressContainsKeywordsPredicate.class.getCanonicalName() + "{keywords=" + keywords + "}"; + assertEquals(expected, predicate.toString()); + } +} diff --git a/src/test/java/seedu/address/model/person/EmailContainsKeywordsPredicateTest.java b/src/test/java/seedu/address/model/person/EmailContainsKeywordsPredicateTest.java new file mode 100644 index 00000000000..bd18478a6fc --- /dev/null +++ b/src/test/java/seedu/address/model/person/EmailContainsKeywordsPredicateTest.java @@ -0,0 +1,89 @@ +package seedu.address.model.person; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.junit.jupiter.api.Test; + +import seedu.address.testutil.PersonBuilder; + +public class EmailContainsKeywordsPredicateTest { + + @Test + public void equals() { + List firstPredicateKeywordList = Collections.singletonList("andy@yahoo.com"); + List secondPredicateKeywordList = Arrays.asList("pris@gmail.com", "prisha@hotmail.com"); + + EmailContainsKeywordsPredicate firstPredicate = new EmailContainsKeywordsPredicate(firstPredicateKeywordList); + EmailContainsKeywordsPredicate secondPredicate = new EmailContainsKeywordsPredicate(secondPredicateKeywordList); + + // same object -> returns true + assertTrue(firstPredicate.equals(firstPredicate)); + + // same values -> returns true + EmailContainsKeywordsPredicate firstPredicateCopy = + new EmailContainsKeywordsPredicate(firstPredicateKeywordList); + assertTrue(firstPredicate.equals(firstPredicateCopy)); + + // different types -> returns false + assertFalse(firstPredicate.equals(1)); + + // null -> returns false + assertFalse(firstPredicate.equals(null)); + + // different person -> returns false + assertFalse(firstPredicate.equals(secondPredicate)); + } + + @Test + public void test_nameContainsKeywords_returnsTrue() { + // One full-matching keyword + EmailContainsKeywordsPredicate predicate = + new EmailContainsKeywordsPredicate(Collections.singletonList("alice@email.com")); + assertTrue(predicate.test(new PersonBuilder().withEmail("alice@email.com").build())); + + // Only one matching keyword + predicate = new EmailContainsKeywordsPredicate(Arrays.asList("sam", "laura")); + assertTrue(predicate.test(new PersonBuilder().withEmail("sam@email.com").build())); + + // Mixed-case keywords + predicate = new EmailContainsKeywordsPredicate(Arrays.asList("aLIce", "bOB")); + assertTrue(predicate.test(new PersonBuilder().withEmail("bob@email.com").build())); + + // Partial matching keyword + predicate = new EmailContainsKeywordsPredicate(Arrays.asList("lly")); + assertTrue(predicate.test(new PersonBuilder().withEmail("sally@email.com").build())); + + } + + @Test + public void test_nameDoesNotContainKeywords_returnsFalse() { + // Zero keywords + EmailContainsKeywordsPredicate predicate = new EmailContainsKeywordsPredicate(Collections.emptyList()); + assertFalse(predicate.test(new PersonBuilder().withEmail("charlie@yahoo.com").build())); + + // Non-matching keyword + predicate = new EmailContainsKeywordsPredicate(Arrays.asList("chris")); + assertFalse(predicate.test(new PersonBuilder().withEmail("daniel@email.com").build())); + + // Keywords match name, phone and email, but does not match email + predicate = new EmailContainsKeywordsPredicate(Arrays.asList("Alice", "12345", + "alice@email.com", "Main", "Street")); + assertFalse(predicate.test(new PersonBuilder().withName("Alice").withPhone("12345") + .withEmail("alex@email.com").withAddress("Main Street").build())); + } + + @Test + public void toStringMethod() { + List keywords = List.of("tammy384@email.com", "josh304@gmail.com"); + EmailContainsKeywordsPredicate predicate = new EmailContainsKeywordsPredicate(keywords); + + String expected = EmailContainsKeywordsPredicate.class.getCanonicalName() + "{keywords=" + keywords + "}"; + assertEquals(expected, predicate.toString()); + } +} diff --git a/src/test/java/seedu/address/model/person/PhoneContainsKeywordsPredicateTest.java b/src/test/java/seedu/address/model/person/PhoneContainsKeywordsPredicateTest.java new file mode 100644 index 00000000000..8bd95a4d613 --- /dev/null +++ b/src/test/java/seedu/address/model/person/PhoneContainsKeywordsPredicateTest.java @@ -0,0 +1,89 @@ +package seedu.address.model.person; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.junit.jupiter.api.Test; + +import seedu.address.testutil.PersonBuilder; + +public class PhoneContainsKeywordsPredicateTest { + + @Test + public void equals() { + List firstPredicateKeywordList = Collections.singletonList("938493"); + List secondPredicateKeywordList = Arrays.asList("83748", "10293"); + + PhoneContainsKeywordsPredicate firstPredicate = new PhoneContainsKeywordsPredicate(firstPredicateKeywordList); + PhoneContainsKeywordsPredicate secondPredicate = + new PhoneContainsKeywordsPredicate(secondPredicateKeywordList); + + // same object -> returns true + assertTrue(firstPredicate.equals(firstPredicate)); + + // same values -> returns true + PhoneContainsKeywordsPredicate firstPredicateCopy = + new PhoneContainsKeywordsPredicate(firstPredicateKeywordList); + assertTrue(firstPredicate.equals(firstPredicateCopy)); + + // different types -> returns false + assertFalse(firstPredicate.equals(1)); + + // null -> returns false + assertFalse(firstPredicate.equals(null)); + + // different person -> returns false + assertFalse(firstPredicate.equals(secondPredicate)); + } + + @Test + public void test_phoneContainsKeywords_returnsTrue() { + // One full-matching keyword + PhoneContainsKeywordsPredicate predicate = new PhoneContainsKeywordsPredicate(Arrays.asList("10293")); + assertTrue(predicate.test(new PersonBuilder().withPhone("10293").build())); + + // One full-matching keyword + predicate = new PhoneContainsKeywordsPredicate(Arrays.asList("3847384", "1237685")); + assertTrue(predicate.test(new PersonBuilder().withPhone("1237685").build())); + + // One partial-matching keyword + predicate = new PhoneContainsKeywordsPredicate(Arrays.asList("234")); + assertTrue(predicate.test(new PersonBuilder().withPhone("38490234").build())); + } + + @Test + public void test_phoneDoesNotContainKeywords_returnsFalse() { + // Zero keywords + PhoneContainsKeywordsPredicate predicate = new PhoneContainsKeywordsPredicate(Collections.emptyList()); + assertFalse(predicate.test(new PersonBuilder().withPhone("98765432").build())); + + // Non-matching keyword + predicate = new PhoneContainsKeywordsPredicate(Arrays.asList("123")); + assertFalse(predicate.test(new PersonBuilder().withPhone("87654").build())); + + // Non-matching keywords + predicate = new PhoneContainsKeywordsPredicate(Arrays.asList("5960, 856")); + assertFalse(predicate.test(new PersonBuilder().withPhone("87654").build())); + + // Keywords match name, email and address, but does not match phone + predicate = new PhoneContainsKeywordsPredicate(Arrays.asList("Alice", "12345", + "alice@email.com", "Main", "Street")); + assertFalse(predicate.test(new PersonBuilder().withName("Alice").withPhone("5768") + .withEmail("alice@email.com").withAddress("Main Street").build())); + } + + @Test + public void toStringMethod() { + List keywords = List.of("238958", "203498549"); + PhoneContainsKeywordsPredicate predicate = new PhoneContainsKeywordsPredicate(keywords); + + String expected = PhoneContainsKeywordsPredicate.class.getCanonicalName() + "{keywords=" + keywords + "}"; + assertEquals(expected, predicate.toString()); + } + +} From cf3e1e39f4f21430abb23162279ead629164d994 Mon Sep 17 00:00:00 2001 From: tingxuanp Date: Wed, 16 Oct 2024 00:54:25 +0800 Subject: [PATCH 12/33] Add testing for find command parser --- .../parser/FindAddressCommandParser.java | 7 - .../logic/parser/FindEmailCommandParser.java | 7 - .../logic/parser/FindNameCommandParser.java | 7 - .../logic/parser/FindPhoneCommandParser.java | 7 - .../logic/parser/FindCommandParserTest.java | 136 +++++++++++++++++- 5 files changed, 135 insertions(+), 29 deletions(-) delete mode 100644 src/main/java/seedu/address/logic/parser/FindAddressCommandParser.java delete mode 100644 src/main/java/seedu/address/logic/parser/FindEmailCommandParser.java delete mode 100644 src/main/java/seedu/address/logic/parser/FindNameCommandParser.java delete mode 100644 src/main/java/seedu/address/logic/parser/FindPhoneCommandParser.java diff --git a/src/main/java/seedu/address/logic/parser/FindAddressCommandParser.java b/src/main/java/seedu/address/logic/parser/FindAddressCommandParser.java deleted file mode 100644 index 44d5aee1952..00000000000 --- a/src/main/java/seedu/address/logic/parser/FindAddressCommandParser.java +++ /dev/null @@ -1,7 +0,0 @@ -package seedu.address.logic.parser; - -/** - * Parses input arguments and creates a new FindAddressCommand object - */ -public class FindAddressCommandParser { -} diff --git a/src/main/java/seedu/address/logic/parser/FindEmailCommandParser.java b/src/main/java/seedu/address/logic/parser/FindEmailCommandParser.java deleted file mode 100644 index caa9017317a..00000000000 --- a/src/main/java/seedu/address/logic/parser/FindEmailCommandParser.java +++ /dev/null @@ -1,7 +0,0 @@ -package seedu.address.logic.parser; - -/** - * Parses input arguments and creates a new FindEmailCommand object - */ -public class FindEmailCommandParser { -} diff --git a/src/main/java/seedu/address/logic/parser/FindNameCommandParser.java b/src/main/java/seedu/address/logic/parser/FindNameCommandParser.java deleted file mode 100644 index 0be234117df..00000000000 --- a/src/main/java/seedu/address/logic/parser/FindNameCommandParser.java +++ /dev/null @@ -1,7 +0,0 @@ -package seedu.address.logic.parser; - -/** - * Parses input arguments and creates a new FindNameCommand object - */ -public class FindNameCommandParser { -} diff --git a/src/main/java/seedu/address/logic/parser/FindPhoneCommandParser.java b/src/main/java/seedu/address/logic/parser/FindPhoneCommandParser.java deleted file mode 100644 index e25a4afc282..00000000000 --- a/src/main/java/seedu/address/logic/parser/FindPhoneCommandParser.java +++ /dev/null @@ -1,7 +0,0 @@ -package seedu.address.logic.parser; - -/** - * Parses input arguments and creates a new FindPhoneCommand object - */ -public class FindPhoneCommandParser { -} diff --git a/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java b/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java index 32a37968d24..8505d01f197 100644 --- a/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java @@ -1,5 +1,7 @@ package seedu.address.logic.parser; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure; import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess; @@ -8,9 +10,16 @@ import org.junit.jupiter.api.Test; +import seedu.address.logic.commands.FindAddressCommand; import seedu.address.logic.commands.FindCommand; +import seedu.address.logic.commands.FindEmailCommand; import seedu.address.logic.commands.FindNameCommand; +import seedu.address.logic.commands.FindPhoneCommand; +import seedu.address.logic.parser.exceptions.ParseException; +import seedu.address.model.person.AddressContainsKeywordsPredicate; +import seedu.address.model.person.EmailContainsKeywordsPredicate; import seedu.address.model.person.NameContainsKeywordsPredicate; +import seedu.address.model.person.PhoneContainsKeywordsPredicate; public class FindCommandParserTest { @@ -28,7 +37,6 @@ public void parse_missingPrefix_throwsParseException() { String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE)); } - @Test public void parse_validFindNameArgs_returnsFindNameCommand() { // no leading and trailing whitespaces @@ -40,4 +48,130 @@ public void parse_validFindNameArgs_returnsFindNameCommand() { assertParseSuccess(parser, "find n/ \n Alice \n \t Bob \t", expectedFindCommand); } + @Test + public void parse_missingNameAfterPrefix_throwsParseException() { + String input = "find n/"; // Input with empty name prefix + ParseException thrown = assertThrows(ParseException.class, () -> { + parser.parse(input); + }); + + // Check for correct error message + assertEquals("Name cannot be empty!", thrown.getMessage()); + + } + + @Test + public void parse_missingNameWithTrailingWhiteSpace_throwsParseException() { + String input = "find n/ \n \t"; // Input with empty name prefix + ParseException thrown = assertThrows(ParseException.class, () -> { + parser.parse(input); + }); + + // Check for correct error message + assertEquals("Name cannot be empty!", thrown.getMessage()); + } + + @Test + public void parse_validFindAddressArgs_returnsFindAddressCommand() { + // no leading and trailing whitespaces + FindAddressCommand expectedFindCommand = + new FindAddressCommand(new AddressContainsKeywordsPredicate(Arrays.asList("5,", "Clementi", + "Ave", "4,", "#03-945"))); + assertParseSuccess(parser, "find a/5, Clementi Ave 4, #03-945", expectedFindCommand); + + // multiple whitespaces between keywords + assertParseSuccess(parser, "find a/ \n5, Clementi Ave 4, \t #03-945 \t", expectedFindCommand); + } + + @Test + public void parse_missingAddressAfterPrefix_throwsParseException() { + String input = "find a/"; // Input with empty name prefix + ParseException thrown = assertThrows(ParseException.class, () -> { + parser.parse(input); + }); + + // Check for correct error message + assertEquals("Address cannot be empty!", thrown.getMessage()); + + } + + @Test + public void missingAddressWithTrailingWhiteSpace_throwsParseException() { + String input = "find a/ \t \n"; // Input with empty name prefix + ParseException thrown = assertThrows(ParseException.class, () -> { + parser.parse(input); + }); + + // Check for correct error message + assertEquals("Address cannot be empty!", thrown.getMessage()); + } + + @Test + public void parse_validFindPhoneArgs_returnsFindPhoneCommand() { + // no leading and trailing whitespaces + FindPhoneCommand expectedFindCommand = + new FindPhoneCommand(new PhoneContainsKeywordsPredicate(Arrays.asList("91234567"))); + assertParseSuccess(parser, "find p/91234567", expectedFindCommand); + + // multiple whitespaces between keywords + assertParseSuccess(parser, "find p/ \n91234567 \t", expectedFindCommand); + } + + @Test + public void parse_missingPhoneAfterPrefix_throwsParseException() { + String input = "find p/"; // Input with empty name prefix + ParseException thrown = assertThrows(ParseException.class, () -> { + parser.parse(input); + }); + + // Check for correct error message + assertEquals("Phone number cannot be empty!", thrown.getMessage()); + + } + + @Test + public void parse_missingPhoneWithTrailingWhiteSpace_throwsParseException() { + String input = "find p/ \n \t"; // Input with empty name prefix + ParseException thrown = assertThrows(ParseException.class, () -> { + parser.parse(input); + }); + + // Check for correct error message + assertEquals("Phone number cannot be empty!", thrown.getMessage()); + } + + @Test + public void parse_validFindEmailArgs_returnsFindEmailCommand() { + // no leading and trailing whitespaces + FindEmailCommand expectedFindCommand = + new FindEmailCommand(new EmailContainsKeywordsPredicate(Arrays.asList("carlos@gmail.com"))); + assertParseSuccess(parser, "find e/carlos@gmail.com", expectedFindCommand); + + // multiple whitespaces between keywords + assertParseSuccess(parser, "find e/ \t carlos@gmail.com", expectedFindCommand); + } + + @Test + public void parse_missingEmailAfterPrefix_throwsParseException() { + String input = "find e/"; // Input with empty name prefix + ParseException thrown = assertThrows(ParseException.class, () -> { + parser.parse(input); + }); + + // Check for correct error message + assertEquals("Email address cannot be empty!", thrown.getMessage()); + + } + + @Test + public void parse_missingEmailWithTrailingWhiteSpace_throwsParseException() { + String input = "find e/ \n \t"; // Input with empty name prefix + ParseException thrown = assertThrows(ParseException.class, () -> { + parser.parse(input); + }); + + // Check for correct error message + assertEquals("Email address cannot be empty!", thrown.getMessage()); + } + } From ec039102b9b415ada8d04f867e486315289efd8c Mon Sep 17 00:00:00 2001 From: DanzaSeah Date: Wed, 16 Oct 2024 12:25:44 +0800 Subject: [PATCH 13/33] Add test cases and modify comments --- .../parser/TaggingCommandParserUtil.java | 7 ++-- .../logic/parser/TagCommandParserTest.java | 9 +++-- .../parser/TaggingCommandParserUtilTest.java | 35 +++++++++++++++++-- .../logic/parser/UntagCommandParserTest.java | 9 +++-- 4 files changed, 42 insertions(+), 18 deletions(-) diff --git a/src/main/java/seedu/address/logic/parser/TaggingCommandParserUtil.java b/src/main/java/seedu/address/logic/parser/TaggingCommandParserUtil.java index f3f305fe478..7532d9dff25 100644 --- a/src/main/java/seedu/address/logic/parser/TaggingCommandParserUtil.java +++ b/src/main/java/seedu/address/logic/parser/TaggingCommandParserUtil.java @@ -32,11 +32,8 @@ public static Pair> parseIndexAndTags(ArgumentMultimap argMultim throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, messageUsage)); } - try { - index = ParserUtil.parseIndex(argMultimap.getPreamble()); - } catch (ParseException pe) { - throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, messageUsage), pe); - } + index = ParserUtil.parseIndex(argMultimap.getPreamble()); + Set tagValues = ParserUtil.parseTags(argMultimap.getAllValues(PREFIX_TAG)); return new Pair<>(index, new HashSet<>(tagValues)); diff --git a/src/test/java/seedu/address/logic/parser/TagCommandParserTest.java b/src/test/java/seedu/address/logic/parser/TagCommandParserTest.java index fb368ef87d1..55742a6365d 100644 --- a/src/test/java/seedu/address/logic/parser/TagCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/TagCommandParserTest.java @@ -3,6 +3,7 @@ import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure; import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess; +import static seedu.address.logic.parser.ParserUtil.MESSAGE_INVALID_INDEX; import java.util.Arrays; import java.util.HashSet; @@ -36,18 +37,16 @@ public void parse_validArgs_returnsTagCommand() { @Test public void parse_invalidArgs_throwsParseException() { // Invalid index (non-numeric) - assertParseFailure(parser, "a t/colleague", String.format(MESSAGE_INVALID_COMMAND_FORMAT, - TagCommand.MESSAGE_USAGE)); + assertParseFailure(parser, "a t/colleague", MESSAGE_INVALID_INDEX); // Index missing - assertParseFailure(parser, "t/colleague t/gym", String.format(MESSAGE_INVALID_COMMAND_FORMAT, - TagCommand.MESSAGE_USAGE)); + assertParseFailure(parser, "t/colleague t/gym", MESSAGE_INVALID_INDEX); // Missing tags (no tags specified) assertParseFailure(parser, "1", String.format(MESSAGE_INVALID_COMMAND_FORMAT, TagCommand.MESSAGE_USAGE)); - // Tags not in alphanumeric and space format + // Tag descriptions contain non-alphanumeric or space characters assertParseFailure(parser, "1 t/colleague_", TagName.MESSAGE_CONSTRAINTS); } } diff --git a/src/test/java/seedu/address/logic/parser/TaggingCommandParserUtilTest.java b/src/test/java/seedu/address/logic/parser/TaggingCommandParserUtilTest.java index cf0e2f737d6..69c1e34ea96 100644 --- a/src/test/java/seedu/address/logic/parser/TaggingCommandParserUtilTest.java +++ b/src/test/java/seedu/address/logic/parser/TaggingCommandParserUtilTest.java @@ -2,7 +2,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; +import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; +import static seedu.address.logic.parser.ParserUtil.MESSAGE_INVALID_INDEX; import java.util.HashSet; import java.util.Set; @@ -33,13 +35,25 @@ public void parseIndexAndTags_validInput_returnsPair() throws Exception { } @Test - public void parseIndexAndTags_invalidIndex_throwsParseException() { + public void parseIndexAndTags_invalidIndexType_throwsParseException() { String userInput = "a " + PREFIX_TAG + "friend"; ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(userInput, PREFIX_TAG); - assertThrows(ParseException.class, () -> + ParseException thrown = assertThrows(ParseException.class, () -> TaggingCommandParserUtil.parseIndexAndTags(argMultimap, "dummy usage message") ); + assertEquals(MESSAGE_INVALID_INDEX, thrown.getMessage()); + } + + @Test + public void parseIndexAndTags_outOfRangeIndex_throwsParseException() { + String userInput = "-1 " + PREFIX_TAG + "friend"; + ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(userInput, PREFIX_TAG); + + ParseException thrown = assertThrows(ParseException.class, () -> + TaggingCommandParserUtil.parseIndexAndTags(argMultimap, "dummy usage message") + ); + assertEquals(MESSAGE_INVALID_INDEX, thrown.getMessage()); } @Test @@ -47,8 +61,23 @@ public void parseIndexAndTags_missingTags_throwsParseException() { String userInput = "1"; ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(userInput, PREFIX_TAG); - assertThrows(ParseException.class, () -> + ParseException thrown = assertThrows(ParseException.class, () -> + TaggingCommandParserUtil.parseIndexAndTags(argMultimap, "dummy usage message") + ); + assertEquals(String.format(MESSAGE_INVALID_COMMAND_FORMAT, + "dummy usage message"), thrown.getMessage()); + } + + @Test + public void parseIndexAndTags_invalidTagNames_throwsParseException() { + String userInput = "1 " + PREFIX_TAG + "invalidTag_"; + ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(userInput, PREFIX_TAG); + + ParseException thrown = assertThrows(ParseException.class, () -> TaggingCommandParserUtil.parseIndexAndTags(argMultimap, "dummy usage message") ); + + assertEquals(TagName.MESSAGE_CONSTRAINTS, thrown.getMessage()); } + } diff --git a/src/test/java/seedu/address/logic/parser/UntagCommandParserTest.java b/src/test/java/seedu/address/logic/parser/UntagCommandParserTest.java index 4bd2ee06eef..398d077e595 100644 --- a/src/test/java/seedu/address/logic/parser/UntagCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/UntagCommandParserTest.java @@ -3,6 +3,7 @@ import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure; import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess; +import static seedu.address.logic.parser.ParserUtil.MESSAGE_INVALID_INDEX; import java.util.Arrays; import java.util.HashSet; @@ -36,18 +37,16 @@ public void parse_validArgs_returnsUntagCommand() { @Test public void parse_invalidArgs_throwsParseException() { // Invalid index (non-numeric) - assertParseFailure(parser, "a t/colleague", String.format(MESSAGE_INVALID_COMMAND_FORMAT, - UntagCommand.MESSAGE_USAGE)); + assertParseFailure(parser, "a t/colleague", MESSAGE_INVALID_INDEX); // Index missing - assertParseFailure(parser, "t/colleague t/gym", String.format(MESSAGE_INVALID_COMMAND_FORMAT, - UntagCommand.MESSAGE_USAGE)); + assertParseFailure(parser, "t/colleague t/gym", MESSAGE_INVALID_INDEX); // Missing tags (no tags specified) assertParseFailure(parser, "1", String.format(MESSAGE_INVALID_COMMAND_FORMAT, UntagCommand.MESSAGE_USAGE)); - // Tags not in alphanumeric and space format + // Tag descriptions contain non-alphanumeric or space characters assertParseFailure(parser, "1 t/colleague_", TagName.MESSAGE_CONSTRAINTS); } } From 1229cbe119b1f07afc06ce3482d6628c7fc3e9c3 Mon Sep 17 00:00:00 2001 From: tingxuanp Date: Wed, 16 Oct 2024 18:20:32 +0800 Subject: [PATCH 14/33] Update description for find command --- .../seedu/address/logic/commands/FindCommand.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/address/logic/commands/FindCommand.java b/src/main/java/seedu/address/logic/commands/FindCommand.java index 43eba662163..115d7ceb72d 100644 --- a/src/main/java/seedu/address/logic/commands/FindCommand.java +++ b/src/main/java/seedu/address/logic/commands/FindCommand.java @@ -1,6 +1,6 @@ package seedu.address.logic.commands; -import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; +import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; /** * Finds and lists all persons in address book whose name contains any of the argument keywords. @@ -10,10 +10,12 @@ public abstract class FindCommand extends Command { public static final String COMMAND_WORD = "find"; - public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all persons whose names contain any of " - + "the specified keywords (case-insensitive) and displays them as a list with index numbers.\n" - + "Parameters: KEYWORD [MORE_KEYWORDS]...\n" - + "Example: " + COMMAND_WORD + " " + PREFIX_PHONE + " alice charlie"; + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all persons based on the specified keywords " + + "(case-insensitive) after the prefix representing the field, " + + "and displays them as a list with index numbers.\n" + + "Use 'n/' to search by name, 'a/' to search by address etc. \n" + + "Parameters: PREFIX/ KEYWORDS [MORE_KEYWORDS]...\n" + + "Example: " + COMMAND_WORD + " " + PREFIX_NAME + " alice charlie"; public static final String MESSAGE_FIND_PERSON_UNSUCCESSFUL = "No contacts found."; From ac7cb93c47224d9e7e239a43f0b86e5c2fbcb70e Mon Sep 17 00:00:00 2001 From: Han Bin Date: Wed, 16 Oct 2024 21:29:07 +0800 Subject: [PATCH 15/33] Add testing for Weddings Add test for Wedding functions. --- .../java/seedu/address/logic/Messages.java | 15 +- .../address/logic/commands/AddCommand.java | 4 +- .../logic/commands/AssignWeddingCommand.java | 105 ++++++++++ .../logic/commands/CreateWeddingCommand.java | 73 +++++++ .../logic/commands/DeleteTagCommand.java | 5 +- .../logic/commands/DeleteWeddingCommand.java | 78 ++++++++ .../address/logic/commands/EditCommand.java | 29 ++- .../address/logic/commands/TagCommand.java | 7 +- .../commands/UnassignWeddingCommand.java | 112 +++++++++++ .../address/logic/commands/UntagCommand.java | 114 +++++++++++ .../logic/parser/AddCommandParser.java | 8 +- .../logic/parser/AddressBookParser.java | 10 + .../parser/AssignWeddingCommandParser.java | 76 +++++++ .../seedu/address/logic/parser/CliSyntax.java | 2 +- .../logic/parser/CreateTagCommandParser.java | 8 +- .../parser/CreateWeddingCommandParser.java | 41 ++++ .../logic/parser/DeleteTagCommandParser.java | 7 +- .../parser/DeleteWeddingCommandParser.java | 42 ++++ .../logic/parser/EditCommandParser.java | 22 +- .../address/logic/parser/ParserUtil.java | 29 +++ .../logic/parser/TagCommandParser.java | 2 +- .../parser/UnassignWeddingCommandParser.java | 80 ++++++++ .../logic/parser/UntagCommandParser.java | 58 ++++++ .../java/seedu/address/model/AddressBook.java | 116 +++++++++-- src/main/java/seedu/address/model/Model.java | 36 +++- .../seedu/address/model/ModelManager.java | 46 ++++- .../address/model/ReadOnlyAddressBook.java | 8 + .../seedu/address/model/person/Person.java | 21 +- .../person/TagContainsKeywordsPredicate.java | 2 +- .../WeddingContainsKeywordsPredicate.java | 43 ++++ .../exceptions/PersonNotFoundException.java | 6 +- .../java/seedu/address/model/tag/Tag.java | 8 +- .../java/seedu/address/model/tag/TagName.java | 11 +- .../address/model/tag/UniqueTagList.java | 20 +- .../tag/exceptions/TagNotFoundException.java | 6 +- .../address/model/util/SampleDataUtil.java | 31 ++- .../model/wedding/UniqueWeddingList.java | 149 ++++++++++++++ .../seedu/address/model/wedding/Wedding.java | 108 ++++++++++ .../address/model/wedding/WeddingName.java | 74 +++++++ .../exceptions/DuplicateWeddingException.java | 11 + .../exceptions/WeddingNotFoundException.java | 10 + .../address/storage/JsonAdaptedPerson.java | 24 ++- .../seedu/address/storage/JsonAdaptedTag.java | 1 - .../address/storage/JsonAdaptedWedding.java | 47 +++++ .../storage/JsonSerializableAddressBook.java | 45 ++++- .../java/seedu/address/ui/PersonCard.java | 7 +- src/main/resources/view/DarkTheme.css | 14 ++ src/main/resources/view/PersonListCard.fxml | 20 +- .../invalidAndValidPersonAddressBook.json | 4 +- .../invalidPersonAddressBook.json | 4 +- .../invalidTagAddressBook.json | 10 + .../invalidWeddingAddressBook.json | 10 + .../duplicatePersonAddressBook.json | 4 +- .../duplicateTagAddressBook.json | 11 + .../duplicateWeddingAddressBook.json | 11 + .../invalidPersonAddressBook.json | 3 +- .../invalidTagAddressBook.json | 10 + .../invalidWeddingAddressBook.json | 10 + .../typicalPersonsAddressBook.json | 6 +- .../seedu/address/logic/MessagesTest.java | 3 +- .../logic/commands/AddCommandTest.java | 31 +++ .../logic/commands/CommandTestUtil.java | 4 + .../logic/commands/CreateTagCommandTest.java | 30 +++ .../commands/EditPersonDescriptorTest.java | 3 +- .../logic/commands/TagCommandTest.java | 10 +- .../logic/commands/UntagCommandTest.java | 140 +++++++++++++ .../AssignWeddingCommandParserTest.java | 59 ++++++ .../CreateWeddingCommandParserTest.java | 52 +++++ .../DeleteWeddingCommandParserTest.java | 52 +++++ .../logic/parser/TagCommandParserTest.java | 8 + .../UnassignWeddingCommandParserTest.java | 60 ++++++ .../logic/parser/UntagCommandParserTest.java | 46 +++++ .../seedu/address/model/AddressBookTest.java | 14 +- .../address/model/person/PersonTest.java | 3 +- .../model/wedding/UniqueWeddingListTest.java | 189 ++++++++++++++++++ .../model/wedding/WeddingNameTest.java | 89 +++++++++ .../address/model/wedding/WeddingTest.java | 113 +++++++++++ .../storage/JsonAdaptedPersonTest.java | 31 ++- .../storage/JsonAddressBookStorageTest.java | 10 + .../JsonSerializableAddressBookTest.java | 38 ++++ .../seedu/address/testutil/PersonBuilder.java | 14 +- .../address/testutil/TypicalPersons.java | 6 +- .../seedu/address/testutil/TypicalTags.java | 4 + .../address/testutil/TypicalWeddings.java | 14 ++ 84 files changed, 2784 insertions(+), 113 deletions(-) create mode 100644 src/main/java/seedu/address/logic/commands/AssignWeddingCommand.java create mode 100644 src/main/java/seedu/address/logic/commands/CreateWeddingCommand.java create mode 100644 src/main/java/seedu/address/logic/commands/DeleteWeddingCommand.java create mode 100644 src/main/java/seedu/address/logic/commands/UnassignWeddingCommand.java create mode 100644 src/main/java/seedu/address/logic/commands/UntagCommand.java create mode 100644 src/main/java/seedu/address/logic/parser/AssignWeddingCommandParser.java create mode 100644 src/main/java/seedu/address/logic/parser/CreateWeddingCommandParser.java create mode 100644 src/main/java/seedu/address/logic/parser/DeleteWeddingCommandParser.java create mode 100644 src/main/java/seedu/address/logic/parser/UnassignWeddingCommandParser.java create mode 100644 src/main/java/seedu/address/logic/parser/UntagCommandParser.java create mode 100644 src/main/java/seedu/address/model/person/WeddingContainsKeywordsPredicate.java create mode 100644 src/main/java/seedu/address/model/wedding/UniqueWeddingList.java create mode 100644 src/main/java/seedu/address/model/wedding/Wedding.java create mode 100644 src/main/java/seedu/address/model/wedding/WeddingName.java create mode 100644 src/main/java/seedu/address/model/wedding/exceptions/DuplicateWeddingException.java create mode 100644 src/main/java/seedu/address/model/wedding/exceptions/WeddingNotFoundException.java create mode 100644 src/main/java/seedu/address/storage/JsonAdaptedWedding.java create mode 100644 src/test/data/JsonAddressBookStorageTest/invalidTagAddressBook.json create mode 100644 src/test/data/JsonAddressBookStorageTest/invalidWeddingAddressBook.json create mode 100644 src/test/data/JsonSerializableAddressBookTest/duplicateTagAddressBook.json create mode 100644 src/test/data/JsonSerializableAddressBookTest/duplicateWeddingAddressBook.json create mode 100644 src/test/data/JsonSerializableAddressBookTest/invalidTagAddressBook.json create mode 100644 src/test/data/JsonSerializableAddressBookTest/invalidWeddingAddressBook.json create mode 100644 src/test/java/seedu/address/logic/commands/UntagCommandTest.java create mode 100644 src/test/java/seedu/address/logic/parser/AssignWeddingCommandParserTest.java create mode 100644 src/test/java/seedu/address/logic/parser/CreateWeddingCommandParserTest.java create mode 100644 src/test/java/seedu/address/logic/parser/DeleteWeddingCommandParserTest.java create mode 100644 src/test/java/seedu/address/logic/parser/UnassignWeddingCommandParserTest.java create mode 100644 src/test/java/seedu/address/logic/parser/UntagCommandParserTest.java create mode 100644 src/test/java/seedu/address/model/wedding/UniqueWeddingListTest.java create mode 100644 src/test/java/seedu/address/model/wedding/WeddingNameTest.java create mode 100644 src/test/java/seedu/address/model/wedding/WeddingTest.java create mode 100644 src/test/java/seedu/address/testutil/TypicalTags.java create mode 100644 src/test/java/seedu/address/testutil/TypicalWeddings.java diff --git a/src/main/java/seedu/address/logic/Messages.java b/src/main/java/seedu/address/logic/Messages.java index d78f6fba0e8..7bf4cf91e7f 100644 --- a/src/main/java/seedu/address/logic/Messages.java +++ b/src/main/java/seedu/address/logic/Messages.java @@ -8,6 +8,7 @@ import seedu.address.logic.parser.Prefix; import seedu.address.model.person.Person; import seedu.address.model.tag.Tag; +import seedu.address.model.wedding.Wedding; /** * Container for user visible messages. @@ -20,8 +21,14 @@ public class Messages { public static final String MESSAGE_PERSONS_LISTED_OVERVIEW = "%1$d persons listed!"; public static final String MESSAGE_DUPLICATE_FIELDS = "Multiple values specified for the following single-valued field(s): "; - public static final String MESSAGE_TAG_NOT_FOUND = "One or more specified tags do not exist in the model."; + public static final String MESSAGE_TAG_NOT_FOUND = "One or more specified tags do not exist in the Wedlinker."; + public static final String MESSAGE_TAG_NOT_FOUND_IN_CONTACT = "Some tags were not found in the person's tag list."; public static final String MESSAGE_ADD_TAG_SUCCESS = "Added tag(s) %1$s to %2$s."; + public static final String MESSAGE_ADD_WEDDING_SUCCESS = "Added wedding(s) %1$s to %2$s."; + public static final String MESSAGE_WEDDING_NOT_FOUND = "One or more specified weddings do not exist in " + + "the Wedlinker."; + public static final String MESSAGE_WEDDING_NOT_FOUND_IN_CONTACT = "Some weddings were not found in " + + "the person's wedding list."; /** * Returns an error message indicating the duplicate prefixes. @@ -49,6 +56,8 @@ public static String format(Person person) { .append(person.getAddress()) .append("; Tags: "); person.getTags().forEach(builder::append); + builder.append("; Weddings: "); + person.getWeddings().forEach(builder::append); return builder.toString(); } @@ -61,4 +70,8 @@ public static String format(Tag tag) { return builder.toString(); } + public static String format(Wedding wedding) { + return wedding.getWeddingName().toString(); + } + } diff --git a/src/main/java/seedu/address/logic/commands/AddCommand.java b/src/main/java/seedu/address/logic/commands/AddCommand.java index 5d7185a9680..94beb7d37bd 100644 --- a/src/main/java/seedu/address/logic/commands/AddCommand.java +++ b/src/main/java/seedu/address/logic/commands/AddCommand.java @@ -6,6 +6,7 @@ import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; +import static seedu.address.logic.parser.CliSyntax.PREFIX_WEDDING; import seedu.address.commons.util.ToStringBuilder; import seedu.address.logic.Messages; @@ -33,7 +34,8 @@ public class AddCommand extends Command { + PREFIX_EMAIL + "johnd@example.com " + PREFIX_ADDRESS + "311, Clementi Ave 2, #02-25 " + PREFIX_TAG + "friends " - + PREFIX_TAG + "owesMoney"; + + PREFIX_TAG + "owesMoney " + + PREFIX_WEDDING + "Wedding March 20th 2027";; public static final String MESSAGE_SUCCESS = "New person added: %1$s"; public static final String MESSAGE_DUPLICATE_PERSON = "This person already exists in the address book"; diff --git a/src/main/java/seedu/address/logic/commands/AssignWeddingCommand.java b/src/main/java/seedu/address/logic/commands/AssignWeddingCommand.java new file mode 100644 index 00000000000..84d4fdf7ed3 --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/AssignWeddingCommand.java @@ -0,0 +1,105 @@ +package seedu.address.logic.commands; + +import static seedu.address.logic.Messages.MESSAGE_ADD_WEDDING_SUCCESS; +import static seedu.address.logic.Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX; +import static seedu.address.logic.Messages.MESSAGE_WEDDING_NOT_FOUND; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import seedu.address.commons.core.index.Index; +import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.Model; +import seedu.address.model.person.Person; +import seedu.address.model.wedding.Wedding; + +/** + * Adds a wedding to an existing person in the Wedlinker. + */ +public class AssignWeddingCommand extends Command { + + public static final String COMMAND_WORD = "assign-wedding"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + + ": Adds one or multiple weddings to the person identified " + + "by the index number used in the last person listing.\n" + + "Parameters: INDEX (must be a positive integer) " + + "w/[WEDDING]... (can specify multiple weddings)\n" + + "Example: " + COMMAND_WORD + " 1 " + + "w/Craig's Wedding w/Wedding April 2025."; + + private final Index index; + private final HashSet weddingsToAdd; + + /** + * Constructs a {@code AssignWedding} Command to add weddings to a person. + * @param index The index of the person in the person list. + * @param weddingsToAdd The list of weddings to be added. + */ + public AssignWeddingCommand(Index index, HashSet weddingsToAdd) { + this.index = index; + this.weddingsToAdd = weddingsToAdd; + } + + /** + * Generates a command execution success message showing the added weddings and the person. + * + * @param personToEdit The person to whom the weddings were added. + * @return A success message indicating the weddings that were added and the name of the person. + */ + private String generateSuccessMessage(Person personToEdit) { + String addedWeddings = weddingsToAdd.stream() + .map(wedding -> wedding.toString().replaceAll("[\\[\\]]", "")) + .collect(Collectors.joining(", ")); + return String.format(MESSAGE_ADD_WEDDING_SUCCESS, addedWeddings, personToEdit.getName().toString()); + } + + @Override + public CommandResult execute(Model model) throws CommandException { + List lastShownList = model.getFilteredPersonList(); + + if (index.getZeroBased() >= lastShownList.size()) { + throw new CommandException(MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); + } + + Person personToEdit = lastShownList.get(index.getZeroBased()); + + for (Wedding wedding : weddingsToAdd) { + if (!model.hasWedding(wedding)) { + throw new CommandException(MESSAGE_WEDDING_NOT_FOUND); + } + } + + Set updatedWeddings = new HashSet<>(personToEdit.getWeddings()); + updatedWeddings.addAll(weddingsToAdd); + + Person editedPerson = new Person( + personToEdit.getName(), + personToEdit.getPhone(), + personToEdit.getEmail(), + personToEdit.getAddress(), + personToEdit.getTags(), + updatedWeddings); + + model.setPerson(personToEdit, editedPerson); + model.updateFilteredPersonList(Model.PREDICATE_SHOW_ALL_PERSONS); + + return new CommandResult(generateSuccessMessage(editedPerson)); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + if (!(other instanceof AssignWeddingCommand)) { + return false; + } + + AssignWeddingCommand otherCommand = (AssignWeddingCommand) other; + return index.equals(otherCommand.index) && weddingsToAdd.equals(((AssignWeddingCommand) other).weddingsToAdd); + } +} diff --git a/src/main/java/seedu/address/logic/commands/CreateWeddingCommand.java b/src/main/java/seedu/address/logic/commands/CreateWeddingCommand.java new file mode 100644 index 00000000000..9cb2b466110 --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/CreateWeddingCommand.java @@ -0,0 +1,73 @@ +package seedu.address.logic.commands; + +import static java.util.Objects.requireNonNull; +import static seedu.address.logic.parser.CliSyntax.PREFIX_WEDDING; + +import seedu.address.commons.util.ToStringBuilder; +import seedu.address.logic.Messages; +import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.Model; +import seedu.address.model.wedding.Wedding; + +/** + * Adds a wedding to the address book. + */ +public class CreateWeddingCommand extends Command { + + public static final String COMMAND_WORD = "create-wedding"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Creates a wedding in the address book. " + + "Parameters: " + + PREFIX_WEDDING + "WEDDING\n" + + "Example: " + COMMAND_WORD + " " + + PREFIX_WEDDING + "Cheryl's Wedding"; + + public static final String MESSAGE_SUCCESS = "New wedding added: %1$s"; + + public static final String MESSAGE_DUPLICATE_WEDDING = "This wedding already exists in the address book"; + + private final Wedding weddingToAdd; + + /** + * Creates a CreateWeddingCommand to add the specified {@code Wedding} to the Wedlinker + * @param wedding The {@code Wedding} to be added to the Wedlinker + */ + public CreateWeddingCommand(Wedding wedding) { + requireNonNull(wedding); + weddingToAdd = wedding; + } + + @Override + public CommandResult execute(Model model) throws CommandException { + requireNonNull(model); + + if (model.hasWedding(weddingToAdd)) { + throw new CommandException(MESSAGE_DUPLICATE_WEDDING); + } + + model.addWedding(weddingToAdd); + return new CommandResult(String.format(MESSAGE_SUCCESS, Messages.format(weddingToAdd))); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + + // null case handled by instanceof + if (!(obj instanceof CreateWeddingCommand)) { + return false; + } + + CreateWeddingCommand otherCreateWeddingCommand = (CreateWeddingCommand) obj; + return weddingToAdd.equals(otherCreateWeddingCommand.weddingToAdd); + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .add("weddingToAdd", weddingToAdd) + .toString(); + } +} diff --git a/src/main/java/seedu/address/logic/commands/DeleteTagCommand.java b/src/main/java/seedu/address/logic/commands/DeleteTagCommand.java index 89b41b4697b..5a4fda99e6f 100644 --- a/src/main/java/seedu/address/logic/commands/DeleteTagCommand.java +++ b/src/main/java/seedu/address/logic/commands/DeleteTagCommand.java @@ -11,16 +11,15 @@ import seedu.address.model.tag.Tag; /** - * Deletes a person identified using it's displayed index from the address book. + * Deletes a person identified using its tag name in the Wedlinker. */ public class DeleteTagCommand extends Command { - public static final String COMMAND_WORD = "delete-tag"; public static final String MESSAGE_USAGE = COMMAND_WORD + ": Deletes the tag identified by the tag name.\n" + "Parameters: TAG_NAME (must exists in the AddressBook)\n" - + "Example: " + COMMAND_WORD + " florist"; + + "Example: " + COMMAND_WORD + " t/florist"; public static final String MESSAGE_DELETE_TAG_SUCCESS = "Deleted Tag: %1$s"; public static final String MESSAGE_DELETE_TAG_FAILURE_STILL_TAGGED = "The Tag: %1$s is still used"; diff --git a/src/main/java/seedu/address/logic/commands/DeleteWeddingCommand.java b/src/main/java/seedu/address/logic/commands/DeleteWeddingCommand.java new file mode 100644 index 00000000000..1fcdaad871c --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/DeleteWeddingCommand.java @@ -0,0 +1,78 @@ +package seedu.address.logic.commands; + +import static java.util.Objects.requireNonNull; +import static seedu.address.logic.parser.CliSyntax.PREFIX_WEDDING; + +import java.util.List; + +import seedu.address.commons.util.ToStringBuilder; +import seedu.address.logic.Messages; +import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.Model; +import seedu.address.model.wedding.Wedding; + +/** + * Deletes a wedding identified using its wedding name in the Wedlinker. + */ +public class DeleteWeddingCommand extends Command { + public static final String COMMAND_WORD = "delete-wedding"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + + ": Deletes the wedding identified by the wedding name.\n" + + "Parameters: WEDDING_NAME (must exist in the Wedlinker)\n" + + "Example: " + COMMAND_WORD + " " + + PREFIX_WEDDING + " Timothy's Wedding"; + + public static final String MESSAGE_DELETE_WEDDING_SUCCESS = "Deleted Wedding: %1$s"; + public static final String MESSAGE_DELETE_WEDDING_FAILURE_STILL_USED = "The Wedding: %1$s is still used"; + public static final String MESSAGE_DELETE_WEDDING_FAILURE_NOT_FOUND = "The Wedding: %1$s does not exist"; + + private final Wedding targetWedding; + + public DeleteWeddingCommand(Wedding wedding) { + targetWedding = wedding; + } + + @Override + public CommandResult execute(Model model) throws CommandException { + requireNonNull(model); + List allWeddings = model.getFilteredWeddingList(); + + for (Wedding wedding : allWeddings) { + if (wedding.getWeddingName().equals(targetWedding.getWeddingName())) { + if (wedding.canBeDeleted()) { + model.deleteWedding(wedding); + return new CommandResult(String.format(MESSAGE_DELETE_WEDDING_SUCCESS, + Messages.format(targetWedding))); + } else { + throw new CommandException( + String.format(MESSAGE_DELETE_WEDDING_FAILURE_STILL_USED, Messages.format(targetWedding))); + } + } + } + throw new CommandException(String.format(MESSAGE_DELETE_WEDDING_FAILURE_NOT_FOUND, + Messages.format(targetWedding))); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + + // instanceof handles nulls + if (!(obj instanceof DeleteWeddingCommand)) { + return false; + } + + DeleteWeddingCommand otherDeleteWeddingCommand = (DeleteWeddingCommand) obj; + return targetWedding.equals(otherDeleteWeddingCommand.targetWedding); + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .add("targetWedding", targetWedding) + .toString(); + } +} diff --git a/src/main/java/seedu/address/logic/commands/EditCommand.java b/src/main/java/seedu/address/logic/commands/EditCommand.java index 4b581c7331e..328ec7190da 100644 --- a/src/main/java/seedu/address/logic/commands/EditCommand.java +++ b/src/main/java/seedu/address/logic/commands/EditCommand.java @@ -27,6 +27,7 @@ import seedu.address.model.person.Person; import seedu.address.model.person.Phone; import seedu.address.model.tag.Tag; +import seedu.address.model.wedding.Wedding; /** * Edits the details of an existing person in the address book. @@ -100,8 +101,9 @@ private static Person createEditedPerson(Person personToEdit, EditPersonDescript Email updatedEmail = editPersonDescriptor.getEmail().orElse(personToEdit.getEmail()); Address updatedAddress = editPersonDescriptor.getAddress().orElse(personToEdit.getAddress()); Set updatedTags = editPersonDescriptor.getTags().orElse(personToEdit.getTags()); + Set updatedWeddings = editPersonDescriptor.getWeddings().orElse(personToEdit.getWeddings()); - return new Person(updatedName, updatedPhone, updatedEmail, updatedAddress, updatedTags); + return new Person(updatedName, updatedPhone, updatedEmail, updatedAddress, updatedTags, updatedWeddings); } @Override @@ -138,6 +140,7 @@ public static class EditPersonDescriptor { private Email email; private Address address; private Set tags; + private Set weddings; public EditPersonDescriptor() {} @@ -151,13 +154,14 @@ public EditPersonDescriptor(EditPersonDescriptor toCopy) { setEmail(toCopy.email); setAddress(toCopy.address); setTags(toCopy.tags); + setWeddings(toCopy.weddings); } /** * Returns true if at least one field is edited. */ public boolean isAnyFieldEdited() { - return CollectionUtil.isAnyNonNull(name, phone, email, address, tags); + return CollectionUtil.isAnyNonNull(name, phone, email, address, tags, weddings); } public void setName(Name name) { @@ -209,6 +213,23 @@ public Optional> getTags() { return (tags != null) ? Optional.of(Collections.unmodifiableSet(tags)) : Optional.empty(); } + /** + * Sets {@code weddings} to this object's {@code weddings}. + * A defensive copy of {@code weddings} is used internally. + */ + public void setWeddings(Set weddings) { + this.weddings = (weddings != null) ? new HashSet<>(weddings) : null; + } + + /** + * Returns an unmodifiable weddings set, which throws {@code UnsupportedOperationException} + * if modification is attempted. + * Returns {@code Optional#empty()} if {@code weddings} is null. + */ + public Optional> getWeddings() { + return (weddings != null) ? Optional.of(Collections.unmodifiableSet(weddings)) : Optional.empty(); + } + @Override public boolean equals(Object other) { if (other == this) { @@ -225,7 +246,8 @@ public boolean equals(Object other) { && Objects.equals(phone, otherEditPersonDescriptor.phone) && Objects.equals(email, otherEditPersonDescriptor.email) && Objects.equals(address, otherEditPersonDescriptor.address) - && Objects.equals(tags, otherEditPersonDescriptor.tags); + && Objects.equals(tags, otherEditPersonDescriptor.tags) + && Objects.equals(weddings, otherEditPersonDescriptor.weddings); } @Override @@ -236,6 +258,7 @@ public String toString() { .add("email", email) .add("address", address) .add("tags", tags) + .add("weddings", weddings) .toString(); } } diff --git a/src/main/java/seedu/address/logic/commands/TagCommand.java b/src/main/java/seedu/address/logic/commands/TagCommand.java index e25dbfbf5b3..6a966e062c9 100644 --- a/src/main/java/seedu/address/logic/commands/TagCommand.java +++ b/src/main/java/seedu/address/logic/commands/TagCommand.java @@ -16,7 +16,7 @@ import seedu.address.model.tag.Tag; /** - * Removes a tag associated with an existing person in the address book. + * Adds a tag to an existing person in the Wedlinker. */ public class TagCommand extends Command { @@ -35,7 +35,7 @@ public class TagCommand extends Command { /** - * Constructs a TagCommand to add tags to a person. + * Constructs a {@code TagCommand} to add tags to a person. * * @param index The index of the person in the person list. * @param tagsToAdd The list of tags to be added. @@ -82,7 +82,8 @@ public CommandResult execute(Model model) throws CommandException { personToEdit.getPhone(), personToEdit.getEmail(), personToEdit.getAddress(), - updatedTags); + updatedTags, + personToEdit.getWeddings()); model.setPerson(personToEdit, editedPerson); model.updateFilteredPersonList(Model.PREDICATE_SHOW_ALL_PERSONS); diff --git a/src/main/java/seedu/address/logic/commands/UnassignWeddingCommand.java b/src/main/java/seedu/address/logic/commands/UnassignWeddingCommand.java new file mode 100644 index 00000000000..01689e1afbb --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/UnassignWeddingCommand.java @@ -0,0 +1,112 @@ +package seedu.address.logic.commands; + +import static seedu.address.logic.Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX; +import static seedu.address.logic.Messages.MESSAGE_WEDDING_NOT_FOUND_IN_CONTACT; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import seedu.address.commons.core.index.Index; +import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.Model; +import seedu.address.model.person.Person; +import seedu.address.model.wedding.Wedding; + +/** + * Removes a wedding associated with an existing person in the Wedlinker. + */ +public class UnassignWeddingCommand extends Command { + public static final String COMMAND_WORD = "unassign-wedding"; + public static final String MESSAGE_REMOVE_WEDDING_SUCCESS = "Removed wedding(s) %1$s from %2$s."; + + public static final String MESSAGE_USAGE = COMMAND_WORD + + ": Removes one or multiple weddings from the person identified " + + "by the index number used in the last person listing.\n" + + "Parameters: INDEX (must be a positive integer) " + + "w/[WEDDING]... (can specify multiple weddings)\n" + + "Example: " + COMMAND_WORD + " 1 " + + "w/Craig's Wedding w/Wedding April 2025."; + + private final Index index; + private final HashSet weddingsToRemove; + + /** + * Constructs an UnassignWeddingCommand to remove weddings from a person. + * + * @param index The index of the person in the person list. + * @param weddingsToRemove The list of weddings to be removed. + */ + public UnassignWeddingCommand(Index index, HashSet weddingsToRemove) { + this.index = index; + this.weddingsToRemove = weddingsToRemove; + } + + /** + * Generates a command execution success message showing the removed wedding and the person. + * + * @param personToEdit The person from whom the weddings were removed. + * @return A success message indicating the weddings that were removed and the name of the person. + */ + private String generateSuccessMessage(Person personToEdit) { + String removedWeddings = weddingsToRemove.stream() + .map(wedding -> wedding.toString().replaceAll("[\\[\\]]", "")) + .collect(Collectors.joining(", ")); + return String.format(MESSAGE_REMOVE_WEDDING_SUCCESS, removedWeddings, personToEdit.getName().toString()); + } + + @Override + public CommandResult execute(Model model) throws CommandException { + List lastShownList = model.getFilteredPersonList(); + + if (index.getZeroBased() >= lastShownList.size()) { + throw new CommandException(MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); + } + + Person personToEdit = lastShownList.get(index.getZeroBased()); + Set updatedWeddings = new HashSet<>(personToEdit.getWeddings()); + + if (personToEdit.getWeddings().isEmpty()) { + throw new CommandException(MESSAGE_WEDDING_NOT_FOUND_IN_CONTACT); + } + + if (weddingsToRemove.isEmpty()) { + throw new CommandException(MESSAGE_WEDDING_NOT_FOUND_IN_CONTACT); + } + + if (!updatedWeddings.containsAll(weddingsToRemove)) { + throw new CommandException(MESSAGE_WEDDING_NOT_FOUND_IN_CONTACT); + } + updatedWeddings.removeAll(weddingsToRemove); + + Person editedPerson = new Person( + personToEdit.getName(), + personToEdit.getPhone(), + personToEdit.getEmail(), + personToEdit.getAddress(), + personToEdit.getTags(), + updatedWeddings); + + model.setPerson(personToEdit, editedPerson); + model.updateFilteredPersonList(Model.PREDICATE_SHOW_ALL_PERSONS); + + return new CommandResult(generateSuccessMessage(personToEdit)); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + if (!(other instanceof UnassignWeddingCommand)) { + return false; + } + + UnassignWeddingCommand otherCommand = (UnassignWeddingCommand) other; + return index.equals(otherCommand.index) + && weddingsToRemove.equals(otherCommand.weddingsToRemove); + } + +} diff --git a/src/main/java/seedu/address/logic/commands/UntagCommand.java b/src/main/java/seedu/address/logic/commands/UntagCommand.java new file mode 100644 index 00000000000..4f5b4f2d1b7 --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/UntagCommand.java @@ -0,0 +1,114 @@ +package seedu.address.logic.commands; + +import static seedu.address.logic.Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX; +import static seedu.address.logic.Messages.MESSAGE_TAG_NOT_FOUND_IN_CONTACT; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import seedu.address.commons.core.index.Index; +import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.Model; +import seedu.address.model.person.Person; +import seedu.address.model.tag.Tag; + +/** + * Removes a tag associated with an existing person in the Wedlinker. + */ +public class UntagCommand extends Command { + + public static final String COMMAND_WORD = "untag"; + public static final String MESSAGE_REMOVE_TAG_SUCCESS = "Removed tag(s) %1$s from %2$s."; + + public static final String MESSAGE_USAGE = COMMAND_WORD + + ": Removes one or multiple tags from the person identified " + + "by the index number used in the last person listing.\n" + + "Parameters: INDEX (must be a positive integer) " + + "t/[TAG]... (can specify multiple tags)\n" + + "Example: " + COMMAND_WORD + " 1 " + + "t/florist t/photographer."; + + private final Index index; + private final HashSet tagsToRemove; + + /** + * Constructs an UntagCommand to remove tags from a person. + * + * @param index The index of the person in the person list. + * @param tagsToRemove The list of tags to be removed. + */ + public UntagCommand(Index index, HashSet tagsToRemove) { + this.index = index; + this.tagsToRemove = tagsToRemove; + } + + /** + * Generates a command execution success message showing the removed tags and the person. + * + * @param personToEdit The person from whom the tags were removed. + * @return A success message indicating the tags that were removed and the name of the person. + */ + private String generateSuccessMessage(Person personToEdit) { + String removedTags = tagsToRemove.stream() + .map(tag -> tag.toString().replaceAll("[\\[\\]]", "")) + .collect(Collectors.joining(", ")); + return String.format(MESSAGE_REMOVE_TAG_SUCCESS, removedTags, personToEdit.getName().toString()); + } + + @Override + public CommandResult execute(Model model) throws CommandException { + List lastShownList = model.getFilteredPersonList(); + + if (index.getZeroBased() >= lastShownList.size()) { + throw new CommandException(MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); + } + + Person personToEdit = lastShownList.get(index.getZeroBased()); + Set updatedTags = new HashSet<>(personToEdit.getTags()); + + if (personToEdit.getTags().isEmpty()) { + throw new CommandException(MESSAGE_TAG_NOT_FOUND_IN_CONTACT); + } + + if (tagsToRemove.isEmpty()) { + throw new CommandException(MESSAGE_TAG_NOT_FOUND_IN_CONTACT); + } + + if (!updatedTags.containsAll(tagsToRemove)) { + throw new CommandException(MESSAGE_TAG_NOT_FOUND_IN_CONTACT); + } + updatedTags.removeAll(tagsToRemove); + + Person editedPerson = new Person( + personToEdit.getName(), + personToEdit.getPhone(), + personToEdit.getEmail(), + personToEdit.getAddress(), + updatedTags, + personToEdit.getWeddings()); + + model.setPerson(personToEdit, editedPerson); + model.updateFilteredPersonList(Model.PREDICATE_SHOW_ALL_PERSONS); + + return new CommandResult(generateSuccessMessage(personToEdit)); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + if (!(other instanceof UntagCommand)) { + return false; + } + + UntagCommand otherCommand = (UntagCommand) other; + return index.equals(otherCommand.index) + && tagsToRemove.equals(otherCommand.tagsToRemove); + } + + +} diff --git a/src/main/java/seedu/address/logic/parser/AddCommandParser.java b/src/main/java/seedu/address/logic/parser/AddCommandParser.java index 3eab72ea58d..5eb7e572b60 100644 --- a/src/main/java/seedu/address/logic/parser/AddCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/AddCommandParser.java @@ -6,6 +6,7 @@ import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; +import static seedu.address.logic.parser.CliSyntax.PREFIX_WEDDING; import java.util.Set; import java.util.stream.Stream; @@ -18,6 +19,7 @@ import seedu.address.model.person.Person; import seedu.address.model.person.Phone; import seedu.address.model.tag.Tag; +import seedu.address.model.wedding.Wedding; /** * Parses input arguments and creates a new AddCommand object @@ -31,7 +33,8 @@ public class AddCommandParser implements Parser { */ public AddCommand parse(String args) throws ParseException { ArgumentMultimap argMultimap = - ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TAG); + ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, + PREFIX_TAG, PREFIX_WEDDING); if (!arePrefixesPresent(argMultimap, PREFIX_NAME) || !argMultimap.getPreamble().isEmpty()) { @@ -44,8 +47,9 @@ public AddCommand parse(String args) throws ParseException { Phone phone = ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE).orElse("")); Email email = ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL).orElse("")); Set tagList = ParserUtil.parseTags(argMultimap.getAllValues(PREFIX_TAG)); + Set weddingList = ParserUtil.parseWeddings(argMultimap.getAllValues(PREFIX_WEDDING)); - Person person = new Person(name, phone, email, address, tagList); + Person person = new Person(name, phone, email, address, tagList, weddingList); return new AddCommand(person); } diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java index 5d2875ed8ef..31fcf307138 100644 --- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java +++ b/src/main/java/seedu/address/logic/parser/AddressBookParser.java @@ -9,11 +9,14 @@ import seedu.address.commons.core.LogsCenter; import seedu.address.logic.commands.AddCommand; +import seedu.address.logic.commands.AssignWeddingCommand; import seedu.address.logic.commands.ClearCommand; import seedu.address.logic.commands.Command; import seedu.address.logic.commands.CreateTagCommand; +import seedu.address.logic.commands.CreateWeddingCommand; import seedu.address.logic.commands.DeleteCommand; import seedu.address.logic.commands.DeleteTagCommand; +import seedu.address.logic.commands.DeleteWeddingCommand; import seedu.address.logic.commands.EditCommand; import seedu.address.logic.commands.ExitCommand; import seedu.address.logic.commands.FilterCommand; @@ -21,6 +24,8 @@ import seedu.address.logic.commands.HelpCommand; import seedu.address.logic.commands.ListCommand; import seedu.address.logic.commands.TagCommand; +import seedu.address.logic.commands.UnassignWeddingCommand; +import seedu.address.logic.commands.UntagCommand; import seedu.address.logic.parser.exceptions.ParseException; /** @@ -67,7 +72,12 @@ public Command parseCommand(String userInput) throws ParseException { case HelpCommand.COMMAND_WORD -> new HelpCommand(); case CreateTagCommand.COMMAND_WORD -> new CreateTagCommandParser().parse(arguments); case DeleteTagCommand.COMMAND_WORD -> new DeleteTagCommandParser().parse(arguments); + case CreateWeddingCommand.COMMAND_WORD -> new CreateWeddingCommandParser().parse(arguments); + case DeleteWeddingCommand.COMMAND_WORD -> new DeleteWeddingCommandParser().parse(arguments); case TagCommand.COMMAND_WORD -> new TagCommandParser().parse(arguments); + case UntagCommand.COMMAND_WORD -> new UntagCommandParser().parse(arguments); + case AssignWeddingCommand.COMMAND_WORD -> new AssignWeddingCommandParser().parse(arguments); + case UnassignWeddingCommand.COMMAND_WORD -> new UnassignWeddingCommandParser().parse(arguments); default -> { logger.finer("This user input caused a ParseException: " + userInput); throw new ParseException(MESSAGE_UNKNOWN_COMMAND); diff --git a/src/main/java/seedu/address/logic/parser/AssignWeddingCommandParser.java b/src/main/java/seedu/address/logic/parser/AssignWeddingCommandParser.java new file mode 100644 index 00000000000..d86c84f875b --- /dev/null +++ b/src/main/java/seedu/address/logic/parser/AssignWeddingCommandParser.java @@ -0,0 +1,76 @@ +package seedu.address.logic.parser; + +import static java.util.Objects.requireNonNull; +import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static seedu.address.logic.parser.CliSyntax.PREFIX_WEDDING; + +import java.util.HashSet; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import seedu.address.commons.core.index.Index; +import seedu.address.commons.exceptions.IllegalValueException; +import seedu.address.logic.commands.AssignWeddingCommand; +import seedu.address.logic.parser.exceptions.ParseException; +import seedu.address.model.wedding.Wedding; +import seedu.address.model.wedding.WeddingName; + +/** + * Parses input arguments and creates a new AssignWeddingCommand object. + */ +public class AssignWeddingCommandParser implements Parser { + /** + * Parses the given String of arguments in the context of the AssignWeddingCommand + * and returns a AssignWeddingCommand object for execution. + * + * @param args the user input string containing the index and weddings to be added + * @return a new {@code AssignWeddingCommand} object that contains the parsed index and list of weddings + * @throws ParseException if the input does not conform to the expected format (i.e., invalid index + * or missing weddings) + */ + public AssignWeddingCommand parse(String args) throws ParseException { + requireNonNull(args); + + ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_WEDDING); + Index index; + + if (!arePrefixesPresent(argMultimap, PREFIX_WEDDING)) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AssignWeddingCommand.MESSAGE_USAGE)); + } + + try { + // Parse the index from the preamble + index = ParserUtil.parseIndex(argMultimap.getPreamble()); + } catch (IllegalValueException ive) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AssignWeddingCommand.MESSAGE_USAGE), + ive); + } + + List weddingValues = argMultimap.getAllValues(PREFIX_WEDDING); + if (weddingValues.isEmpty()) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AssignWeddingCommand.MESSAGE_USAGE)); + } + + // Checks that all weddings have valid names + if (weddingValues.stream().anyMatch(wedding -> !Wedding.isValidWeddingName(wedding))) { + throw new ParseException(WeddingName.MESSAGE_CONSTRAINTS); + } + + // Convert wedding values to Wedding objects + HashSet weddings = new HashSet<>(weddingValues.stream() + .map(WeddingName::new) // Convert each string to a TagName object + .map(Wedding::new) + .collect(Collectors.toList())); + + return new AssignWeddingCommand(index, weddings); + } + + /** + * Returns true if none of the prefixes contains empty {@code Optional} values in the given + * {@code ArgumentMultimap}. + */ + private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) { + return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent()); + } +} diff --git a/src/main/java/seedu/address/logic/parser/CliSyntax.java b/src/main/java/seedu/address/logic/parser/CliSyntax.java index 75b1a9bf119..66d74a4997e 100644 --- a/src/main/java/seedu/address/logic/parser/CliSyntax.java +++ b/src/main/java/seedu/address/logic/parser/CliSyntax.java @@ -11,5 +11,5 @@ public class CliSyntax { public static final Prefix PREFIX_EMAIL = new Prefix("e/"); public static final Prefix PREFIX_ADDRESS = new Prefix("a/"); public static final Prefix PREFIX_TAG = new Prefix("t/"); - + public static final Prefix PREFIX_WEDDING = new Prefix("w/"); } diff --git a/src/main/java/seedu/address/logic/parser/CreateTagCommandParser.java b/src/main/java/seedu/address/logic/parser/CreateTagCommandParser.java index d53116ed45f..e96e22c89b5 100644 --- a/src/main/java/seedu/address/logic/parser/CreateTagCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/CreateTagCommandParser.java @@ -10,14 +10,14 @@ import seedu.address.model.tag.Tag; /** - * Parses input arguments and creates a new AddCommand object + * Parses input arguments and creates a new CreateTagCommand object */ public class CreateTagCommandParser implements Parser { /** - * Parses the given {@code String} of arguments in the context of the AddCommand - * and returns an AddCommand object for execution. - * @throws ParseException if the user input does not conform the expected format + * Parses the given {@code String} of arguments in the context of the CreateTagCommand + * and returns an CreateTagCommand object for execution. + * @throws ParseException if the user input does not conform to the expected format */ public CreateTagCommand parse(String args) throws ParseException { ArgumentMultimap argMultimap = diff --git a/src/main/java/seedu/address/logic/parser/CreateWeddingCommandParser.java b/src/main/java/seedu/address/logic/parser/CreateWeddingCommandParser.java new file mode 100644 index 00000000000..97b5d8c68c3 --- /dev/null +++ b/src/main/java/seedu/address/logic/parser/CreateWeddingCommandParser.java @@ -0,0 +1,41 @@ +package seedu.address.logic.parser; + +import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static seedu.address.logic.parser.CliSyntax.PREFIX_WEDDING; + +import java.util.stream.Stream; + +import seedu.address.logic.commands.CreateWeddingCommand; +import seedu.address.logic.parser.exceptions.ParseException; +import seedu.address.model.wedding.Wedding; + +/** + * Parses input arguments and creates a new CreateWeddingCommand object + */ +public class CreateWeddingCommandParser implements Parser { + /** + * Parses a {@code String} of arguments in the context of the CreateWeddingCommand + * and returns an CreateWeddingCommand object for execution. + * @throws ParseException if the user input does not conform to the expected format + */ + public CreateWeddingCommand parse(String args) throws ParseException { + ArgumentMultimap argMultimap = + ArgumentTokenizer.tokenize(args, PREFIX_WEDDING); + + if (!arePrefixesPresent(argMultimap, PREFIX_WEDDING) + || !argMultimap.getPreamble().isEmpty()) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, CreateWeddingCommand.MESSAGE_USAGE)); + } + + argMultimap.verifyNoDuplicatePrefixesFor(PREFIX_WEDDING); + Wedding wedding = ParserUtil.parseWedding(argMultimap.getValue(PREFIX_WEDDING).get()); + return new CreateWeddingCommand(wedding); + } + + /** + * Returns true if none of the prefixes contain empty {@code Optional} values in the given {@code ArgumentMultimap} + */ + public static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) { + return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent()); + } +} diff --git a/src/main/java/seedu/address/logic/parser/DeleteTagCommandParser.java b/src/main/java/seedu/address/logic/parser/DeleteTagCommandParser.java index 6df60a5574f..4b564139b67 100644 --- a/src/main/java/seedu/address/logic/parser/DeleteTagCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/DeleteTagCommandParser.java @@ -10,13 +10,12 @@ import seedu.address.model.tag.Tag; /** - * Parses input arguments and creates a new DeleteTagCommand object + * Parses input arguments and creates a new DeleteTagCommand object. */ public class DeleteTagCommandParser implements Parser { - /** - * Parses the given {@code String} of arguments in the context of the DeleteCommand - * and returns a DeleteCommand object for execution. + * Parses the given {@code String} of arguments in the context of the DeleteTagCommand + * and returns a DeleteTagCommand object for execution. * @throws ParseException if the user input does not conform the expected format */ public DeleteTagCommand parse(String args) throws ParseException { diff --git a/src/main/java/seedu/address/logic/parser/DeleteWeddingCommandParser.java b/src/main/java/seedu/address/logic/parser/DeleteWeddingCommandParser.java new file mode 100644 index 00000000000..4e6278dfb6c --- /dev/null +++ b/src/main/java/seedu/address/logic/parser/DeleteWeddingCommandParser.java @@ -0,0 +1,42 @@ +package seedu.address.logic.parser; + +import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static seedu.address.logic.parser.CliSyntax.PREFIX_WEDDING; + +import java.util.stream.Stream; + +import seedu.address.logic.commands.DeleteWeddingCommand; +import seedu.address.logic.parser.exceptions.ParseException; +import seedu.address.model.wedding.Wedding; + +/** + * Parses input arguments and creates a new DeleteWeddingCommand object. + */ +public class DeleteWeddingCommandParser implements Parser { + /** + * Parses the given {@code String} of arguments in the context of the DeleteWeddingCommand + * and returns a DeleteWeddingCommand object for execution. + * @throws ParseException if the user input does not conform the expected format + */ + public DeleteWeddingCommand parse(String args) throws ParseException { + ArgumentMultimap argMultimap = + ArgumentTokenizer.tokenize(args, PREFIX_WEDDING); + + if (!arePrefixesPresent(argMultimap, PREFIX_WEDDING) + || !argMultimap.getPreamble().isEmpty()) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteWeddingCommand.MESSAGE_USAGE)); + } + + argMultimap.verifyNoDuplicatePrefixesFor(PREFIX_WEDDING); + Wedding wedding = ParserUtil.parseWedding(argMultimap.getValue(PREFIX_WEDDING).get()); + return new DeleteWeddingCommand(wedding); + } + + /** + * Returns true if none of the prefixes contains empty {@code Optional} values in the given + * {@code ArgumentMultimap}. + */ + private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) { + return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent()); + } +} diff --git a/src/main/java/seedu/address/logic/parser/EditCommandParser.java b/src/main/java/seedu/address/logic/parser/EditCommandParser.java index 3305ca44004..91093d2b233 100644 --- a/src/main/java/seedu/address/logic/parser/EditCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/EditCommandParser.java @@ -7,6 +7,7 @@ import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; +import static seedu.address.logic.parser.CliSyntax.PREFIX_WEDDING; import java.util.Collection; import java.util.Collections; @@ -18,6 +19,7 @@ import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.tag.Tag; +import seedu.address.model.wedding.Wedding; /** * Parses input arguments and creates a new EditCommand object @@ -32,7 +34,8 @@ public class EditCommandParser implements Parser { public EditCommand parse(String args) throws ParseException { requireNonNull(args); ArgumentMultimap argMultimap = - ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TAG); + ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, + PREFIX_TAG, PREFIX_WEDDING); Index index; @@ -60,6 +63,8 @@ public EditCommand parse(String args) throws ParseException { } parseTagsForEdit(argMultimap.getAllValues(PREFIX_TAG)).ifPresent(editPersonDescriptor::setTags); + parseWeddingsForEdit(argMultimap.getAllValues(PREFIX_WEDDING)).ifPresent(editPersonDescriptor::setWeddings); + if (!editPersonDescriptor.isAnyFieldEdited()) { throw new ParseException(EditCommand.MESSAGE_NOT_EDITED); } @@ -82,4 +87,19 @@ private Optional> parseTagsForEdit(Collection tags) throws Pars return Optional.of(ParserUtil.parseTags(tagSet)); } + /** + * Parses {@code Collection weddings} into a {@code Set} if {@code weddings} is non-empty. + * If {@code weddings} contain only one element which is an empty string, it will be parsed into a + * {@code Set} containing zero tags. + */ + private Optional> parseWeddingsForEdit(Collection weddings) throws ParseException { + assert weddings != null; + + if (weddings.isEmpty()) { + return Optional.empty(); + } + Collection weddingSet = weddings.size() == 1 && weddings.contains("") + ? Collections.emptySet() : weddings; + return Optional.of(ParserUtil.parseWeddings(weddingSet)); + } } diff --git a/src/main/java/seedu/address/logic/parser/ParserUtil.java b/src/main/java/seedu/address/logic/parser/ParserUtil.java index 90061bd058f..aea1a72569d 100644 --- a/src/main/java/seedu/address/logic/parser/ParserUtil.java +++ b/src/main/java/seedu/address/logic/parser/ParserUtil.java @@ -15,6 +15,8 @@ import seedu.address.model.person.Phone; import seedu.address.model.tag.Tag; import seedu.address.model.tag.TagName; +import seedu.address.model.wedding.Wedding; +import seedu.address.model.wedding.WeddingName; /** * Contains utility methods used for parsing strings in the various *Parser classes. @@ -119,4 +121,31 @@ public static Set parseTags(Collection tags) throws ParseException } return tagSet; } + + /** + * Parses {@code String} wedding into {@code Wedding} object. + * Leading and trailing whitespaces will be trimmed. + * @throws ParseException if the given {@code String} wedding is an invalid wedding name. + */ + public static Wedding parseWedding(String wedding) throws ParseException { + requireNonNull(wedding); + String trimmedWedding = wedding.trim(); + if (!Wedding.isValidWeddingName(trimmedWedding)) { + throw new ParseException(WeddingName.MESSAGE_CONSTRAINTS); + } + return new Wedding(new WeddingName(trimmedWedding)); + } + + + /** + * Parses {@code Collection weddings} into a {@code Set}. + */ + public static Set parseWeddings(Collection weddings) throws ParseException { + requireNonNull(weddings); + final Set weddingSet = new HashSet<>(); + for (String weddingName : weddings) { + weddingSet.add(parseWedding(weddingName)); + } + return weddingSet; + } } diff --git a/src/main/java/seedu/address/logic/parser/TagCommandParser.java b/src/main/java/seedu/address/logic/parser/TagCommandParser.java index c42979ca4c8..65318ae43b7 100644 --- a/src/main/java/seedu/address/logic/parser/TagCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/TagCommandParser.java @@ -25,7 +25,7 @@ public class TagCommandParser implements Parser { * and returns a TagCommand object for execution. * * @param args the user input string containing the index and tags to be added - * @return a new TagCommand object that contains the parsed index and list of tags + * @return a new {@code TagCommand} object that contains the parsed index and list of tags * @throws ParseException if the input does not conform to the expected format (i.e., invalid index or missing tags) */ public TagCommand parse(String args) throws ParseException { diff --git a/src/main/java/seedu/address/logic/parser/UnassignWeddingCommandParser.java b/src/main/java/seedu/address/logic/parser/UnassignWeddingCommandParser.java new file mode 100644 index 00000000000..0939fefb50e --- /dev/null +++ b/src/main/java/seedu/address/logic/parser/UnassignWeddingCommandParser.java @@ -0,0 +1,80 @@ +package seedu.address.logic.parser; + +import static java.util.Objects.requireNonNull; +import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static seedu.address.logic.parser.CliSyntax.PREFIX_WEDDING; + +import java.util.HashSet; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import seedu.address.commons.core.index.Index; +import seedu.address.commons.exceptions.IllegalValueException; +import seedu.address.logic.commands.UnassignWeddingCommand; +import seedu.address.logic.parser.exceptions.ParseException; +import seedu.address.model.wedding.Wedding; +import seedu.address.model.wedding.WeddingName; + +/** + * Parses input arguments and create a new UnassignWeddingCommand object. + */ +public class UnassignWeddingCommandParser implements Parser { + + /** + * Parses the given String of arguments in the context of the UnassignWeddingCommand + * and returns a UnassignWeddingCommand object for execution. + * + * @param args the user input string containing the index and weddings to be removed + * @return a new UntagCommand object that contains the parsed index and list of weddings + * @throws ParseException if the input does not conform to the expected format (i.e., invalid index + * or missing weddings) + */ + public UnassignWeddingCommand parse(String args) throws ParseException { + requireNonNull(args); + + ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_WEDDING); + Index index; + + if (!arePrefixesPresent(argMultimap, PREFIX_WEDDING)) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, + UnassignWeddingCommand.MESSAGE_USAGE)); + } + + try { + // Parse the index from the preamble + index = ParserUtil.parseIndex(argMultimap.getPreamble()); + } catch (IllegalValueException ive) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, + UnassignWeddingCommand.MESSAGE_USAGE), ive); + } + + List weddingValues = argMultimap.getAllValues(PREFIX_WEDDING); + if (weddingValues.isEmpty()) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, + UnassignWeddingCommand.MESSAGE_USAGE)); + } + + // Checks that all weddings have valid names + if (weddingValues.stream().anyMatch(wedding -> !Wedding.isValidWeddingName(wedding))) { + throw new ParseException(WeddingName.MESSAGE_CONSTRAINTS); + } + + // Convert wedding values to Wedding objects + List weddings = weddingValues.stream() + .map(WeddingName::new) + .map(Wedding::new) + .collect(Collectors.toList()); + + return new UnassignWeddingCommand(index, new HashSet<>(weddings)); + } + + + /** + * Returns true if none of the prefixes contains empty {@code Optional} values in the given + * {@code ArgumentMultimap}. + */ + private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) { + return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent()); + } +} diff --git a/src/main/java/seedu/address/logic/parser/UntagCommandParser.java b/src/main/java/seedu/address/logic/parser/UntagCommandParser.java new file mode 100644 index 00000000000..a016a82a232 --- /dev/null +++ b/src/main/java/seedu/address/logic/parser/UntagCommandParser.java @@ -0,0 +1,58 @@ +package seedu.address.logic.parser; + +import static java.util.Objects.requireNonNull; +import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; + +import java.util.HashSet; +import java.util.List; +import java.util.stream.Collectors; + +import seedu.address.commons.core.index.Index; +import seedu.address.commons.exceptions.IllegalValueException; +import seedu.address.logic.commands.UntagCommand; +import seedu.address.logic.parser.exceptions.ParseException; +import seedu.address.model.tag.Tag; +import seedu.address.model.tag.TagName; + +/** + * Parses input arguments and creates a new UntagCommand object. + */ +public class UntagCommandParser implements Parser { + + /** + * Parses the given String of arguments in the context of the UntagCommand + * and returns a UntagCommand object for execution. + * + * @param args the user input string containing the index and tags to be removed + * @return a new UntagCommand object that contains the parsed index and list of tags + * @throws ParseException if the input does not conform to the expected format (i.e., invalid index or missing tags) + */ + public UntagCommand parse(String args) throws ParseException { + requireNonNull(args); + + ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_TAG); + + Index index; + + try { + // Parse the index from the preamble + index = ParserUtil.parseIndex(argMultimap.getPreamble()); + } catch (IllegalValueException ive) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, UntagCommand.MESSAGE_USAGE), ive); + } + + List tagValues = argMultimap.getAllValues(PREFIX_TAG); + if (tagValues.isEmpty()) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, UntagCommand.MESSAGE_USAGE)); + } + + // Convert tag values to Tag objects + List tags = tagValues.stream() + .map(TagName::new) + .map(Tag::new) + .collect(Collectors.toList()); + + return new UntagCommand(index, new HashSet<>(tags)); + } +} diff --git a/src/main/java/seedu/address/model/AddressBook.java b/src/main/java/seedu/address/model/AddressBook.java index 8bf329fd6df..13eddcb079c 100644 --- a/src/main/java/seedu/address/model/AddressBook.java +++ b/src/main/java/seedu/address/model/AddressBook.java @@ -3,6 +3,7 @@ import static java.util.Objects.requireNonNull; import java.util.List; +import java.util.Set; import javafx.collections.ObservableList; import seedu.address.commons.util.ToStringBuilder; @@ -10,6 +11,8 @@ import seedu.address.model.person.UniquePersonList; import seedu.address.model.tag.Tag; import seedu.address.model.tag.UniqueTagList; +import seedu.address.model.wedding.UniqueWeddingList; +import seedu.address.model.wedding.Wedding; /** * Wraps all data at the address-book level @@ -19,6 +22,7 @@ public class AddressBook implements ReadOnlyAddressBook { private final UniquePersonList persons; private final UniqueTagList tags; + private final UniqueWeddingList weddings; /* * The 'unusual' code block below is a non-static initialization block, sometimes used to avoid duplication @@ -30,6 +34,7 @@ public class AddressBook implements ReadOnlyAddressBook { { persons = new UniquePersonList(); tags = new UniqueTagList(); + weddings = new UniqueWeddingList(); } public AddressBook() {} @@ -40,18 +45,12 @@ public AddressBook() {} public AddressBook(ReadOnlyAddressBook toBeCopied) { this(); resetData(toBeCopied); + initialiseTags(); + initialiseWeddings(); } //// list overwrite operations - /** - * Replaces the contents of the person list with {@code persons}. - * {@code persons} must not contain duplicate persons. - */ - public void setPersons(List persons) { - this.persons.setPersons(persons); - } - /** * Resets the existing data of this {@code AddressBook} with {@code newData}. */ @@ -60,6 +59,15 @@ public void resetData(ReadOnlyAddressBook newData) { setPersons(newData.getPersonList()); setTags(newData.getTagList()); + setWeddings(newData.getWeddingList()); + } + + /** + * Replaces the contents of the person list with {@code persons}. + * {@code persons} must not contain duplicate persons. + */ + public void setPersons(List persons) { + this.persons.setPersons(persons); } /** @@ -70,6 +78,14 @@ public void setTags(List tags) { this.tags.setTags(tags); } + /** + * Replaces the contents of the wedding list with {@code weddings}. + * {@code weddings} must not contain duplicate tags. + */ + public void setWeddings(List weddings) { + this.weddings.setWeddings(weddings); + } + //// person-level operations /** @@ -110,25 +126,62 @@ public void removePerson(Person key) { //// tag-level operations /** - * Adds a tag to the address book. - * The tag must not already exist in the address book. + * Adds a tag to the Wedlinker. + * The tag must not already exist in the Wedlinker. + * @param tag A {@code Tag} object to be added. */ public void addTag(Tag tag) { tags.add(tag); } /** - * Returns true if a tag with the same name as {@code tag} exists in the address book. + * Returns true if a tag with the same name as {@code tag} exists in the Wedlinker. */ public boolean hasTag(Tag tag) { requireNonNull(tag); return tags.contains(tag); } + /** + * Adds a wedding to the Wedlinker + * The wedding must not already exist in the Wedlinker + * @param wedding A {@code Wedding} object to be added. + */ + public void addWedding(Wedding wedding) { + weddings.add(wedding); + } + + /** + * Replaces the given wedding {@code target} in the list with {@code editedWedding}. + * {@code target} must exist in the address book. + * The wedding identity of {@code editedWedding} must not be the same as another existing wedding in the Wedlinker. + */ + public void setWedding(Wedding target, Wedding editedWedding) { + requireNonNull(editedWedding); + + weddings.setWedding(target, editedWedding); + } + + /** + * Returns true if a wedding with the same name as the {@code wedding} exists in the Wedlinker. + */ + public boolean hasWedding(Wedding wedding) { + requireNonNull(wedding); + return weddings.contains(wedding); + } + + /** + * Removes {@code key} from this {@code AddressBook}. + * {@code key} must exist in the address book. + */ + public void removeWedding(Wedding key) { + weddings.remove(key); + } + /** * Replaces the given tag {@code target} in the list with {@code editedTag}. * {@code target} must exist in the address book. - * The person identity of {@code editedTag} must not be the same as another existing tag in the address book. + * The tag identity of {@code editedTag} must not be the same as another existing tag in the address book. */ public void setTag(Tag target, Tag editedTag) { requireNonNull(editedTag); @@ -144,6 +197,36 @@ public void removeTag(Tag key) { tags.remove(key); } + /** + * Creates any tags that is attached to a person but not initialised. + * This function is only to be used when loading from Storage. + */ + public void initialiseTags() { + for (Person person : persons) { + Set tagForPerson = person.getTags(); + for (Tag tag : tagForPerson) { + if (!this.hasTag(tag)) { + this.addTag(tag); + } + } + } + } + + /** + * Creates any weddings attached to a person but not initialised. + * This function is only to be used when loading from Storage. + */ + public void initialiseWeddings() { + for (Person person : persons) { + Set weddingForPerson = person.getWeddings(); + for (Wedding wedding : weddingForPerson) { + if (!this.hasWedding(wedding)) { + this.addWedding(wedding); + } + } + } + } + //// util methods @Override @@ -159,7 +242,14 @@ public ObservableList getPersonList() { } @Override - public ObservableList getTagList() { return tags.asUnmodifiableObservableList(); } + public ObservableList getTagList() { + return tags.asUnmodifiableObservableList(); + } + + @Override + public ObservableList getWeddingList() { + return weddings.asUnmodifiableObservableList(); + } @Override public boolean equals(Object other) { diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java index a2bfdd7efbd..69e005ff328 100644 --- a/src/main/java/seedu/address/model/Model.java +++ b/src/main/java/seedu/address/model/Model.java @@ -7,6 +7,7 @@ import seedu.address.commons.core.GuiSettings; import seedu.address.model.person.Person; import seedu.address.model.tag.Tag; +import seedu.address.model.wedding.Wedding; /** * The API of the Model component. @@ -15,6 +16,7 @@ public interface Model { /** {@code Predicate} that always evaluate to true */ Predicate PREDICATE_SHOW_ALL_PERSONS = unused -> true; Predicate PREDICATE_SHOW_ALL_TAGS = unused -> true; + Predicate PREDICATE_SHOW_ALL_WEDDINGS = unused -> true; /** * Replaces user prefs data with the data in {@code userPrefs}. @@ -96,7 +98,7 @@ public interface Model { void updateFilteredPersonListByTag(Predicate tagPredicate); /** - * Returns true if a tag with the same name as (@code tag} exists in the addres book. + * Returns true if a tag with the same name as {@code toAdd} exists in the Wedlinker. */ boolean hasTag(Tag toAdd); @@ -117,7 +119,37 @@ public interface Model { /** * Deletes the given tag. - * The tag must exist in the AddressBook. + * The tag must exist in the Wedlinker. */ void deleteTag(Tag toDelete); + + /** + * Returns true if a tag with the same name as {@code toAdd} exists in the Wedlinker. + * @param toAdd A {@code Wedding} object, will be checked to see if the model already has this. + * @return A boolean, true if the Wedlinker already contains the {@code Wedding}, false if it does not. + */ + boolean hasWedding(Wedding toAdd); + + /** + * Adds the given {@code Wedding} to the Wedlinker. + * @param toAdd A {@code Wedding} to add to the Wedlinker. + */ + void addWedding(Wedding toAdd); + + void setWedding(Wedding target, Wedding editedWedding); + + /** + * Deletes the given wedding. + * The wedding must exist in the Wedlinker. + */ + void deleteWedding(Wedding toDelete); + + /** Returns an unmodifiable view of the filtered wedding list */ + ObservableList getFilteredWeddingList(); + + /** + * Updates the filter of the filtered wedding list to filter by the given {@code predicate}. + * @throws NullPointerException if {@code predicate} is null. + */ + void updateFilteredWeddingList(Predicate predicate); } diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index 6dc3d878151..fd1eae552f4 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -13,6 +13,7 @@ import seedu.address.commons.core.LogsCenter; import seedu.address.model.person.Person; import seedu.address.model.tag.Tag; +import seedu.address.model.wedding.Wedding; /** * Represents the in-memory model of the address book data. @@ -24,6 +25,7 @@ public class ModelManager implements Model { private final UserPrefs userPrefs; private final FilteredList filteredPersons; private final FilteredList filteredTags; + private final FilteredList filteredWeddings; /** * Initializes a ModelManager with the given addressBook and userPrefs. @@ -37,6 +39,7 @@ public ModelManager(ReadOnlyAddressBook addressBook, ReadOnlyUserPrefs userPrefs this.userPrefs = new UserPrefs(userPrefs); filteredPersons = new FilteredList<>(this.addressBook.getPersonList()); filteredTags = new FilteredList<>(this.addressBook.getTagList()); + filteredWeddings = new FilteredList<>(this.addressBook.getWeddingList()); } public ModelManager() { @@ -110,7 +113,6 @@ public void addPerson(Person person) { @Override public void setPerson(Person target, Person editedPerson) { requireAllNonNull(target, editedPerson); - addressBook.setPerson(target, editedPerson); } @@ -129,12 +131,36 @@ public boolean hasTag(Tag tag) { @Override public void setTag(Tag target, Tag editedTag) { requireAllNonNull(target, editedTag); - addressBook.setTag(target, editedTag); } @Override - public void deleteTag(Tag target) { addressBook.removeTag(target); } + public void deleteTag(Tag target) { + addressBook.removeTag(target); + } + + @Override + public void addWedding(Wedding toAdd) { + addressBook.addWedding(toAdd); + updateFilteredWeddingList(PREDICATE_SHOW_ALL_WEDDINGS); + } + + @Override + public void setWedding(Wedding target, Wedding editedWedding) { + requireAllNonNull(target, editedWedding); + addressBook.setWedding(target, editedWedding); + } + + @Override + public boolean hasWedding(Wedding wedding) { + requireNonNull(wedding); + return addressBook.hasWedding(wedding); + } + + @Override + public void deleteWedding(Wedding target) { + addressBook.removeWedding(target); + } //=========== Filtered Person List Accessors ============================================================= @@ -170,6 +196,17 @@ public void updateFilteredTagList(Predicate predicate) { filteredTags.setPredicate(predicate); } + @Override + public ObservableList getFilteredWeddingList() { + return filteredWeddings; + } + + @Override + public void updateFilteredWeddingList(Predicate predicate) { + requireNonNull(predicate); + filteredWeddings.setPredicate(predicate); + } + @Override public boolean equals(Object other) { if (other == this) { @@ -185,6 +222,7 @@ public boolean equals(Object other) { return addressBook.equals(otherModelManager.addressBook) && userPrefs.equals(otherModelManager.userPrefs) && filteredPersons.equals(otherModelManager.filteredPersons) - && filteredTags.equals(otherModelManager.filteredTags); + && filteredTags.equals(otherModelManager.filteredTags) + && filteredWeddings.equals(otherModelManager.filteredWeddings); } } diff --git a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java b/src/main/java/seedu/address/model/ReadOnlyAddressBook.java index 273d41cd864..3da6438a8bb 100644 --- a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java +++ b/src/main/java/seedu/address/model/ReadOnlyAddressBook.java @@ -3,6 +3,7 @@ import javafx.collections.ObservableList; import seedu.address.model.person.Person; import seedu.address.model.tag.Tag; +import seedu.address.model.wedding.Wedding; /** * Unmodifiable view of an address book @@ -20,4 +21,11 @@ public interface ReadOnlyAddressBook { * This list will not contain any duplicate tags. */ ObservableList getTagList(); + + /** + * Returns an unmodifiable view of the tags list. + * This list will not contain any duplicate tags. + */ + ObservableList getWeddingList(); + } diff --git a/src/main/java/seedu/address/model/person/Person.java b/src/main/java/seedu/address/model/person/Person.java index abe8c46b535..1236e0f56c5 100644 --- a/src/main/java/seedu/address/model/person/Person.java +++ b/src/main/java/seedu/address/model/person/Person.java @@ -9,6 +9,7 @@ import seedu.address.commons.util.ToStringBuilder; import seedu.address.model.tag.Tag; +import seedu.address.model.wedding.Wedding; /** * Represents a Person in the address book. @@ -24,17 +25,19 @@ public class Person { // Data fields private final Address address; private final Set tags = new HashSet<>(); + private final Set weddings = new HashSet<>(); /** * Every field must be present and not null. */ - public Person(Name name, Phone phone, Email email, Address address, Set tags) { - requireAllNonNull(name, phone, email, address, tags); + public Person(Name name, Phone phone, Email email, Address address, Set tags, Set weddings) { + requireAllNonNull(name, phone, email, address, tags, weddings); this.name = name; this.phone = phone; this.email = email; this.address = address; this.tags.addAll(tags); + this.weddings.addAll(weddings); } public Name getName() { @@ -61,6 +64,14 @@ public Set getTags() { return Collections.unmodifiableSet(tags); } + /** + * Returns an immutable tag set, which throws {@code UnsupportedOperationException} + * if modification is attempted. + */ + public Set getWeddings() { + return Collections.unmodifiableSet(weddings); + } + /** * Returns true if both persons have the same name. * This defines a weaker notion of equality between two persons. @@ -94,13 +105,14 @@ public boolean equals(Object other) { && phone.equals(otherPerson.phone) && email.equals(otherPerson.email) && address.equals(otherPerson.address) - && tags.equals(otherPerson.tags); + && tags.equals(otherPerson.tags) + && weddings.equals((otherPerson.weddings)); } @Override public int hashCode() { // use this method for custom fields hashing instead of implementing your own - return Objects.hash(name, phone, email, address, tags); + return Objects.hash(name, phone, email, address, tags, weddings); } @Override @@ -111,6 +123,7 @@ public String toString() { .add("email", email) .add("address", address) .add("tags", tags) + .add("weddings", weddings) .toString(); } diff --git a/src/main/java/seedu/address/model/person/TagContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/person/TagContainsKeywordsPredicate.java index 361bb2fca7a..117bef46b9e 100644 --- a/src/main/java/seedu/address/model/person/TagContainsKeywordsPredicate.java +++ b/src/main/java/seedu/address/model/person/TagContainsKeywordsPredicate.java @@ -8,7 +8,7 @@ import seedu.address.model.tag.Tag; /** - * Tests that a {@code Person}'s {@code Tag } matches any of the keywords given. + * Tests that a {@code Person}'s {@code Tag} matches any of the keywords given. */ public class TagContainsKeywordsPredicate implements Predicate { private final List keywords; diff --git a/src/main/java/seedu/address/model/person/WeddingContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/person/WeddingContainsKeywordsPredicate.java new file mode 100644 index 00000000000..6e13bf5ad3c --- /dev/null +++ b/src/main/java/seedu/address/model/person/WeddingContainsKeywordsPredicate.java @@ -0,0 +1,43 @@ +package seedu.address.model.person; + +import java.util.List; +import java.util.function.Predicate; + +import seedu.address.commons.util.StringUtil; +import seedu.address.commons.util.ToStringBuilder; +import seedu.address.model.wedding.Wedding; + +/** + * Tests that a {@code Person}'s {@code Wedding} matches any of the keywords given. + */ +public class WeddingContainsKeywordsPredicate implements Predicate { + private final List keywords; + + public WeddingContainsKeywordsPredicate(List keywords) { + this.keywords = keywords; + } + + @Override + public boolean test(Wedding wedding) { + return keywords.stream() + .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(wedding.getWeddingName().toString(), keyword)); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + + if (!(obj instanceof WeddingContainsKeywordsPredicate otherWeddingContainsKeywordsPredicate)) { + return false; + } + + return keywords.equals(otherWeddingContainsKeywordsPredicate.keywords); + } + + @Override + public String toString() { + return new ToStringBuilder(this).add("keywords", keywords).toString(); + } +} diff --git a/src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java b/src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java index fa764426ca7..f1592f96b87 100644 --- a/src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java +++ b/src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java @@ -3,4 +3,8 @@ /** * Signals that the operation is unable to find the specified person. */ -public class PersonNotFoundException extends RuntimeException {} +public class PersonNotFoundException extends RuntimeException { + public PersonNotFoundException() { + super("Person does not exist."); + } +} diff --git a/src/main/java/seedu/address/model/tag/Tag.java b/src/main/java/seedu/address/model/tag/Tag.java index 9b629eec4f2..6dda59a6d8a 100644 --- a/src/main/java/seedu/address/model/tag/Tag.java +++ b/src/main/java/seedu/address/model/tag/Tag.java @@ -8,7 +8,7 @@ */ public class Tag { - public static final String MESSAGE_CONSTRAINTS = "Tags names should be alphanumeric"; + public static final String MESSAGE_CONSTRAINTS = "Tag names should be alphanumeric"; public static final String VALIDATION_REGEX = "[\\p{Alnum}][\\p{Alnum} ]*"; private final TagName tagName; @@ -16,8 +16,7 @@ public class Tag { /** * Constructs a {@code Tag}. - * - * @param tagName A valid tag name. + * @param tagName A valid {@code TagName}. */ public Tag(TagName tagName) { requireNonNull(tagName); @@ -34,7 +33,7 @@ public static boolean isValidTagName(String test) { /** * Returns true if another tag has the same TagName as this tag. - * @param otherTag A tag to compare with. + * @param otherTag A {@code tag} to compare with. */ public boolean isSameTag(Tag otherTag) { if (otherTag == this) { @@ -92,6 +91,7 @@ public int hashCode() { /** * Format state as text for viewing. */ + @Override public String toString() { return '[' + tagName.toString() + ']'; } diff --git a/src/main/java/seedu/address/model/tag/TagName.java b/src/main/java/seedu/address/model/tag/TagName.java index ce23c11ce00..2060008eed8 100644 --- a/src/main/java/seedu/address/model/tag/TagName.java +++ b/src/main/java/seedu/address/model/tag/TagName.java @@ -4,16 +4,16 @@ import static seedu.address.commons.util.AppUtil.checkArgument; /** - * Represents a Tag's name in the address book. + * Represents a {@code Tag}'s name in the address book. * Guarantees: immutable; is valid as declared in {@link #isValidName(String)} */ public class TagName { public static final String MESSAGE_CONSTRAINTS = - "Tag names should only contain alphanumeric characters and spaces, and it should not be blank"; + "Tag names should only contain alphanumeric characters and spaces, and they should not be blank"; /* - * The first character of the address must not be a whitespace, + * The first character of the tag name must not be a whitespace, * otherwise " " (a blank string) becomes a valid input. */ public static final String VALIDATION_REGEX = "[\\p{Alnum}][\\p{Alnum} ]*"; @@ -21,9 +21,8 @@ public class TagName { public final String tagName; /** - * Constructs a {@code Name}. - * - * @param name A valid name. + * Constructs a {@code TagName}. + * @param name A valid name for a tag. */ public TagName(String name) { requireNonNull(name); diff --git a/src/main/java/seedu/address/model/tag/UniqueTagList.java b/src/main/java/seedu/address/model/tag/UniqueTagList.java index c7c7595b4c5..ffda89cc062 100644 --- a/src/main/java/seedu/address/model/tag/UniqueTagList.java +++ b/src/main/java/seedu/address/model/tag/UniqueTagList.java @@ -14,9 +14,9 @@ /** * A list of tags that enforces uniqueness and does not allow nulls. * A tag is considered unique by comparing using {@code Tag#isSameTag(Tag)}. As such, adding and updating of - * tags uses Tag#isSameTag(Tag) for equality to ensure that the person being added or updated is + * tags uses Tag#isSameTag(Tag) for equality to ensure that the tag being added or updated is * unique in terms of identity in the UniqueTagList. However, the removal of a tag uses Tag#equals(Object) to - * ensure that the person with exactly the same fields will be removed. + * ensure that the tag with exactly the same fields will be removed. * Supports a minimal set of list operations. * * @see Tag#isSameTag(Tag) @@ -28,7 +28,7 @@ public class UniqueTagList implements Iterable { FXCollections.unmodifiableObservableList(internalList); /** - * Returns true if the list contains an equivalent person as the given argument. + * Returns true if the list contains an equivalent tag as the given argument. */ public boolean contains(Tag toCheck) { requireNonNull(toCheck); @@ -50,21 +50,21 @@ public void add(Tag toAdd) { /** * Replaces the tag {@code target} in the list with {@code editedTag}. * {@code target} must exist in the list. - * The person identity of {@code editedTag} must not be the same as another existing tag in the list. + * The tag identity of {@code editedTag} must not be the same as another existing tag in the list. */ - public void setTag(Tag target, Tag editedPerson) { - requireAllNonNull(target, editedPerson); + public void setTag(Tag target, Tag editedTag) { + requireAllNonNull(target, editedTag); int index = internalList.indexOf(target); if (index == -1) { throw new TagNotFoundException(); } - if (!target.isSameTag(editedPerson) && contains(editedPerson)) { + if (!target.isSameTag(editedTag) && contains(editedTag)) { throw new DuplicateTagException(); } - internalList.set(index, editedPerson); + internalList.set(index, editedTag); } public void setTag(UniqueTagList replacement) { @@ -84,8 +84,8 @@ public void remove(Tag toRemove) { } /** - * Replaces the contents of this list with {@code persons}. - * {@code persons} must not contain duplicate persons. + * Replaces the contents of this list with {@code tags}. + * {@code tags} must not contain duplicate tags. */ public void setTags(List tags) { requireAllNonNull(tags); diff --git a/src/main/java/seedu/address/model/tag/exceptions/TagNotFoundException.java b/src/main/java/seedu/address/model/tag/exceptions/TagNotFoundException.java index 9de0aa2c897..f5f0e5f15c9 100644 --- a/src/main/java/seedu/address/model/tag/exceptions/TagNotFoundException.java +++ b/src/main/java/seedu/address/model/tag/exceptions/TagNotFoundException.java @@ -3,4 +3,8 @@ /** * Signals that the operation is unable to find the specified tag. */ -public class TagNotFoundException extends RuntimeException {} +public class TagNotFoundException extends RuntimeException { + public TagNotFoundException() { + super("Tag does not exist."); + } +} diff --git a/src/main/java/seedu/address/model/util/SampleDataUtil.java b/src/main/java/seedu/address/model/util/SampleDataUtil.java index 44cadf6c0f2..76b473de94e 100644 --- a/src/main/java/seedu/address/model/util/SampleDataUtil.java +++ b/src/main/java/seedu/address/model/util/SampleDataUtil.java @@ -13,6 +13,8 @@ import seedu.address.model.person.Phone; import seedu.address.model.tag.Tag; import seedu.address.model.tag.TagName; +import seedu.address.model.wedding.Wedding; +import seedu.address.model.wedding.WeddingName; /** * Contains utility methods for populating {@code AddressBook} with sample data. @@ -22,22 +24,28 @@ public static Person[] getSamplePersons() { return new Person[] { new Person(new Name("Alex Yeoh"), new Phone("87438807"), new Email("alexyeoh@example.com"), new Address("Blk 30 Geylang Street 29, #06-40"), - getTagSet("friends")), + getTagSet("friends"), + getWeddingSet("Casey's Wedding")), new Person(new Name("Bernice Yu"), new Phone("99272758"), new Email("berniceyu@example.com"), new Address("Blk 30 Lorong 3 Serangoon Gardens, #07-18"), - getTagSet("colleagues", "friends")), + getTagSet("colleagues", "friends"), + getWeddingSet()), new Person(new Name("Charlotte Oliveiro"), new Phone("93210283"), new Email("charlotte@example.com"), new Address("Blk 11 Ang Mo Kio Street 74, #11-04"), - getTagSet("neighbours")), + getTagSet("neighbours"), + getWeddingSet("Wedding August 2029", "Wedding 2")), new Person(new Name("David Li"), new Phone("91031282"), new Email("lidavid@example.com"), new Address("Blk 436 Serangoon Gardens Street 26, #16-43"), - getTagSet("family")), + getTagSet("family"), + getWeddingSet()), new Person(new Name("Irfan Ibrahim"), new Phone("92492021"), new Email("irfan@example.com"), new Address("Blk 47 Tampines Street 20, #17-35"), - getTagSet("classmates")), + getTagSet("classmates"), + getWeddingSet("Casey's Wedding")), new Person(new Name("Roy Balakrishnan"), new Phone("92624417"), new Email("royb@example.com"), new Address("Blk 45 Aljunied Street 85, #11-31"), - getTagSet("colleagues")) + getTagSet("colleagues"), + getWeddingSet("Wedding 10")) }; } @@ -59,4 +67,15 @@ public static Set getTagSet(String... strings) { .collect(Collectors.toSet()); } + + /** + * Returns a wedding set containing the list of weddings given. + */ + public static Set getWeddingSet(String... strings) { + return Arrays.stream(strings) + .map(WeddingName::new) + .map(Wedding::new) + .collect(Collectors.toSet()); + } + } diff --git a/src/main/java/seedu/address/model/wedding/UniqueWeddingList.java b/src/main/java/seedu/address/model/wedding/UniqueWeddingList.java new file mode 100644 index 00000000000..f21850e55c9 --- /dev/null +++ b/src/main/java/seedu/address/model/wedding/UniqueWeddingList.java @@ -0,0 +1,149 @@ +package seedu.address.model.wedding; + +import static java.util.Objects.requireNonNull; +import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; + +import java.util.Iterator; +import java.util.List; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import seedu.address.model.wedding.exceptions.DuplicateWeddingException; +import seedu.address.model.wedding.exceptions.WeddingNotFoundException; + +/** + * A list of weddings that enforces uniqueness and does not allow nulls. + * A wedding is considered unique by comparing using {@code Wedding#isSameWedding(Wedding)}. As such, adding and + * updating of tags uses Wedding#isSameWedding(Wedding) for equality to ensure that the wedding being added or updated + * is unique in terms of identity in the UniqueWeddingList. However, the removal of a wedding uses + * Wedding#equals(Object) to ensure that the wedding with exactly the same fields will be removed. + * Supports a minimal set of list operations. + * + * @see Wedding#isSameWedding(Wedding) + */ +public class UniqueWeddingList implements Iterable { + + private final ObservableList internalList = FXCollections.observableArrayList(); + private final ObservableList internalUnmodifiableList = + FXCollections.unmodifiableObservableList(internalList); + + /** + * Returns true if the list contains an equivalent wedding as the given argument. + */ + public boolean contains(Wedding toCheck) { + requireNonNull(toCheck); + return internalList.stream().anyMatch(toCheck::isSameWedding); + } + + /** + * Adds a wedding to the list. + * The wedding must not already exist in the list. + */ + public void add(Wedding toAdd) { + requireNonNull(toAdd); + if (contains(toAdd)) { + throw new DuplicateWeddingException(); + } + internalList.add(toAdd); + } + + /** + * Replaces the wedding {@code target} in the list with {@code editedWedding}. + * {@code target} must exist in the list. + * The wedding identity of {@code editedWedding} must not be the same as another existing wedding in the list. + */ + public void setWedding(Wedding target, Wedding editedWedding) { + requireAllNonNull(target, editedWedding); + + int index = internalList.indexOf(target); + if (index == -1) { + throw new WeddingNotFoundException(); + } + + if (!target.isSameWedding(editedWedding) && contains(editedWedding)) { + throw new DuplicateWeddingException(); + } + + internalList.set(index, editedWedding); + } + + public void setTag(UniqueWeddingList replacement) { + requireNonNull(replacement); + internalList.setAll(replacement.internalList); + } + + /** + * Removes the equivalent wedding from the list. + * The wedding must exist in the list. + */ + public void remove(Wedding toRemove) { + requireNonNull(toRemove); + if (!internalList.remove(toRemove)) { + throw new WeddingNotFoundException(); + } + } + + /** + * Replaces the contents of this list with {@code weddings}. + * {@code weddings} must not contain duplicate weddings. + */ + public void setWeddings(List weddings) { + requireAllNonNull(weddings); + if (!weddingsAreUnique(weddings)) { + throw new DuplicateWeddingException(); + } + + internalList.setAll(weddings); + } + + /** + * Returns the backing list as an unmodifiable {@code ObservableList}. + */ + public ObservableList asUnmodifiableObservableList() { + return internalUnmodifiableList; + } + + /** + * Returns true if {@code weddings} contains only unique weddings. + */ + private boolean weddingsAreUnique(List weddings) { + for (int i = 0; i < weddings.size() - 1; i++) { + for (int j = i + 1; j < weddings.size(); j++) { + if (weddings.get(i).isSameWedding(weddings.get(j))) { + return false; + } + } + } + return true; + } + + @Override + public Iterator iterator() { + return internalList.iterator(); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + // instanceof handles nulls + if (!(other instanceof UniqueWeddingList)) { + return false; + } + + UniqueWeddingList otherUniqueWeddingList = (UniqueWeddingList) other; + return internalList.equals(otherUniqueWeddingList.internalList); + } + + @Override + public int hashCode() { + return internalList.hashCode(); + } + + @Override + public String toString() { + return internalList.toString(); + } +} diff --git a/src/main/java/seedu/address/model/wedding/Wedding.java b/src/main/java/seedu/address/model/wedding/Wedding.java new file mode 100644 index 00000000000..04429ec69dc --- /dev/null +++ b/src/main/java/seedu/address/model/wedding/Wedding.java @@ -0,0 +1,108 @@ +package seedu.address.model.wedding; + +import static java.util.Objects.requireNonNull; + +/** + * Represents a Wedding in the system. + * Guarantees: immutable; name is valid as declared in {@link #isValidWeddingName(String)} + */ +public class Wedding { + public static final String MESSAGE_CONSTRAINTS = + "Wedding names should only contain alphanumeric characters, spaces or apostrophes, " + + "and they should not be blank."; + + /** + * Validation regex checks that first character of the wedding name must not be a whitespace, + * so that " " (a blank string) is not a valid input. + */ + public static final String VALIDATION_REGEX = "[\\p{Alnum}'][\\p{Alnum} ']*"; + private WeddingName weddingName; + private int peopleCount; + + /** + * Constructs a {@code Wedding} with the specified {@code weddingName} + * @param weddingName A valid {@code WeddingName} + */ + public Wedding(WeddingName weddingName) { + requireNonNull(weddingName); + this.weddingName = weddingName; + this.peopleCount = 0; + } + + /** + * Returns true if a given string is a valid wedding name. + */ + public static boolean isValidWeddingName(String checkName) { + return checkName.matches(VALIDATION_REGEX); + } + + /** + * Returns wedding name associated with wedding + * @return A {@code WeddingName} object representing the name of the wedding + */ + public WeddingName getWeddingName() { + return this.weddingName; + } + + /** + * Returns the number of people assigned to this wedding + * @return An {@code int} with the number of people assigned to the wedding + */ + public int getNumPersonsForWedding() { + return this.peopleCount; + } + + + public void increasePeopleCount() { + peopleCount++; + } + + public void decreasePeopleCount() { + peopleCount--; + } + + /** + * Returns true if the wedding can be deleted, + * wedding can be deleted if {@code peopleCount} is 0. + */ + public boolean canBeDeleted() { + return (peopleCount == 0); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (!(obj instanceof Wedding)) { + return true; + } + + Wedding otherWedding = (Wedding) obj; + return weddingName.equals(otherWedding.weddingName); + } + + /** + * Returns true if another wedding has the same WeddingName as this wedding. + * @param otherWedding A {@code Wedding} to compare with. + */ + public boolean isSameWedding(Wedding otherWedding) { + if (otherWedding == this) { + return true; + } + + // Wedding#equals(Object) covers the null case + return otherWedding.getWeddingName().equals(getWeddingName()); + } + + @Override + public int hashCode() { + return weddingName.hashCode(); + } + + @Override + public String toString() { + return '[' + weddingName.toString() + ']'; + } +} diff --git a/src/main/java/seedu/address/model/wedding/WeddingName.java b/src/main/java/seedu/address/model/wedding/WeddingName.java new file mode 100644 index 00000000000..4e14cfa7a7e --- /dev/null +++ b/src/main/java/seedu/address/model/wedding/WeddingName.java @@ -0,0 +1,74 @@ +package seedu.address.model.wedding; + +import static java.util.Objects.requireNonNull; +import static seedu.address.commons.util.AppUtil.checkArgument; + +/** + * Represents a {@code Wedding}'s name in the address book. + * Guarantees: immutable; is valid as declared in {@link #isValidName(String)} + */ +public class WeddingName { + public static final String MESSAGE_CONSTRAINTS = + "Wedding names should only contain alphanumeric characters, spaces or apostrophes, " + + "and they should not be blank."; + + /** + * Validation regex checks that first character of the wedding name must not be a whitespace, + * so that " " (a blank string) is not a valid input. + */ + public static final String VALIDATION_REGEX = "[\\p{Alnum}'][\\p{Alnum} ']*"; + private final String weddingName; + + /** + * Constructs a {@code WeddingName} + * @param name A valid name for a wedding. + */ + public WeddingName(String name) { + requireNonNull(name); + checkArgument(isValidName(name), MESSAGE_CONSTRAINTS); + weddingName = name; + } + + /** + * Returns true if the given name matched the validation regex. + * @param nameToCheck A {@code String} with the name of the wedding. + * @return A {@code boolean}, true if the name is valid based on the validation regex, false if not. + */ + public static boolean isValidName(String nameToCheck) { + return nameToCheck.matches(VALIDATION_REGEX); + } + + @Override + public String toString() { + return weddingName; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (!(obj instanceof WeddingName)) { + return false; + } + + WeddingName otherWeddingName = (WeddingName) obj; + return this.weddingName.equals(otherWeddingName.weddingName); + } + + @Override + public int hashCode() { + return weddingName.hashCode(); + } + + /** + * Checks if the {@code WeddingName} object matches the given validation regex + * by checking the internal {@code WeddingName} + * @param validationRegex A {@code String} with the validation regex to check the wedding name against + * @return true if wedding name matches the validation regex, false if not. + */ + public boolean matches(String validationRegex) { + return weddingName.matches(validationRegex); + } +} diff --git a/src/main/java/seedu/address/model/wedding/exceptions/DuplicateWeddingException.java b/src/main/java/seedu/address/model/wedding/exceptions/DuplicateWeddingException.java new file mode 100644 index 00000000000..e0e96f483a7 --- /dev/null +++ b/src/main/java/seedu/address/model/wedding/exceptions/DuplicateWeddingException.java @@ -0,0 +1,11 @@ +package seedu.address.model.wedding.exceptions; + +/** + * Signals that the operation will result in duplicate {@code Wedding}s. + * Weddings are considered duplicates if they have the same {@code WeddingName}. + */ +public class DuplicateWeddingException extends RuntimeException { + public DuplicateWeddingException() { + super("Operation would result in duplicate weddings"); + } +} diff --git a/src/main/java/seedu/address/model/wedding/exceptions/WeddingNotFoundException.java b/src/main/java/seedu/address/model/wedding/exceptions/WeddingNotFoundException.java new file mode 100644 index 00000000000..d990d45427d --- /dev/null +++ b/src/main/java/seedu/address/model/wedding/exceptions/WeddingNotFoundException.java @@ -0,0 +1,10 @@ +package seedu.address.model.wedding.exceptions; + +/** + * Signals that the operation is unable to find the specified wedding. + */ +public class WeddingNotFoundException extends RuntimeException { + public WeddingNotFoundException() { + super("Wedding does not exist."); + } +} diff --git a/src/main/java/seedu/address/storage/JsonAdaptedPerson.java b/src/main/java/seedu/address/storage/JsonAdaptedPerson.java index 527dfdb8a96..989b6914e56 100644 --- a/src/main/java/seedu/address/storage/JsonAdaptedPerson.java +++ b/src/main/java/seedu/address/storage/JsonAdaptedPerson.java @@ -16,6 +16,7 @@ import seedu.address.model.person.Person; import seedu.address.model.person.Phone; import seedu.address.model.tag.Tag; +import seedu.address.model.wedding.Wedding; /** * Jackson-friendly version of {@link Person}. @@ -29,6 +30,7 @@ class JsonAdaptedPerson { private final String email; private final String address; private final List tags = new ArrayList<>(); + private final List weddings = new ArrayList<>(); /** * Constructs a {@code JsonAdaptedPerson} with the given person details. @@ -36,7 +38,8 @@ class JsonAdaptedPerson { @JsonCreator public JsonAdaptedPerson(@JsonProperty("name") String name, @JsonProperty("phone") String phone, @JsonProperty("email") String email, @JsonProperty("address") String address, - @JsonProperty("tags") List tags) { + @JsonProperty("tags") List tags, + @JsonProperty("weddings") List weddings) { this.name = name; this.phone = phone; this.email = email; @@ -44,6 +47,9 @@ public JsonAdaptedPerson(@JsonProperty("name") String name, @JsonProperty("phone if (tags != null) { this.tags.addAll(tags); } + if (weddings != null) { + this.weddings.addAll(weddings); + } } /** @@ -57,6 +63,9 @@ public JsonAdaptedPerson(Person source) { tags.addAll(source.getTags().stream() .map(JsonAdaptedTag::new) .collect(Collectors.toList())); + weddings.addAll(source.getWeddings().stream() + .map(JsonAdaptedWedding::new) + .collect(Collectors.toList())); } /** @@ -66,10 +75,19 @@ public JsonAdaptedPerson(Person source) { */ public Person toModelType() throws IllegalValueException { final List personTags = new ArrayList<>(); + final List personWeddings = new ArrayList<>(); + for (JsonAdaptedTag tag : tags) { personTags.add(tag.toModelType()); } + for (JsonAdaptedWedding wedding : weddings) { + if (!Wedding.isValidWeddingName(wedding.getWeddingName())) { + throw new IllegalValueException(Wedding.MESSAGE_CONSTRAINTS); + } + personWeddings.add(wedding.toModelType()); + } + if (name == null) { throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Name.class.getSimpleName())); } @@ -100,7 +118,9 @@ public Person toModelType() throws IllegalValueException { final Address modelAddress = new Address(address); final Set modelTags = new HashSet<>(personTags); - return new Person(modelName, modelPhone, modelEmail, modelAddress, modelTags); + final Set modelWeddings = new HashSet<>(personWeddings); + + return new Person(modelName, modelPhone, modelEmail, modelAddress, modelTags, modelWeddings); } } diff --git a/src/main/java/seedu/address/storage/JsonAdaptedTag.java b/src/main/java/seedu/address/storage/JsonAdaptedTag.java index 5a8b60e56f0..63bb63356d6 100644 --- a/src/main/java/seedu/address/storage/JsonAdaptedTag.java +++ b/src/main/java/seedu/address/storage/JsonAdaptedTag.java @@ -11,7 +11,6 @@ * Jackson-friendly version of {@link Tag}. */ class JsonAdaptedTag { - private final String tagName; /** diff --git a/src/main/java/seedu/address/storage/JsonAdaptedWedding.java b/src/main/java/seedu/address/storage/JsonAdaptedWedding.java new file mode 100644 index 00000000000..0f7b9b31219 --- /dev/null +++ b/src/main/java/seedu/address/storage/JsonAdaptedWedding.java @@ -0,0 +1,47 @@ +package seedu.address.storage; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import seedu.address.commons.exceptions.IllegalValueException; +import seedu.address.model.wedding.Wedding; +import seedu.address.model.wedding.WeddingName; + +/** + * Jackson-friendly version of {@link Wedding}. + */ +public class JsonAdaptedWedding { + private final String weddingName; + + /** + * Constructs a {@code JsonAdaptedWedding} with the given {@code weddingName}. + */ + @JsonCreator + public JsonAdaptedWedding(String weddingName) { + this.weddingName = weddingName; + } + + /** + * Converts a given {@code Wedding} into this class for Jackson use. + */ + public JsonAdaptedWedding(Wedding source) { + weddingName = source.getWeddingName().toString(); + } + + @JsonValue + public String getWeddingName() { + return weddingName; + } + + /** + * Converts this Jackson-friendly adapted wedding object into the model's {@code Wedding} object. + * + * @throws IllegalValueException if there were any data constraints violated in the adapted wedding. + */ + public Wedding toModelType() throws IllegalValueException { + if (!Wedding.isValidWeddingName(weddingName)) { + throw new IllegalValueException(WeddingName.MESSAGE_CONSTRAINTS); + } + return new Wedding(new WeddingName(weddingName)); + } +} diff --git a/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java b/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java index 61b2424dfa6..1ef393cc6a6 100644 --- a/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java +++ b/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java @@ -2,6 +2,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Set; import java.util.stream.Collectors; import com.fasterxml.jackson.annotation.JsonCreator; @@ -13,6 +14,7 @@ import seedu.address.model.ReadOnlyAddressBook; import seedu.address.model.person.Person; import seedu.address.model.tag.Tag; +import seedu.address.model.wedding.Wedding; /** * An Immutable AddressBook that is serializable to JSON format. @@ -22,19 +24,23 @@ class JsonSerializableAddressBook { public static final String MESSAGE_DUPLICATE_PERSON = "Persons list contains duplicate person(s)."; public static final String MESSAGE_DUPLICATE_TAG = "Tags list contains duplicate tag(s)."; + public static final String MESSAGE_DUPLICATE_WEDDING = "Weddings list contains duplicate wedding(s)."; private final List persons = new ArrayList<>(); private final List tags = new ArrayList<>(); + private final List weddings = new ArrayList<>(); /** - * Constructs a {@code JsonSerializableAddressBook} with the given persons and tag. + * Constructs a {@code JsonSerializableAddressBook} with the given persons, tag, and weddings. */ @JsonCreator public JsonSerializableAddressBook( @JsonProperty("persons") List persons, - @JsonProperty("tags") List tags) { + @JsonProperty("tags") List tags, + @JsonProperty("weddings") List weddings) { this.persons.addAll(persons); this.tags.addAll(tags); + this.weddings.addAll(weddings); } /** @@ -45,6 +51,7 @@ public JsonSerializableAddressBook( public JsonSerializableAddressBook(ReadOnlyAddressBook source) { persons.addAll(source.getPersonList().stream().map(JsonAdaptedPerson::new).collect(Collectors.toList())); tags.addAll(source.getTagList().stream().map(JsonAdaptedTag::new).collect(Collectors.toList())); + weddings.addAll(source.getWeddingList().stream().map(JsonAdaptedWedding::new).collect(Collectors.toList())); } /** @@ -68,6 +75,40 @@ public AddressBook toModelType() throws IllegalValueException { } addressBook.addTag(tag); } + for (JsonAdaptedWedding jsonAdaptedWedding : weddings) { + Wedding wedding = jsonAdaptedWedding.toModelType(); + if (addressBook.hasWedding(wedding)) { + throw new IllegalValueException(MESSAGE_DUPLICATE_WEDDING); + } + addressBook.addWedding(wedding); + } + // load tags and weddings from people after loading weddings and tags, because if tag or wedding already exist, + // method will throw an error + for (JsonAdaptedPerson jsonAdaptedPerson : persons) { + Person person = jsonAdaptedPerson.toModelType(); + loadTags(addressBook, person); + loadWeddings(addressBook, person); + } return addressBook; } + + private void loadTags(AddressBook addressBook, Person person) { + Set tagList = person.getTags(); + for (Tag tag : tagList) { + if (addressBook.hasTag(tag) || !Tag.isValidTagName(tag.getTagName().toString())) { + continue; + } + addressBook.addTag(tag); + } + } + + private void loadWeddings(AddressBook addressBook, Person person) { + Set weddingList = person.getWeddings(); + for (Wedding wedding : weddingList) { + if (addressBook.hasWedding(wedding) || !Wedding.isValidWeddingName(wedding.getWeddingName().toString())) { + continue; + } + addressBook.addWedding(wedding); + } + } } diff --git a/src/main/java/seedu/address/ui/PersonCard.java b/src/main/java/seedu/address/ui/PersonCard.java index 521083fa65b..c44e7e2394b 100644 --- a/src/main/java/seedu/address/ui/PersonCard.java +++ b/src/main/java/seedu/address/ui/PersonCard.java @@ -10,7 +10,7 @@ import seedu.address.model.person.Person; /** - * An UI component that displays information of a {@code Person}. + * A UI component that displays information of a {@code Person}. */ public class PersonCard extends UiPart { @@ -40,6 +40,8 @@ public class PersonCard extends UiPart { private Label email; @FXML private FlowPane tags; + @FXML + private FlowPane weddings; /** * Creates a {@code PersonCode} with the given {@code Person} and index to display. @@ -55,5 +57,8 @@ public PersonCard(Person person, int displayedIndex) { person.getTags().stream() .sorted(Comparator.comparing(tag -> tag.getTagName().toString())) .forEach(tag -> tags.getChildren().add(new Label(tag.getTagName().toString()))); + person.getWeddings().stream() + .sorted(Comparator.comparing(wedding -> wedding.getWeddingName().toString())) + .forEach(wedding -> weddings.getChildren().add(new Label(wedding.getWeddingName().toString()))); } } diff --git a/src/main/resources/view/DarkTheme.css b/src/main/resources/view/DarkTheme.css index 36e6b001cd8..d3dbcf1cb37 100644 --- a/src/main/resources/view/DarkTheme.css +++ b/src/main/resources/view/DarkTheme.css @@ -350,3 +350,17 @@ -fx-background-radius: 2; -fx-font-size: 11; } + +#weddings { + -fx-hgap: 7; + -fx-vgap: 3; +} + +#weddings .label { + -fx-text-fill: white; + -fx-background-color: #228B22; + -fx-padding: 1 3 1 3; + -fx-border-radius: 2; + -fx-background-radius: 2; + -fx-font-size: 11; +} diff --git a/src/main/resources/view/PersonListCard.fxml b/src/main/resources/view/PersonListCard.fxml index 84e09833a87..4450713ad21 100644 --- a/src/main/resources/view/PersonListCard.fxml +++ b/src/main/resources/view/PersonListCard.fxml @@ -7,30 +7,40 @@ + - + - + - + + - - + + + + + + + + + diff --git a/src/test/data/JsonAddressBookStorageTest/invalidAndValidPersonAddressBook.json b/src/test/data/JsonAddressBookStorageTest/invalidAndValidPersonAddressBook.json index 6a4d2b7181c..b95a76c2fb8 100644 --- a/src/test/data/JsonAddressBookStorageTest/invalidAndValidPersonAddressBook.json +++ b/src/test/data/JsonAddressBookStorageTest/invalidAndValidPersonAddressBook.json @@ -9,5 +9,7 @@ "phone": "948asdf2424", "email": "hans@example.com", "address": "4th street" - } ] + } ], + "tags": [], + "weddings": [] } diff --git a/src/test/data/JsonAddressBookStorageTest/invalidPersonAddressBook.json b/src/test/data/JsonAddressBookStorageTest/invalidPersonAddressBook.json index ccd21f7d1a9..6281db4c10c 100644 --- a/src/test/data/JsonAddressBookStorageTest/invalidPersonAddressBook.json +++ b/src/test/data/JsonAddressBookStorageTest/invalidPersonAddressBook.json @@ -4,5 +4,7 @@ "phone": "9482424", "email": "hans@example.com", "address": "4th street" - } ] + } ], + "tags": [], + "weddings": [] } diff --git a/src/test/data/JsonAddressBookStorageTest/invalidTagAddressBook.json b/src/test/data/JsonAddressBookStorageTest/invalidTagAddressBook.json new file mode 100644 index 00000000000..bec5f5644c7 --- /dev/null +++ b/src/test/data/JsonAddressBookStorageTest/invalidTagAddressBook.json @@ -0,0 +1,10 @@ +{ + "persons": [ { + "name": "Valid Person", + "phone": "9482424", + "email": "hans@example.com", + "address": "4th street" + }], + "tags": ["Valid Tag", " "], + "weddings": ["Valid Wedding"] +} diff --git a/src/test/data/JsonAddressBookStorageTest/invalidWeddingAddressBook.json b/src/test/data/JsonAddressBookStorageTest/invalidWeddingAddressBook.json new file mode 100644 index 00000000000..630f41d70d6 --- /dev/null +++ b/src/test/data/JsonAddressBookStorageTest/invalidWeddingAddressBook.json @@ -0,0 +1,10 @@ +{ + "persons": [ { + "name": "Valid Person", + "phone": "9482424", + "email": "hans@example.com", + "address": "4th street" + }], + "tags": ["Valid Tag"], + "weddings": [" "] +} diff --git a/src/test/data/JsonSerializableAddressBookTest/duplicatePersonAddressBook.json b/src/test/data/JsonSerializableAddressBookTest/duplicatePersonAddressBook.json index 02bfd8316c8..6b1dbae9aae 100644 --- a/src/test/data/JsonSerializableAddressBookTest/duplicatePersonAddressBook.json +++ b/src/test/data/JsonSerializableAddressBookTest/duplicatePersonAddressBook.json @@ -11,6 +11,6 @@ "email": "pauline@example.com", "address": "4th street" } ], - - "tags": ["florist"] + "tags": ["florist"], + "weddings": [] } diff --git a/src/test/data/JsonSerializableAddressBookTest/duplicateTagAddressBook.json b/src/test/data/JsonSerializableAddressBookTest/duplicateTagAddressBook.json new file mode 100644 index 00000000000..536f1968239 --- /dev/null +++ b/src/test/data/JsonSerializableAddressBookTest/duplicateTagAddressBook.json @@ -0,0 +1,11 @@ +{ + "persons": [ { + "name": "Alice Pauline", + "phone": "94351253", + "email": "alice@example.com", + "address": "123, Jurong West Ave 6, #08-111", + "tags": [ "friends" ] + }], + "tags": ["florist", "chef", "florist"], + "weddings": ["Wedding July 2026"] +} diff --git a/src/test/data/JsonSerializableAddressBookTest/duplicateWeddingAddressBook.json b/src/test/data/JsonSerializableAddressBookTest/duplicateWeddingAddressBook.json new file mode 100644 index 00000000000..df1376a4bba --- /dev/null +++ b/src/test/data/JsonSerializableAddressBookTest/duplicateWeddingAddressBook.json @@ -0,0 +1,11 @@ +{ + "persons": [ { + "name": "Alice Pauline", + "phone": "94351253", + "email": "alice@example.com", + "address": "123, Jurong West Ave 6, #08-111", + "tags": [ "friends" ] + }], + "tags": ["florist", "chef"], + "weddings": ["Wedding July 2026", "Wedding 1", "Wedding July 2026", "Paula's Wedding"] +} diff --git a/src/test/data/JsonSerializableAddressBookTest/invalidPersonAddressBook.json b/src/test/data/JsonSerializableAddressBookTest/invalidPersonAddressBook.json index 2cf46c1b310..3278e110d29 100644 --- a/src/test/data/JsonSerializableAddressBookTest/invalidPersonAddressBook.json +++ b/src/test/data/JsonSerializableAddressBookTest/invalidPersonAddressBook.json @@ -5,5 +5,6 @@ "email": "invalid@email!3e", "address": "4th street" } ], - "tags": ["florist"] + "tags": ["florist"], + "weddings": [] } diff --git a/src/test/data/JsonSerializableAddressBookTest/invalidTagAddressBook.json b/src/test/data/JsonSerializableAddressBookTest/invalidTagAddressBook.json new file mode 100644 index 00000000000..037d42b390b --- /dev/null +++ b/src/test/data/JsonSerializableAddressBookTest/invalidTagAddressBook.json @@ -0,0 +1,10 @@ +{ + "persons": [ { + "name": "Hans Muster", + "phone": "9482424", + "email": "valid@email.ede", + "address": "4th street" + } ], + "tags": ["florist", " "], + "weddings": ["Wedding 19"] +} diff --git a/src/test/data/JsonSerializableAddressBookTest/invalidWeddingAddressBook.json b/src/test/data/JsonSerializableAddressBookTest/invalidWeddingAddressBook.json new file mode 100644 index 00000000000..ef459b24c63 --- /dev/null +++ b/src/test/data/JsonSerializableAddressBookTest/invalidWeddingAddressBook.json @@ -0,0 +1,10 @@ +{ + "persons": [ { + "name": "Hans Muster", + "phone": "9482424", + "email": "valid@email.ede", + "address": "4th street" + } ], + "tags": ["florist", "musician"], + "weddings": ["Wedding 19", " "] +} diff --git a/src/test/data/JsonSerializableAddressBookTest/typicalPersonsAddressBook.json b/src/test/data/JsonSerializableAddressBookTest/typicalPersonsAddressBook.json index 43eb9a325a0..323f6d95174 100644 --- a/src/test/data/JsonSerializableAddressBookTest/typicalPersonsAddressBook.json +++ b/src/test/data/JsonSerializableAddressBookTest/typicalPersonsAddressBook.json @@ -11,7 +11,8 @@ "phone" : "98765432", "email" : "johnd@example.com", "address" : "311, Clementi Ave 2, #02-25", - "tags" : [ "owesMoney", "friends" ] + "tags" : [ "owesMoney", "friends" ], + "weddings": ["Wedding 2", "Carla's Wedding"] }, { "name" : "Carl Kurz", "phone" : "95352563", @@ -43,5 +44,6 @@ "address" : "4th street", "tags" : [ ] } ], - "tags": ["florist"] + "tags": ["florist"], + "weddings": ["Wedding 2", "Carla's Wedding"] } diff --git a/src/test/java/seedu/address/logic/MessagesTest.java b/src/test/java/seedu/address/logic/MessagesTest.java index c51b025cb91..6124dda957e 100644 --- a/src/test/java/seedu/address/logic/MessagesTest.java +++ b/src/test/java/seedu/address/logic/MessagesTest.java @@ -47,7 +47,8 @@ public void format_person_success() { String expectedOutput = "John Doe; Phone: 12345678; Email: john@example.com; Address: 123 Main St; Tags: " + person.getTags().stream() .map(Tag::toString) - .collect(Collectors.joining()); + .collect(Collectors.joining()) + + "; Weddings: "; String actualOutput = Messages.format(person); assertEquals(expectedOutput, actualOutput); diff --git a/src/test/java/seedu/address/logic/commands/AddCommandTest.java b/src/test/java/seedu/address/logic/commands/AddCommandTest.java index b6387c76bce..adb3bf47ed1 100644 --- a/src/test/java/seedu/address/logic/commands/AddCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddCommandTest.java @@ -24,6 +24,7 @@ import seedu.address.model.ReadOnlyUserPrefs; import seedu.address.model.person.Person; import seedu.address.model.tag.Tag; +import seedu.address.model.wedding.Wedding; import seedu.address.testutil.PersonBuilder; public class AddCommandTest { @@ -184,6 +185,36 @@ public ObservableList getFilteredTagList() { throw new AssertionError("This method should not be called."); } + @Override + public boolean hasWedding(Wedding toAdd) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void addWedding(Wedding toAdd) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void deleteWedding(Wedding toDelete) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void setWedding(Wedding target, Wedding editedWedding) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void updateFilteredWeddingList(Predicate predicate) { + throw new AssertionError("This method should not be called."); + } + + @Override + public ObservableList getFilteredWeddingList() { + throw new AssertionError("This method should not be called."); + } + @Override public void deleteTag(Tag toDelete) { throw new AssertionError("This method should not be called."); diff --git a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java index 293d44e15d2..7490c036343 100644 --- a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java +++ b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java @@ -7,6 +7,7 @@ import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; +import static seedu.address.logic.parser.CliSyntax.PREFIX_WEDDING; import static seedu.address.testutil.Assert.assertThrows; import java.util.ArrayList; @@ -53,6 +54,7 @@ public class CommandTestUtil { public static final String VALID_TAG_FLORIST = "florist"; public static final String VALID_TAG_NEIGHBOR = "neighbor"; public static final String VALID_TAG_PHOTOGRAPHER = "photographer"; + public static final String VALID_WEDDING_AMY = "Amy's Wedding"; public static final String NAME_DESC_AMY = " " + PREFIX_NAME + VALID_NAME_AMY; public static final String NAME_DESC_BOB = " " + PREFIX_NAME + VALID_NAME_BOB; @@ -78,6 +80,7 @@ public class CommandTestUtil { public static final String TAG_DESC_NEIGHBOR = " " + PREFIX_TAG + VALID_TAG_NEIGHBOR; public static final String TAG_DESC_FLORIST = " " + PREFIX_TAG + VALID_TAG_FLORIST; public static final String TAG_DESC_PHOTOGRAPHER = " " + PREFIX_TAG + VALID_TAG_FLORIST; + public static final String WEDDING_DESC_AMY = " " + PREFIX_WEDDING + VALID_WEDDING_AMY; public static final String INVALID_NAME_DESC = " " + PREFIX_NAME + "James&"; // '&' not allowed in names public static final String INVALID_PHONE_DESC = " " + PREFIX_PHONE + "911a"; // 'a' not allowed in phones @@ -85,6 +88,7 @@ public class CommandTestUtil { public static final String INVALID_PHONE_DESC_TOO_SHORT = " " + PREFIX_PHONE + "91"; public static final String INVALID_EMAIL_DESC = " " + PREFIX_EMAIL + "bob!yahoo"; // missing '@' symbol public static final String INVALID_TAG_DESC = " " + PREFIX_TAG + "hubby*"; // '*' not allowed in tags + public static final String INVALID_WEDDING_DESC = " " + PREFIX_WEDDING + "Amy's_Wedding"; //'_' not allowed public static final String BLANK_ADDRESS_DESC = " " + PREFIX_ADDRESS + VALID_ADDRESS_BLANK; public static final String PREAMBLE_WHITESPACE = "\t \r \n"; public static final String PREAMBLE_NON_EMPTY = "NonEmptyPreamble"; diff --git a/src/test/java/seedu/address/logic/commands/CreateTagCommandTest.java b/src/test/java/seedu/address/logic/commands/CreateTagCommandTest.java index 4d4865f1e33..dffdf3c9864 100644 --- a/src/test/java/seedu/address/logic/commands/CreateTagCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/CreateTagCommandTest.java @@ -25,6 +25,7 @@ import seedu.address.model.person.Person; import seedu.address.model.tag.Tag; import seedu.address.model.tag.TagName; +import seedu.address.model.wedding.Wedding; public class CreateTagCommandTest { @@ -172,6 +173,35 @@ public void addTag(Tag toAdd) { throw new AssertionError("This method should not be called."); } + @Override + public boolean hasWedding(Wedding toAdd) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void addWedding(Wedding toAdd) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void setWedding(Wedding target, Wedding editedWedding) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void deleteWedding(Wedding tag) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void updateFilteredWeddingList(Predicate predicate) { + throw new AssertionError("This method should not be called."); + } + + @Override + public ObservableList getFilteredWeddingList() { + throw new AssertionError("This method should not be called."); + } @Override public void updateFilteredTagList(Predicate predicate) { throw new AssertionError("This method should not be called."); diff --git a/src/test/java/seedu/address/logic/commands/EditPersonDescriptorTest.java b/src/test/java/seedu/address/logic/commands/EditPersonDescriptorTest.java index b17c1f3d5c2..87f2287b906 100644 --- a/src/test/java/seedu/address/logic/commands/EditPersonDescriptorTest.java +++ b/src/test/java/seedu/address/logic/commands/EditPersonDescriptorTest.java @@ -65,7 +65,8 @@ public void toStringMethod() { + editPersonDescriptor.getPhone().orElse(null) + ", email=" + editPersonDescriptor.getEmail().orElse(null) + ", address=" + editPersonDescriptor.getAddress().orElse(null) + ", tags=" - + editPersonDescriptor.getTags().orElse(null) + "}"; + + editPersonDescriptor.getTags().orElse(null) + ", weddings=" + + editPersonDescriptor.getWeddings().orElse(null) + "}"; assertEquals(expected, editPersonDescriptor.toString()); } } diff --git a/src/test/java/seedu/address/logic/commands/TagCommandTest.java b/src/test/java/seedu/address/logic/commands/TagCommandTest.java index 8903f3d89a2..992b1b968a2 100644 --- a/src/test/java/seedu/address/logic/commands/TagCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/TagCommandTest.java @@ -43,7 +43,8 @@ public void execute_validTagsUnfilteredList_success() { personToEdit.getPhone(), personToEdit.getEmail(), personToEdit.getAddress(), - updatedTags); + updatedTags, + personToEdit.getWeddings()); expectedModel.setPerson(personToEdit, editedPerson); CommandTestUtil.assertCommandSuccess(tagCommand, model, expectedMessage, expectedModel); @@ -57,8 +58,10 @@ public void execute_validMultipleTagsUnfilteredList_success() { new seedu.address.model.person.Phone("99999999"), new seedu.address.model.person.Email("test@example.com"), new seedu.address.model.person.Address("123, Test Street"), - new HashSet<>(Arrays.asList(new Tag(new TagName("family")))) + new HashSet<>(Arrays.asList(new Tag(new TagName("family")))), + new HashSet<>() ); + model.addTag(new Tag(new TagName("family"))); model.setPerson(model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()), personWithTags); model.addTag(new Tag(new TagName("colleague"))); model.addTag(new Tag(new TagName("gym"))); @@ -77,7 +80,8 @@ public void execute_validMultipleTagsUnfilteredList_success() { personWithTags.getPhone(), personWithTags.getEmail(), personWithTags.getAddress(), - updatedTags); + updatedTags, + personWithTags.getWeddings()); expectedModel.setPerson(personWithTags, editedPerson); CommandTestUtil.assertCommandSuccess(tagCommand, model, expectedMessage, expectedModel); diff --git a/src/test/java/seedu/address/logic/commands/UntagCommandTest.java b/src/test/java/seedu/address/logic/commands/UntagCommandTest.java new file mode 100644 index 00000000000..9aede7c4ded --- /dev/null +++ b/src/test/java/seedu/address/logic/commands/UntagCommandTest.java @@ -0,0 +1,140 @@ +package seedu.address.logic.commands; + +import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; +import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON; +import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import org.junit.jupiter.api.Test; + +import seedu.address.commons.core.index.Index; +import seedu.address.logic.Messages; +import seedu.address.model.Model; +import seedu.address.model.ModelManager; +import seedu.address.model.UserPrefs; +import seedu.address.model.person.Person; +import seedu.address.model.tag.Tag; +import seedu.address.model.tag.TagName; +import seedu.address.model.wedding.Wedding; +import seedu.address.model.wedding.WeddingName; + +public class UntagCommandTest { + + private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + + + @Test + public void execute_validTagsUnfilteredList_success() { + Person personToEdit = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); + HashSet tagsToRemove = new HashSet<>(Arrays.asList(new Tag(new TagName("friends")))); + + UntagCommand untagCommand = new UntagCommand(INDEX_FIRST_PERSON, tagsToRemove); + + String expectedMessage = String.format(UntagCommand.MESSAGE_REMOVE_TAG_SUCCESS, + "friends", personToEdit.getName().toString()); + + Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); + Set updatedTags = new HashSet<>(personToEdit.getTags()); + updatedTags.removeAll(tagsToRemove); + Person editedPerson = new Person( + personToEdit.getName(), + personToEdit.getPhone(), + personToEdit.getEmail(), + personToEdit.getAddress(), + updatedTags, + personToEdit.getWeddings()); + expectedModel.setPerson(personToEdit, editedPerson); + + CommandTestUtil.assertCommandSuccess(untagCommand, model, expectedMessage, expectedModel); + } + + + @Test + public void execute_validMultipleTagsUnfilteredList_success() { + Person personWithTags = new Person( + new seedu.address.model.person.Name("Test Person"), + new seedu.address.model.person.Phone("99999999"), + new seedu.address.model.person.Email("test@example.com"), + new seedu.address.model.person.Address("123, Test Street"), + new HashSet<>(Arrays.asList(new Tag(new TagName("friends")), new Tag(new TagName("owesMoney")))), + new HashSet<>() + ); + model.setPerson(model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()), personWithTags); + HashSet tagsToRemove = new HashSet<>(Arrays.asList(new Tag(new TagName("friends")), + new Tag(new TagName("owesMoney")))); + UntagCommand untagCommand = new UntagCommand(INDEX_FIRST_PERSON, tagsToRemove); + String expectedMessage = String.format(UntagCommand.MESSAGE_REMOVE_TAG_SUCCESS, + "owesMoney, friends", personWithTags.getName().toString()); + + // Create the expected model with the updated tags (i.e., an empty set of tags) + Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); + HashSet updatedTags = new HashSet<>(personWithTags.getTags()); + updatedTags.removeAll(tagsToRemove); + Person editedPerson = new Person( + personWithTags.getName(), + personWithTags.getPhone(), + personWithTags.getEmail(), + personWithTags.getAddress(), + updatedTags, + personWithTags.getWeddings()); + expectedModel.setPerson(personWithTags, editedPerson); + + CommandTestUtil.assertCommandSuccess(untagCommand, model, expectedMessage, expectedModel); + } + + + @Test + public void execute_nonExistentTag_failure() { + HashSet tagsToRemove = new HashSet<>(Arrays.asList(new Tag(new TagName("nonExistentTag")))); + UntagCommand untagCommand = new UntagCommand(INDEX_FIRST_PERSON, tagsToRemove); + String expectedMessage = Messages.MESSAGE_TAG_NOT_FOUND_IN_CONTACT; + CommandTestUtil.assertCommandFailure(untagCommand, model, expectedMessage); + } + + + @Test + public void execute_noTagsSpecified_failure() { + // No tags specified to remove + HashSet emptyTagsToRemove = new HashSet<>(Arrays.asList()); + UntagCommand untagCommand = new UntagCommand(INDEX_FIRST_PERSON, emptyTagsToRemove); + String expectedMessage = Messages.MESSAGE_TAG_NOT_FOUND_IN_CONTACT; + CommandTestUtil.assertCommandFailure(untagCommand, model, expectedMessage); + } + + + @Test + public void execute_invalidIndexUnfilteredList_failure() { + Index outOfBoundIndex = Index.fromOneBased(model.getFilteredPersonList().size() + 1); + HashSet tagsToRemove = new HashSet<>(Arrays.asList(new Tag(new TagName("friends")))); + + UntagCommand untagCommand = new UntagCommand(outOfBoundIndex, tagsToRemove); + + String expectedMessage = Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX; + + CommandTestUtil.assertCommandFailure(untagCommand, model, expectedMessage); + } + + + @Test + public void execute_personWithoutTags_failure() { + Person personWithoutTags = new Person( + new seedu.address.model.person.Name("Test Person"), + new seedu.address.model.person.Phone("99999999"), + new seedu.address.model.person.Email("test@example.com"), + new seedu.address.model.person.Address("123, Test Street"), + new HashSet<>(), // No tags + new HashSet<>(Arrays.asList(new Wedding(new WeddingName("Jiazhen's Wedding")), + new Wedding(new WeddingName("Wedding 29th August")))) + ); + + model.setPerson(model.getFilteredPersonList().get(INDEX_SECOND_PERSON.getZeroBased()), personWithoutTags); + HashSet tagsToRemove = new HashSet<>(Arrays.asList(new Tag(new TagName("friends")))); + UntagCommand untagCommand = new UntagCommand(INDEX_SECOND_PERSON, tagsToRemove); + String expectedMessage = Messages.MESSAGE_TAG_NOT_FOUND_IN_CONTACT; + + CommandTestUtil.assertCommandFailure(untagCommand, model, expectedMessage); + } +} diff --git a/src/test/java/seedu/address/logic/parser/AssignWeddingCommandParserTest.java b/src/test/java/seedu/address/logic/parser/AssignWeddingCommandParserTest.java new file mode 100644 index 00000000000..b73f119281a --- /dev/null +++ b/src/test/java/seedu/address/logic/parser/AssignWeddingCommandParserTest.java @@ -0,0 +1,59 @@ +package seedu.address.logic.parser; + +import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure; +import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess; + +import java.util.Arrays; +import java.util.HashSet; + +import org.junit.jupiter.api.Test; + +import seedu.address.commons.core.index.Index; +import seedu.address.logic.commands.AssignWeddingCommand; +import seedu.address.model.wedding.Wedding; +import seedu.address.model.wedding.WeddingName; + +public class AssignWeddingCommandParserTest { + private AssignWeddingCommandParser parser = new AssignWeddingCommandParser(); + + @Test + public void parse_validArgs_returnsAssignWeddingCommand() { + Index targetIndex = Index.fromOneBased(1); + + // Expected weddings + Wedding wedding1 = new Wedding(new WeddingName("Jeslyn's Wedding")); + Wedding wedding2 = new Wedding(new WeddingName("Wedding April 17th 2025")); + + AssignWeddingCommand expectedCommand = new AssignWeddingCommand(targetIndex, + new HashSet<>(Arrays.asList(wedding1, wedding2))); + + String userInput = "1 w/Jeslyn's Wedding w/Wedding April 17th 2025"; + + assertParseSuccess(parser, userInput, expectedCommand); + } + + @Test + public void parse_invalidArgs_throwsParseException() { + // Invalid index (non-numeric) + assertParseFailure(parser, "a w/Wedding April 17th 2025", String.format(MESSAGE_INVALID_COMMAND_FORMAT, + AssignWeddingCommand.MESSAGE_USAGE)); + + // Missing weddings (no weddings specified) + assertParseFailure(parser, "1", String.format(MESSAGE_INVALID_COMMAND_FORMAT, + AssignWeddingCommand.MESSAGE_USAGE)); + + // Index missing + assertParseFailure(parser, "w/Wedding April 17th 2025 w/Jeslyn's Wedding", + String.format(MESSAGE_INVALID_COMMAND_FORMAT, + AssignWeddingCommand.MESSAGE_USAGE)); + + // Invalid wedding (contains non-alphanumeric, apostrophe, or space values) + assertParseFailure(parser, "1 w/Wedding April 17th 2025 w/Jeslyn's_Wedding", + WeddingName.MESSAGE_CONSTRAINTS); + + // Invalid wedding (blank) + assertParseFailure(parser, "1 w/ w/Jeslyn's_Wedding", + WeddingName.MESSAGE_CONSTRAINTS); + } +} diff --git a/src/test/java/seedu/address/logic/parser/CreateWeddingCommandParserTest.java b/src/test/java/seedu/address/logic/parser/CreateWeddingCommandParserTest.java new file mode 100644 index 00000000000..6b324e42b0e --- /dev/null +++ b/src/test/java/seedu/address/logic/parser/CreateWeddingCommandParserTest.java @@ -0,0 +1,52 @@ +package seedu.address.logic.parser; + +import static seedu.address.logic.commands.CommandTestUtil.INVALID_WEDDING_DESC; +import static seedu.address.logic.commands.CommandTestUtil.PREAMBLE_WHITESPACE; +import static seedu.address.logic.commands.CommandTestUtil.VALID_WEDDING_AMY; +import static seedu.address.logic.commands.CommandTestUtil.WEDDING_DESC_AMY; +import static seedu.address.logic.parser.CliSyntax.PREFIX_WEDDING; +import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure; +import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess; +import static seedu.address.testutil.TypicalWeddings.AMY_WEDDING; + +import org.junit.jupiter.api.Test; + +import seedu.address.logic.Messages; +import seedu.address.logic.commands.CreateWeddingCommand; +import seedu.address.model.wedding.Wedding; +import seedu.address.model.wedding.WeddingName; + +public class CreateWeddingCommandParserTest { + private CreateWeddingCommandParser parser = new CreateWeddingCommandParser(); + + @Test + public void parse_validWedding_success() { + assertParseSuccess(parser, PREAMBLE_WHITESPACE + WEDDING_DESC_AMY, + new CreateWeddingCommand(AMY_WEDDING)); + } + + @Test + public void parse_invalidWeddingName_failure() { + assertParseFailure(parser, PREAMBLE_WHITESPACE + INVALID_WEDDING_DESC, WeddingName.MESSAGE_CONSTRAINTS); + } + + @Test + public void parse_multipleWeddings_failure() { + assertParseFailure(parser, WEDDING_DESC_AMY + WEDDING_DESC_AMY, + Messages.getErrorMessageForDuplicatePrefixes(PREFIX_WEDDING)); + } + + @Test + public void parse_emptyWeddingName_failure() { + String expectedMessage = String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, + CreateWeddingCommand.MESSAGE_USAGE); + assertParseFailure(parser, VALID_WEDDING_AMY, expectedMessage); + } + + @Test + public void parse_emptyString_failure() { + String expectedMessage = String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, + CreateWeddingCommand.MESSAGE_USAGE); + assertParseFailure(parser, PREAMBLE_WHITESPACE, expectedMessage); + } +} diff --git a/src/test/java/seedu/address/logic/parser/DeleteWeddingCommandParserTest.java b/src/test/java/seedu/address/logic/parser/DeleteWeddingCommandParserTest.java new file mode 100644 index 00000000000..e59b23947a9 --- /dev/null +++ b/src/test/java/seedu/address/logic/parser/DeleteWeddingCommandParserTest.java @@ -0,0 +1,52 @@ +package seedu.address.logic.parser; + +import static seedu.address.logic.commands.CommandTestUtil.INVALID_WEDDING_DESC; +import static seedu.address.logic.commands.CommandTestUtil.PREAMBLE_WHITESPACE; +import static seedu.address.logic.commands.CommandTestUtil.VALID_WEDDING_AMY; +import static seedu.address.logic.commands.CommandTestUtil.WEDDING_DESC_AMY; +import static seedu.address.logic.parser.CliSyntax.PREFIX_WEDDING; +import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure; +import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess; +import static seedu.address.testutil.TypicalWeddings.AMY_WEDDING; + +import org.junit.jupiter.api.Test; + +import seedu.address.logic.Messages; +import seedu.address.logic.commands.DeleteWeddingCommand; +import seedu.address.model.wedding.Wedding; +import seedu.address.model.wedding.WeddingName; + +public class DeleteWeddingCommandParserTest { + private DeleteWeddingCommandParser parser = new DeleteWeddingCommandParser(); + + @Test + public void parse_validWedding_success() { + assertParseSuccess(parser, PREAMBLE_WHITESPACE + WEDDING_DESC_AMY, + new DeleteWeddingCommand(AMY_WEDDING)); + } + + @Test + public void parse_invalidWeddingName_failure() { + assertParseFailure(parser, PREAMBLE_WHITESPACE + INVALID_WEDDING_DESC, WeddingName.MESSAGE_CONSTRAINTS); + } + + @Test + public void parse_multipleWeddings_failure() { + assertParseFailure(parser, WEDDING_DESC_AMY + WEDDING_DESC_AMY, + Messages.getErrorMessageForDuplicatePrefixes(PREFIX_WEDDING)); + } + + @Test + public void parse_emptyWeddingName_failure() { + String expectedMessage = String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, + DeleteWeddingCommand.MESSAGE_USAGE); + assertParseFailure(parser, VALID_WEDDING_AMY, expectedMessage); + } + + @Test + public void parse_emptyString_failure() { + String expectedMessage = String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, + DeleteWeddingCommand.MESSAGE_USAGE); + assertParseFailure(parser, PREAMBLE_WHITESPACE, expectedMessage); + } +} diff --git a/src/test/java/seedu/address/logic/parser/TagCommandParserTest.java b/src/test/java/seedu/address/logic/parser/TagCommandParserTest.java index fd80f223830..90603f68b7d 100644 --- a/src/test/java/seedu/address/logic/parser/TagCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/TagCommandParserTest.java @@ -46,5 +46,13 @@ public void parse_invalidArgs_throwsParseException() { // Index missing assertParseFailure(parser, "t/colleague t/gym", String.format(MESSAGE_INVALID_COMMAND_FORMAT, TagCommand.MESSAGE_USAGE)); + + // Invalid tag (contains non-alphanumeric or space characters) + // assertParseFailure(parser, "1 t/work_colleague t/gym", TagName.MESSAGE_CONSTRAINTS); + + // Invalid tag (blank) + // assertParseFailure(parser, "1 t/", String.format(MESSAGE_INVALID_COMMAND_FORMAT, + // TagCommand.MESSAGE_USAGE)); + } } diff --git a/src/test/java/seedu/address/logic/parser/UnassignWeddingCommandParserTest.java b/src/test/java/seedu/address/logic/parser/UnassignWeddingCommandParserTest.java new file mode 100644 index 00000000000..b42c341d89d --- /dev/null +++ b/src/test/java/seedu/address/logic/parser/UnassignWeddingCommandParserTest.java @@ -0,0 +1,60 @@ +package seedu.address.logic.parser; + +import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure; +import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess; + +import java.util.Arrays; +import java.util.HashSet; + +import org.junit.jupiter.api.Test; + +import seedu.address.commons.core.index.Index; +import seedu.address.logic.commands.UnassignWeddingCommand; +import seedu.address.model.wedding.Wedding; +import seedu.address.model.wedding.WeddingName; + +public class UnassignWeddingCommandParserTest { + + private UnassignWeddingCommandParser parser = new UnassignWeddingCommandParser(); + + @Test + public void parse_validArgs_returnsUnassignWeddingCommand() { + Index targetIndex = Index.fromOneBased(1); + + // Expected weddings + Wedding wedding1 = new Wedding(new WeddingName("Jeslyn's Wedding")); + Wedding wedding2 = new Wedding(new WeddingName("Wedding April 17th 2025")); + + UnassignWeddingCommand expectedCommand = new UnassignWeddingCommand(targetIndex, + new HashSet<>(Arrays.asList(wedding1, wedding2))); + + String userInput = "1 w/Jeslyn's Wedding w/Wedding April 17th 2025"; + + assertParseSuccess(parser, userInput, expectedCommand); + } + + @Test + public void parse_invalidArgs_throwsParseException() { + // Invalid index (non-numeric) + assertParseFailure(parser, "a w/Wedding April 17th 2025", String.format(MESSAGE_INVALID_COMMAND_FORMAT, + UnassignWeddingCommand.MESSAGE_USAGE)); + + // Missing weddings (no weddings specified) + assertParseFailure(parser, "1", String.format(MESSAGE_INVALID_COMMAND_FORMAT, + UnassignWeddingCommand.MESSAGE_USAGE)); + + // Index missing + assertParseFailure(parser, "w/Wedding April 17th 2025 w/Jeslyn's Wedding", + String.format(MESSAGE_INVALID_COMMAND_FORMAT, + UnassignWeddingCommand.MESSAGE_USAGE)); + + // Invalid wedding (contains non-alphanumeric, apostrophe, or space values) + assertParseFailure(parser, "1 w/Wedding April 17th 2025 w/Jeslyn's_Wedding", + WeddingName.MESSAGE_CONSTRAINTS); + + // Invalid wedding (blank) + assertParseFailure(parser, "1 w/ w/Jeslyn's_Wedding", + WeddingName.MESSAGE_CONSTRAINTS); + } +} diff --git a/src/test/java/seedu/address/logic/parser/UntagCommandParserTest.java b/src/test/java/seedu/address/logic/parser/UntagCommandParserTest.java new file mode 100644 index 00000000000..d5d9b99868e --- /dev/null +++ b/src/test/java/seedu/address/logic/parser/UntagCommandParserTest.java @@ -0,0 +1,46 @@ +package seedu.address.logic.parser; + +import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure; +import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess; + +import java.util.Arrays; +import java.util.HashSet; + +import org.junit.jupiter.api.Test; + +import seedu.address.commons.core.index.Index; +import seedu.address.logic.commands.UntagCommand; +import seedu.address.model.tag.Tag; +import seedu.address.model.tag.TagName; + +public class UntagCommandParserTest { + + private UntagCommandParser parser = new UntagCommandParser(); + + @Test + public void parse_validArgs_returnsUntagCommand() { + Index targetIndex = Index.fromOneBased(1); + + // Expected tags + Tag tag1 = new Tag(new TagName("friends")); + Tag tag2 = new Tag(new TagName("owesMoney")); + + UntagCommand expectedCommand = new UntagCommand(targetIndex, new HashSet<>(Arrays.asList(tag1, tag2))); + + String userInput = "1 t/friends t/owesMoney"; + + assertParseSuccess(parser, userInput, expectedCommand); + } + + @Test + public void parse_invalidArgs_throwsParseException() { + // Invalid index (non-numeric) + assertParseFailure(parser, "a t/friends", String.format(MESSAGE_INVALID_COMMAND_FORMAT, + UntagCommand.MESSAGE_USAGE)); + + // Missing tags (no tags specified) + assertParseFailure(parser, "1", String.format(MESSAGE_INVALID_COMMAND_FORMAT, + UntagCommand.MESSAGE_USAGE)); + } +} diff --git a/src/test/java/seedu/address/model/AddressBookTest.java b/src/test/java/seedu/address/model/AddressBookTest.java index 4f00d27ed0b..ad98bf77264 100644 --- a/src/test/java/seedu/address/model/AddressBookTest.java +++ b/src/test/java/seedu/address/model/AddressBookTest.java @@ -8,6 +8,7 @@ import static seedu.address.testutil.Assert.assertThrows; import static seedu.address.testutil.TypicalPersons.ALICE; import static seedu.address.testutil.TypicalPersons.FLORIST; +import static seedu.address.testutil.TypicalWeddings.AMY_WEDDING; import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; import java.util.Arrays; @@ -22,6 +23,7 @@ import seedu.address.model.person.Person; import seedu.address.model.person.exceptions.DuplicatePersonException; import seedu.address.model.tag.Tag; +import seedu.address.model.wedding.Wedding; import seedu.address.testutil.PersonBuilder; public class AddressBookTest { @@ -52,7 +54,8 @@ public void resetData_withDuplicatePersons_throwsDuplicatePersonException() { .build(); List newPersons = Arrays.asList(ALICE, editedAlice); List tags = Arrays.asList(FLORIST); - AddressBookStub newData = new AddressBookStub(newPersons, tags); + List weddings = Arrays.asList(AMY_WEDDING); + AddressBookStub newData = new AddressBookStub(newPersons, tags, weddings); assertThrows(DuplicatePersonException.class, () -> addressBook.resetData(newData)); } @@ -98,10 +101,12 @@ public void toStringMethod() { private static class AddressBookStub implements ReadOnlyAddressBook { private final ObservableList persons = FXCollections.observableArrayList(); private final ObservableList tags = FXCollections.observableArrayList(); + private final ObservableList weddings = FXCollections.observableArrayList(); - AddressBookStub(Collection persons, Collection tags) { + AddressBookStub(Collection persons, Collection tags, Collection weddings) { this.persons.setAll(persons); this.tags.setAll(tags); + this.weddings.setAll(weddings); } @Override @@ -113,6 +118,11 @@ public ObservableList getPersonList() { public ObservableList getTagList() { return tags; } + + @Override + public ObservableList getWeddingList() { + return weddings; + } } } diff --git a/src/test/java/seedu/address/model/person/PersonTest.java b/src/test/java/seedu/address/model/person/PersonTest.java index 31a10d156c9..91f778b01aa 100644 --- a/src/test/java/seedu/address/model/person/PersonTest.java +++ b/src/test/java/seedu/address/model/person/PersonTest.java @@ -93,7 +93,8 @@ public void equals() { @Test public void toStringMethod() { String expected = Person.class.getCanonicalName() + "{name=" + ALICE.getName() + ", phone=" + ALICE.getPhone() - + ", email=" + ALICE.getEmail() + ", address=" + ALICE.getAddress() + ", tags=" + ALICE.getTags() + "}"; + + ", email=" + ALICE.getEmail() + ", address=" + ALICE.getAddress() + ", tags=" + ALICE.getTags() + + ", weddings=" + ALICE.getWeddings() + "}"; assertEquals(expected, ALICE.toString()); } } diff --git a/src/test/java/seedu/address/model/wedding/UniqueWeddingListTest.java b/src/test/java/seedu/address/model/wedding/UniqueWeddingListTest.java new file mode 100644 index 00000000000..0eeab5e8cac --- /dev/null +++ b/src/test/java/seedu/address/model/wedding/UniqueWeddingListTest.java @@ -0,0 +1,189 @@ +package seedu.address.model.wedding; + +import org.junit.jupiter.api.Test; +import seedu.address.model.wedding.exceptions.DuplicateWeddingException; +import seedu.address.model.wedding.exceptions.WeddingNotFoundException; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; +import static seedu.address.testutil.Assert.assertThrows; +import static seedu.address.testutil.TypicalWeddings.AMY_WEDDING; +import static seedu.address.testutil.TypicalWeddings.BOB_WEDDING; + +public class UniqueWeddingListTest { + private final UniqueWeddingList uniqueWeddingList = new UniqueWeddingList(); + + @Test + public void contains_nullWedding_throwsNullPointerException() { + assertThrows(NullPointerException.class, () -> uniqueWeddingList.contains(null)); + } + + @Test + public void contains_WeddingNotInList_returnsFalse() { + assertFalse(uniqueWeddingList.contains(AMY_WEDDING)); + } + + @Test + public void contains_WeddingInList_returnsTrue() { + uniqueWeddingList.add(AMY_WEDDING); + assertTrue(uniqueWeddingList.contains(AMY_WEDDING)); + } + + @Test + public void contains_WeddingWithSameIdentityFieldsInList_returnsTrue() { + uniqueWeddingList.add(AMY_WEDDING); + Wedding sameWedding = new Wedding(new WeddingName("Amy's Wedding")); + assertTrue(uniqueWeddingList.contains(sameWedding)); + } + + @Test + public void add_nullWedding_throwsNullPointerException() { + assertThrows(NullPointerException.class, () -> uniqueWeddingList.add(null)); + } + + @Test + public void add_duplicateWedding_throwsDuplicateWeddingException() { + uniqueWeddingList.add(AMY_WEDDING); + assertThrows(DuplicateWeddingException.class, () -> uniqueWeddingList.add(AMY_WEDDING)); + } + + @Test + public void setWedding_nullTargetWedding_throwsNullPointerException() { + assertThrows(NullPointerException.class, () -> uniqueWeddingList.setWedding(null, AMY_WEDDING)); + } + + @Test + public void setWedding_nullEditedWedding_throwsNullPointerException() { + assertThrows(NullPointerException.class, () -> uniqueWeddingList.setWedding(AMY_WEDDING, null)); + } + + @Test + public void setWedding_targetWeddingNotInList_throwsWeddingNotFoundException() { + assertThrows(WeddingNotFoundException.class, () -> uniqueWeddingList.setWedding(AMY_WEDDING, BOB_WEDDING)); + } + + @Test + public void setWedding_editedWeddingIsSameWedding_success() { + uniqueWeddingList.add(AMY_WEDDING); + uniqueWeddingList.setWedding(AMY_WEDDING, AMY_WEDDING); + UniqueWeddingList expectedUniqueWeddingList = new UniqueWeddingList(); + expectedUniqueWeddingList.add(AMY_WEDDING); + assertEquals(expectedUniqueWeddingList, uniqueWeddingList); + } + + @Test + public void setWedding_editedWeddingHasDifferentIdentity_success() { + uniqueWeddingList.add(AMY_WEDDING); + uniqueWeddingList.setWedding(AMY_WEDDING, BOB_WEDDING); + UniqueWeddingList expectedUniqueWeddingList = new UniqueWeddingList(); + expectedUniqueWeddingList.add(BOB_WEDDING); + assertEquals(expectedUniqueWeddingList, uniqueWeddingList); + } + + @Test + public void setWedding_editedWeddingHasNonUniqueIdentity_throwsDuplicateWeddingException() { + uniqueWeddingList.add(AMY_WEDDING); + uniqueWeddingList.add(BOB_WEDDING); + assertThrows(DuplicateWeddingException.class, () -> uniqueWeddingList.setWedding(AMY_WEDDING, BOB_WEDDING)); + } + + @Test + public void remove_nullWedding_throwsNullPointerException() { + assertThrows(NullPointerException.class, () -> uniqueWeddingList.remove(null)); + } + + @Test + public void remove_WeddingDoesNotExist_throwsWeddingNotFoundException() { + assertThrows(WeddingNotFoundException.class, () -> uniqueWeddingList.remove(AMY_WEDDING)); + } + + @Test + public void remove_existingWedding_removesWedding() { + uniqueWeddingList.add(AMY_WEDDING); + uniqueWeddingList.remove(AMY_WEDDING); + UniqueWeddingList expectedUniqueWeddingList = new UniqueWeddingList(); + assertEquals(expectedUniqueWeddingList, uniqueWeddingList); + } + + @Test + public void setWeddings_nullUniqueWeddingList_throwsNullPointerException() { + assertThrows(NullPointerException.class, () -> uniqueWeddingList.setWeddings((List) null)); + } + + @Test + public void setWeddings_uniqueWeddingList_replacesOwnListWithProvidedUniqueWeddingList() { + uniqueWeddingList.add(AMY_WEDDING); + List weddingList = Collections.singletonList(BOB_WEDDING); + uniqueWeddingList.setWeddings(weddingList); + UniqueWeddingList expectedUniqueWeddingList = new UniqueWeddingList(); + expectedUniqueWeddingList.add(BOB_WEDDING); + assertEquals(expectedUniqueWeddingList, uniqueWeddingList); + } + + @Test + public void setWeddings_listWithDuplicateWeddings_throwsDuplicateWeddingException() { + List listWithDuplicateWeddings = Arrays.asList(AMY_WEDDING, AMY_WEDDING); + assertThrows(DuplicateWeddingException.class, () -> uniqueWeddingList.setWeddings(listWithDuplicateWeddings)); + } + + @Test + public void asUnmodifiableObservableList_modifyList_throwsUnsupportedOperationException() { + assertThrows(UnsupportedOperationException.class, () -> + uniqueWeddingList.asUnmodifiableObservableList().remove(0)); + } + + @Test + public void equals_sameValues_returnsTrue() { + UniqueWeddingList anotherList = new UniqueWeddingList(); + anotherList.add(AMY_WEDDING); + uniqueWeddingList.add(AMY_WEDDING); + assertTrue(uniqueWeddingList.equals(anotherList)); + } + + @Test + public void equals_differentValues_returnsFalse() { + UniqueWeddingList anotherList = new UniqueWeddingList(); + anotherList.add(BOB_WEDDING); + uniqueWeddingList.add(AMY_WEDDING); + assertFalse(uniqueWeddingList.equals(anotherList)); + } + + @Test + public void equals_sameObject_returnsTrue() { + assertTrue(uniqueWeddingList.equals(uniqueWeddingList)); + } + + @Test + public void equals_null_returnsFalse() { + assertFalse(uniqueWeddingList.equals(null)); + } + + @Test + public void equals_differentType_returnsFalse() { + assertFalse(uniqueWeddingList.equals(5)); + } + + @Test + public void hashCode_sameValues_returnsSameHashCode() { + UniqueWeddingList anotherList = new UniqueWeddingList(); + anotherList.add(AMY_WEDDING); + uniqueWeddingList.add(AMY_WEDDING); + assertEquals(uniqueWeddingList.hashCode(), anotherList.hashCode()); + } + + @Test + public void hashCode_differentValues_returnsDifferentHashCode() { + UniqueWeddingList anotherList = new UniqueWeddingList(); + anotherList.add(BOB_WEDDING); + uniqueWeddingList.add(AMY_WEDDING); + assertFalse(uniqueWeddingList.hashCode() == anotherList.hashCode()); + } + + @Test + public void toStringTest() { + assertEquals(uniqueWeddingList.asUnmodifiableObservableList().toString(), uniqueWeddingList.toString()); + } +} diff --git a/src/test/java/seedu/address/model/wedding/WeddingNameTest.java b/src/test/java/seedu/address/model/wedding/WeddingNameTest.java new file mode 100644 index 00000000000..cc265d88c72 --- /dev/null +++ b/src/test/java/seedu/address/model/wedding/WeddingNameTest.java @@ -0,0 +1,89 @@ +package seedu.address.model.wedding; + +import org.junit.jupiter.api.Test; +import seedu.address.model.wedding.WeddingName; + +import static org.junit.jupiter.api.Assertions.*; +import static seedu.address.testutil.Assert.assertThrows; + +public class WeddingNameTest { + + @Test + public void constructor_null_throwsNullPointerException() { + assertThrows(NullPointerException.class, () -> new WeddingName(null)); + } + + @Test + public void constructor_invalidWeddingName_throwsIllegalArgumentException() { + String invalidWeddingName = ""; + assertThrows(IllegalArgumentException.class, () -> new WeddingName(invalidWeddingName)); + } + + @Test + public void isValidName_null_throwsNullPointerException() { + assertThrows(NullPointerException.class, () -> WeddingName.isValidName(null)); + } + + @Test + public void isValidName_validName_returnsTrue() { + // Valid Wedding names + assertTrue(WeddingName.isValidName("friend")); + assertTrue(WeddingName.isValidName("Work")); + assertTrue(WeddingName.isValidName("123")); + assertTrue(WeddingName.isValidName("friend 123")); + assertTrue(WeddingName.isValidName("Family Time")); // Spaces and alphabets + } + + @Test + public void isValidName_invalidName_returnsFalse() { + // Invalid Wedding names + assertFalse(WeddingName.isValidName("")); // Empty string + assertFalse(WeddingName.isValidName(" ")); // Spaces only + assertFalse(WeddingName.isValidName("@home")); // Special character '@' + assertFalse(WeddingName.isValidName("home!")); // Special character '!' + assertFalse(WeddingName.isValidName(" friend")); // Leading space + } + + @Test + public void equals() { + WeddingName WeddingName = new WeddingName("friend"); + + assertTrue(WeddingName.equals(WeddingName)); + + WeddingName WeddingNameCopy = new WeddingName("friend"); + assertTrue(WeddingName.equals(WeddingNameCopy)); + + assertFalse(WeddingName.equals(5)); + + assertFalse(WeddingName.equals(null)); + + WeddingName differentWeddingName = new WeddingName("colleague"); + assertFalse(WeddingName.equals(differentWeddingName)); + } + + @Test + public void hashCode_sameWeddingName_returnsSameHashCode() { + WeddingName WeddingName = new WeddingName("friend"); + WeddingName WeddingNameCopy = new WeddingName("friend"); + assertEquals(WeddingName.hashCode(), WeddingNameCopy.hashCode()); + } + + @Test + public void hashCode_differentWeddingName_returnsDifferentHashCode() { + WeddingName WeddingName = new WeddingName("friend"); + WeddingName differentWeddingName = new WeddingName("colleague"); + assertFalse(WeddingName.hashCode() == differentWeddingName.hashCode()); + } + + @Test + public void toString_validWeddingName_returnsStringRepresentation() { + WeddingName WeddingName = new WeddingName("friend"); + assertEquals("friend", WeddingName.toString()); + } + + @Test + public void matches_validRegex_returnsTrue() { + WeddingName WeddingName = new WeddingName("friend"); + assertTrue(WeddingName.matches("[\\p{Alnum}][\\p{Alnum} ]*")); + } +} diff --git a/src/test/java/seedu/address/model/wedding/WeddingTest.java b/src/test/java/seedu/address/model/wedding/WeddingTest.java new file mode 100644 index 00000000000..835808e4549 --- /dev/null +++ b/src/test/java/seedu/address/model/wedding/WeddingTest.java @@ -0,0 +1,113 @@ +package seedu.address.model.wedding; + +import org.junit.jupiter.api.Test; +import seedu.address.model.tag.Tag; +import seedu.address.model.tag.TagName; + +import static org.junit.jupiter.api.Assertions.*; +import static seedu.address.testutil.Assert.assertThrows; + +public class WeddingTest { + + @Test + public void constructor_null_throwsNullPointerException() { + assertThrows(NullPointerException.class, () -> new Tag(null)); + } + + @Test + public void constructor_invalidTagName_throwsIllegalArgumentException() { + String invalidTagName = ""; + assertThrows(IllegalArgumentException.class, () -> new Tag(new TagName(invalidTagName))); + } + + @Test + public void isValidTagName() { + // null tag name + assertThrows(NullPointerException.class, () -> Tag.isValidTagName(null)); + } + + @Test + public void isValidTagName_validTagName_returnsTrue() { + // Valid tag names + assertTrue(Tag.isValidTagName("friend")); + assertTrue(Tag.isValidTagName("work")); + assertTrue(Tag.isValidTagName("123")); + assertTrue(Tag.isValidTagName("friend 123")); // Alphanumeric with spaces + } + + @Test + public void isValidTagName_invalidTagName_returnsFalse() { + // Invalid tag names + assertFalse(Tag.isValidTagName("")); // Empty string + assertFalse(Tag.isValidTagName(" ")); // Spaces only + assertFalse(Tag.isValidTagName("@home")); // Special character not allowed + assertFalse(Tag.isValidTagName("friend!")); // Special character not allowed + } + + @Test + public void isSameTag_sameTag_returnsTrue() { + Tag tag = new Tag(new TagName("friend")); + assertTrue(tag.isSameTag(tag)); + } + + @Test + public void isSameTag_identicalTagName_returnsTrue() { + Tag tag1 = new Tag(new TagName("friend")); + Tag tag2 = new Tag(new TagName("friend")); + assertTrue(tag1.isSameTag(tag2)); + } + + @Test + public void isSameTag_differentTagName_returnsFalse() { + Tag tag1 = new Tag(new TagName("friend")); + Tag tag2 = new Tag(new TagName("colleague")); + assertFalse(tag1.isSameTag(tag2)); + } + + @Test + public void equals_identicalTagName_returnsTrue() { + Tag tag1 = new Tag(new TagName("friend")); + Tag tag2 = new Tag(new TagName("friend")); + assertTrue(tag1.equals(tag2)); + } + + @Test + public void equals_differentTagName_returnsFalse() { + Tag tag1 = new Tag(new TagName("friend")); + Tag tag2 = new Tag(new TagName("colleague")); + assertFalse(tag1.equals(tag2)); + } + + @Test + public void toString_validTag_returnsExpectedFormat() { + Tag tag = new Tag(new TagName("friend")); + assertTrue(tag.toString().equals("[friend]")); + } + + @Test + public void noPersonsTaggedCheck() { + Tag florist = new Tag(new TagName("Florist")); + assertEquals(0, florist.getNumberOfPersonsTagged()); + } + + @Test + public void incrementTaggedCount() { + Tag florist = new Tag(new TagName("Florist")); + florist.increaseTaggedCount(); + assertEquals(1, florist.getNumberOfPersonsTagged()); + } + + @Test + public void decrementTaggedCount() { + Tag florist = new Tag(new TagName("Florist"));; + florist.increaseTaggedCount(); + florist.decreaseTaggedCount(); + assertEquals(0, florist.getNumberOfPersonsTagged()); + } + + @Test + public void canBeDeleted() { + Tag florist = new Tag(new TagName("Florist")); + assertTrue(florist.canBeDeleted()); + } +} diff --git a/src/test/java/seedu/address/storage/JsonAdaptedPersonTest.java b/src/test/java/seedu/address/storage/JsonAdaptedPersonTest.java index 5c1c6769c05..48f6ee04866 100644 --- a/src/test/java/seedu/address/storage/JsonAdaptedPersonTest.java +++ b/src/test/java/seedu/address/storage/JsonAdaptedPersonTest.java @@ -31,6 +31,9 @@ public class JsonAdaptedPersonTest { private static final List VALID_TAGS = BENSON.getTags().stream() .map(JsonAdaptedTag::new) .collect(Collectors.toList()); + private static final List VALID_WEDDINGS = BENSON.getWeddings().stream() + .map(JsonAdaptedWedding::new) + .collect(Collectors.toList()); private static final String BLANK_ADDRESS = ""; private static final String CLIVE_NAME = CLIVE.getName().toString(); private static final String CLIVE_PHONE = CLIVE.getPhone().toString(); @@ -38,6 +41,9 @@ public class JsonAdaptedPersonTest { private static final List CLIVE_TAGS = CLIVE.getTags().stream() .map(JsonAdaptedTag::new) .collect(Collectors.toList()); + private static final List CLIVE_WEDDINGS = CLIVE.getWeddings().stream() + .map(JsonAdaptedWedding::new) + .collect(Collectors.toList()); @Test public void toModelType_validPersonDetails_returnsPerson() throws Exception { @@ -48,14 +54,16 @@ public void toModelType_validPersonDetails_returnsPerson() throws Exception { @Test public void toModelType_invalidName_throwsIllegalValueException() { JsonAdaptedPerson person = - new JsonAdaptedPerson(INVALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS); + new JsonAdaptedPerson(INVALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS, + VALID_WEDDINGS); String expectedMessage = Name.MESSAGE_CONSTRAINTS; assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); } @Test public void toModelType_nullName_throwsIllegalValueException() { - JsonAdaptedPerson person = new JsonAdaptedPerson(null, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS); + JsonAdaptedPerson person = new JsonAdaptedPerson(null, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, + VALID_TAGS, VALID_WEDDINGS); String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Name.class.getSimpleName()); assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); } @@ -63,14 +71,16 @@ public void toModelType_nullName_throwsIllegalValueException() { @Test public void toModelType_invalidPhone_throwsIllegalValueException() { JsonAdaptedPerson person = - new JsonAdaptedPerson(VALID_NAME, INVALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS); + new JsonAdaptedPerson(VALID_NAME, INVALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS, + VALID_WEDDINGS); String expectedMessage = Phone.MESSAGE_CONSTRAINTS; assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); } @Test public void toModelType_nullPhone_throwsIllegalValueException() { - JsonAdaptedPerson person = new JsonAdaptedPerson(VALID_NAME, null, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS); + JsonAdaptedPerson person = new JsonAdaptedPerson(VALID_NAME, null, VALID_EMAIL, VALID_ADDRESS, + VALID_TAGS, VALID_WEDDINGS); String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Phone.class.getSimpleName()); assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); } @@ -78,14 +88,16 @@ public void toModelType_nullPhone_throwsIllegalValueException() { @Test public void toModelType_invalidEmail_throwsIllegalValueException() { JsonAdaptedPerson person = - new JsonAdaptedPerson(VALID_NAME, VALID_PHONE, INVALID_EMAIL, VALID_ADDRESS, VALID_TAGS); + new JsonAdaptedPerson(VALID_NAME, VALID_PHONE, INVALID_EMAIL, VALID_ADDRESS, VALID_TAGS, + VALID_WEDDINGS); String expectedMessage = Email.MESSAGE_CONSTRAINTS; assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); } @Test public void toModelType_nullEmail_throwsIllegalValueException() { - JsonAdaptedPerson person = new JsonAdaptedPerson(VALID_NAME, VALID_PHONE, null, VALID_ADDRESS, VALID_TAGS); + JsonAdaptedPerson person = new JsonAdaptedPerson(VALID_NAME, VALID_PHONE, null, VALID_ADDRESS, VALID_TAGS, + VALID_WEDDINGS); String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Email.class.getSimpleName()); assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); } @@ -93,13 +105,14 @@ public void toModelType_nullEmail_throwsIllegalValueException() { @Test public void toModelType_blankAddress_returnsPerson() throws IllegalValueException { JsonAdaptedPerson person = - new JsonAdaptedPerson(CLIVE_NAME, CLIVE_PHONE, CLIVE_EMAIL, BLANK_ADDRESS, CLIVE_TAGS); + new JsonAdaptedPerson(CLIVE_NAME, CLIVE_PHONE, CLIVE_EMAIL, BLANK_ADDRESS, CLIVE_TAGS, CLIVE_WEDDINGS); assertEquals(CLIVE, person.toModelType()); } @Test public void toModelType_nullAddress_throwsIllegalValueException() { - JsonAdaptedPerson person = new JsonAdaptedPerson(VALID_NAME, VALID_PHONE, VALID_EMAIL, null, VALID_TAGS); + JsonAdaptedPerson person = new JsonAdaptedPerson(VALID_NAME, VALID_PHONE, VALID_EMAIL, null, VALID_TAGS, + VALID_WEDDINGS); String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Address.class.getSimpleName()); assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); } @@ -109,7 +122,7 @@ public void toModelType_invalidTags_throwsIllegalValueException() { List invalidTags = new ArrayList<>(VALID_TAGS); invalidTags.add(new JsonAdaptedTag(INVALID_TAG)); JsonAdaptedPerson person = - new JsonAdaptedPerson(VALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, invalidTags); + new JsonAdaptedPerson(VALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, invalidTags, VALID_WEDDINGS); assertThrows(IllegalValueException.class, person::toModelType); } diff --git a/src/test/java/seedu/address/storage/JsonAddressBookStorageTest.java b/src/test/java/seedu/address/storage/JsonAddressBookStorageTest.java index 4e5ce9200c8..70d3dc93478 100644 --- a/src/test/java/seedu/address/storage/JsonAddressBookStorageTest.java +++ b/src/test/java/seedu/address/storage/JsonAddressBookStorageTest.java @@ -60,6 +60,16 @@ public void readAddressBook_invalidAndValidPersonAddressBook_throwDataLoadingExc assertThrows(DataLoadingException.class, () -> readAddressBook("invalidAndValidPersonAddressBook.json")); } + @Test + public void readAddressBook_invalidTagAddressBook_throwDataLoadingException() { + assertThrows(DataLoadingException.class, () -> readAddressBook("invalidTagAddressBook.json")); + } + + @Test + public void readAddressBook_invalidWeddingAddressBook_throwDataLoadingException() { + assertThrows(DataLoadingException.class, () -> readAddressBook("invalidWeddingAddressBook.json")); + } + @Test public void readAndSaveAddressBook_allInOrder_success() throws Exception { Path filePath = testFolder.resolve("TempAddressBook.json"); diff --git a/src/test/java/seedu/address/storage/JsonSerializableAddressBookTest.java b/src/test/java/seedu/address/storage/JsonSerializableAddressBookTest.java index 188c9058d20..8b61ff4f90f 100644 --- a/src/test/java/seedu/address/storage/JsonSerializableAddressBookTest.java +++ b/src/test/java/seedu/address/storage/JsonSerializableAddressBookTest.java @@ -18,7 +18,11 @@ public class JsonSerializableAddressBookTest { private static final Path TEST_DATA_FOLDER = Paths.get("src", "test", "data", "JsonSerializableAddressBookTest"); private static final Path TYPICAL_PERSONS_FILE = TEST_DATA_FOLDER.resolve("typicalPersonsAddressBook.json"); private static final Path INVALID_PERSON_FILE = TEST_DATA_FOLDER.resolve("invalidPersonAddressBook.json"); + private static final Path INVALID_TAG_FILE = TEST_DATA_FOLDER.resolve("invalidTagAddressBook.json"); + private static final Path INVALID_WEDDING_FILE = TEST_DATA_FOLDER.resolve("invalidWeddingAddressBook.json"); private static final Path DUPLICATE_PERSON_FILE = TEST_DATA_FOLDER.resolve("duplicatePersonAddressBook.json"); + private static final Path DUPLICATE_TAG_FILE = TEST_DATA_FOLDER.resolve("duplicateTagAddressBook.json"); + private static final Path DUPLICATE_WEDDING_FILE = TEST_DATA_FOLDER.resolve("duplicateWeddingAddressBook.json"); @Test public void toModelType_typicalPersonsFile_success() throws Exception { @@ -29,6 +33,8 @@ public void toModelType_typicalPersonsFile_success() throws Exception { assertEquals(addressBookFromFile, typicalPersonsAddressBook); } + // Tests for invalid entities in Wedlinker storage + @Test public void toModelType_invalidPersonFile_throwsIllegalValueException() throws Exception { JsonSerializableAddressBook dataFromFile = JsonUtil.readJsonFile(INVALID_PERSON_FILE, @@ -36,6 +42,22 @@ public void toModelType_invalidPersonFile_throwsIllegalValueException() throws E assertThrows(IllegalValueException.class, dataFromFile::toModelType); } + @Test + public void toModelType_invalidTagFile_throwsIllegalValueException() throws Exception { + JsonSerializableAddressBook dataFromFile = JsonUtil.readJsonFile(INVALID_TAG_FILE, + JsonSerializableAddressBook.class).get(); + assertThrows(IllegalValueException.class, dataFromFile::toModelType); + } + + @Test + public void toModelType_invalidWeddingFile_throwsIllegalValueException() throws Exception { + JsonSerializableAddressBook dataFromFile = JsonUtil.readJsonFile(INVALID_WEDDING_FILE, + JsonSerializableAddressBook.class).get(); + assertThrows(IllegalValueException.class, dataFromFile::toModelType); + } + + // Tests for duplicate entities in Wedlinker storage + @Test public void toModelType_duplicatePersons_throwsIllegalValueException() throws Exception { JsonSerializableAddressBook dataFromFile = JsonUtil.readJsonFile(DUPLICATE_PERSON_FILE, @@ -44,4 +66,20 @@ public void toModelType_duplicatePersons_throwsIllegalValueException() throws Ex dataFromFile::toModelType); } + @Test + public void toModelType_duplicateTags_throwsIllegalValueException() throws Exception { + JsonSerializableAddressBook dataFromFile = JsonUtil.readJsonFile(DUPLICATE_TAG_FILE, + JsonSerializableAddressBook.class).get(); + assertThrows(IllegalValueException.class, JsonSerializableAddressBook.MESSAGE_DUPLICATE_TAG, + dataFromFile::toModelType); + } + + @Test + public void toModelType_duplicateWeddings_throwsIllegalValueException() throws Exception { + JsonSerializableAddressBook dataFromFile = JsonUtil.readJsonFile(DUPLICATE_WEDDING_FILE, + JsonSerializableAddressBook.class).get(); + assertThrows(IllegalValueException.class, JsonSerializableAddressBook.MESSAGE_DUPLICATE_WEDDING, + dataFromFile::toModelType); + } + } diff --git a/src/test/java/seedu/address/testutil/PersonBuilder.java b/src/test/java/seedu/address/testutil/PersonBuilder.java index c94f8ea6399..3a1a9802f8d 100644 --- a/src/test/java/seedu/address/testutil/PersonBuilder.java +++ b/src/test/java/seedu/address/testutil/PersonBuilder.java @@ -10,6 +10,7 @@ import seedu.address.model.person.Phone; import seedu.address.model.tag.Tag; import seedu.address.model.util.SampleDataUtil; +import seedu.address.model.wedding.Wedding; /** * A utility class to help with building Person objects. @@ -29,6 +30,7 @@ public class PersonBuilder { private Email email; private Address address; private Set tags; + private Set weddings; /** * Creates a {@code PersonBuilder} with the default details. @@ -39,6 +41,7 @@ public PersonBuilder() { email = new Email(DEFAULT_EMAIL); address = new Address(DEFAULT_ADDRESS); tags = new HashSet<>(); + weddings = new HashSet<>(); } /** @@ -50,6 +53,7 @@ public PersonBuilder(Person personToCopy) { email = personToCopy.getEmail(); address = personToCopy.getAddress(); tags = new HashSet<>(personToCopy.getTags()); + weddings = new HashSet<>(personToCopy.getWeddings()); } /** @@ -68,6 +72,14 @@ public PersonBuilder withTags(String ... tags) { return this; } + /** + * Parses the {@code weddings} into a {@code Set} and set it to the {@code Person} that we are building. + */ + public PersonBuilder withWeddings(String ... weddings) { + this.weddings = SampleDataUtil.getWeddingSet(weddings); + return this; + } + /** * Sets the {@code Address} of the {@code Person} that we are building. */ @@ -93,7 +105,7 @@ public PersonBuilder withEmail(String email) { } public Person build() { - return new Person(name, phone, email, address, tags); + return new Person(name, phone, email, address, tags, weddings); } } diff --git a/src/test/java/seedu/address/testutil/TypicalPersons.java b/src/test/java/seedu/address/testutil/TypicalPersons.java index c92220f2b99..a1fa93f8d88 100644 --- a/src/test/java/seedu/address/testutil/TypicalPersons.java +++ b/src/test/java/seedu/address/testutil/TypicalPersons.java @@ -25,6 +25,7 @@ import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND; import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_NEIGHBOR; import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_PHOTOGRAPHER; +import static seedu.address.logic.commands.CommandTestUtil.VALID_WEDDING_AMY; import java.util.ArrayList; import java.util.Arrays; @@ -34,6 +35,8 @@ import seedu.address.model.person.Person; import seedu.address.model.tag.Tag; import seedu.address.model.tag.TagName; +import seedu.address.model.wedding.Wedding; +import seedu.address.model.wedding.WeddingName; /** * A utility class containing a list of {@code Person} objects to be used in tests. @@ -47,7 +50,7 @@ public class TypicalPersons { public static final Person BENSON = new PersonBuilder().withName("Benson Meier") .withAddress("311, Clementi Ave 2, #02-25") .withEmail("johnd@example.com").withPhone("98765432") - .withTags("owesMoney", "friends").build(); + .withTags("owesMoney", "friends").withWeddings("Wedding 2", "Carla's Wedding").build(); public static final Person CARL = new PersonBuilder().withName("Carl Kurz").withPhone("95352563") .withEmail("heinz@example.com").withAddress("wall street").build(); public static final Person DANIEL = new PersonBuilder().withName("Daniel Meier").withPhone("87652533") @@ -83,6 +86,7 @@ public class TypicalPersons { // Manually added Tags public static final Tag FLORIST = new Tag(new TagName(VALID_TAG_FLORIST)); public static final Tag PHOTOGRAPHER = new Tag(new TagName(VALID_TAG_PHOTOGRAPHER)); + public static final Wedding AMY_WEDDING = new Wedding(new WeddingName(VALID_WEDDING_AMY)); public static final String KEYWORD_MATCHING_MEIER = "Meier"; // A keyword that matches MEIER diff --git a/src/test/java/seedu/address/testutil/TypicalTags.java b/src/test/java/seedu/address/testutil/TypicalTags.java new file mode 100644 index 00000000000..6d3f57344dd --- /dev/null +++ b/src/test/java/seedu/address/testutil/TypicalTags.java @@ -0,0 +1,4 @@ +package seedu.address.testutil; + +public class TypicalTags { +} diff --git a/src/test/java/seedu/address/testutil/TypicalWeddings.java b/src/test/java/seedu/address/testutil/TypicalWeddings.java new file mode 100644 index 00000000000..70633e4cbaf --- /dev/null +++ b/src/test/java/seedu/address/testutil/TypicalWeddings.java @@ -0,0 +1,14 @@ +package seedu.address.testutil; + +import seedu.address.model.wedding.Wedding; +import seedu.address.model.wedding.WeddingName; + +/** + * A utility class containing a list of {@code Wedding} objects to be used in tests. + */ +public class TypicalWeddings { + public static final WeddingName VALID_WEDDING_NAME_AMY_WEDDING = new WeddingName("Amy's Wedding"); + public static final WeddingName VALID_WEDDING_NAME_BOB_WEDDING = new WeddingName("Bob's Wedding"); + public static final Wedding AMY_WEDDING = new Wedding(VALID_WEDDING_NAME_AMY_WEDDING); + public static final Wedding BOB_WEDDING = new Wedding(VALID_WEDDING_NAME_BOB_WEDDING); +} \ No newline at end of file From 0bb78132b1988f4bc7fb40c2e51ddbaee2b6b229 Mon Sep 17 00:00:00 2001 From: Ricco Lim Date: Wed, 16 Oct 2024 23:14:49 +0800 Subject: [PATCH 16/33] Change Filter to FindTag, minor refactor --- .../logic/commands/FindAddressCommand.java | 19 +++-------------- .../address/logic/commands/FindCommand.java | 19 +++-------------- .../logic/commands/FindEmailCommand.java | 18 +++------------- .../logic/commands/FindNameCommand.java | 18 +++------------- .../logic/commands/FindPhoneCommand.java | 17 +++------------ ...FilterCommand.java => FindTagCommand.java} | 21 ++++++------------- .../logic/parser/AddressBookParser.java | 4 ++-- .../logic/parser/FilterCommandParser.java | 14 ++++++------- .../AddressContainsKeywordsPredicate.java | 20 +++--------------- .../EmailContainsKeywordsPredicate.java | 20 +++--------------- .../PhoneContainsKeywordsPredicate.java | 19 +++-------------- ...mmandTest.java => FindTagCommandTest.java} | 12 +++++------ .../logic/parser/AddressBookParserTest.java | 4 ++-- ...est.java => FindTagCommandParserTest.java} | 14 ++++++------- 14 files changed, 54 insertions(+), 165 deletions(-) rename src/main/java/seedu/address/logic/commands/{FilterCommand.java => FindTagCommand.java} (64%) rename src/test/java/seedu/address/logic/commands/{FilterCommandTest.java => FindTagCommandTest.java} (88%) rename src/test/java/seedu/address/logic/parser/{FilterCommandParserTest.java => FindTagCommandParserTest.java} (64%) diff --git a/src/main/java/seedu/address/logic/commands/FindAddressCommand.java b/src/main/java/seedu/address/logic/commands/FindAddressCommand.java index 2e72a747c57..69e9a3e8717 100644 --- a/src/main/java/seedu/address/logic/commands/FindAddressCommand.java +++ b/src/main/java/seedu/address/logic/commands/FindAddressCommand.java @@ -2,10 +2,8 @@ import static java.util.Objects.requireNonNull; -import seedu.address.commons.util.ToStringBuilder; import seedu.address.model.Model; import seedu.address.model.person.AddressContainsKeywordsPredicate; - /** * Finds and lists all persons in address book whose address contains any of the argument keywords. * Keyword matching is case-insensitive and allows partial matching. @@ -15,8 +13,6 @@ public class FindAddressCommand extends FindCommand { public static final String MESSAGE_FIND_ADDRESS_PERSON_SUCCESS = "Search for address containing \"%s\" " + " was successful. Showing results:"; - private final AddressContainsKeywordsPredicate predicate; - /** * Command to filter contacts in WedLinker based on phone numbers. * The search matches any parts of the phone numbers. @@ -24,13 +20,13 @@ public class FindAddressCommand extends FindCommand { * @param predicate Keywords used to filter contacts by their phone number. */ public FindAddressCommand(AddressContainsKeywordsPredicate predicate) { - this.predicate = predicate; + super(predicate); } @Override public CommandResult execute(Model model) { requireNonNull(model); - model.updateFilteredPersonList(predicate); + model.updateFilteredPersonList((AddressContainsKeywordsPredicate) predicate); if (!model.getFilteredPersonList().isEmpty()) { return new CommandResult(String.format(MESSAGE_FIND_ADDRESS_PERSON_SUCCESS, predicate.getDisplayString())); @@ -46,19 +42,10 @@ public boolean equals(Object other) { } // instanceof handles nulls - if (!(other instanceof FindAddressCommand)) { + if (!(other instanceof FindAddressCommand otherFindCommand)) { return false; } - FindAddressCommand otherFindCommand = (FindAddressCommand) other; return predicate.equals(otherFindCommand.predicate); } - - @Override - public String toString() { - return new ToStringBuilder(this) - .add("predicate", predicate) - .toString(); - } - } diff --git a/src/main/java/seedu/address/logic/commands/FindCommand.java b/src/main/java/seedu/address/logic/commands/FindCommand.java index 3861363d056..4f5e1877daa 100644 --- a/src/main/java/seedu/address/logic/commands/FindCommand.java +++ b/src/main/java/seedu/address/logic/commands/FindCommand.java @@ -1,7 +1,7 @@ package seedu.address.logic.commands; -import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; import static java.util.Objects.requireNonNull; +import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; import seedu.address.commons.util.ToStringBuilder; import seedu.address.model.Model; @@ -28,27 +28,14 @@ public abstract class FindCommand extends Command { public static final String MESSAGE_FIND_PERSON_UNSUCCESSFUL = "No contacts found."; - private final TraitContainsKeywordsPredicate predicate; + protected final TraitContainsKeywordsPredicate predicate; public FindCommand(TraitContainsKeywordsPredicate predicate) { this.predicate = predicate; } @Override - public CommandResult execute(Model model) { - requireNonNull(model); - if (predicate instanceof NameContainsKeywordsPredicate namePredicate) { - model.updateFilteredPersonList(namePredicate); - } else if (predicate instanceof TagContainsKeywordsPredicate tagPredicate) { - model.updateFilteredPersonListByTag(tagPredicate); - } - - if (!model.getFilteredPersonList().isEmpty()) { - return new CommandResult(String.format(MESSAGE_FIND_PERSON_SUCCESS, predicate.getDisplayString())); - } else { - return new CommandResult(MESSAGE_FIND_PERSON_UNSUCCESSFUL); - } - } + public abstract CommandResult execute(Model model); @Override public boolean equals(Object other) { diff --git a/src/main/java/seedu/address/logic/commands/FindEmailCommand.java b/src/main/java/seedu/address/logic/commands/FindEmailCommand.java index 95c180da618..cecf69638fd 100644 --- a/src/main/java/seedu/address/logic/commands/FindEmailCommand.java +++ b/src/main/java/seedu/address/logic/commands/FindEmailCommand.java @@ -2,10 +2,8 @@ import static java.util.Objects.requireNonNull; -import seedu.address.commons.util.ToStringBuilder; import seedu.address.model.Model; import seedu.address.model.person.EmailContainsKeywordsPredicate; - /** * Finds and lists all persons in address book whose email contains any of the argument keywords. * Keyword matching is case-insensitive and allows partial matching, including numbers and symbols. @@ -14,8 +12,6 @@ public class FindEmailCommand extends FindCommand { public static final String MESSAGE_FIND_EMAIL_PERSON_SUCCESS = "Search for email containing \"%s\" was successful. " + " Showing results:"; - private final EmailContainsKeywordsPredicate predicate; - /** * Command to filter contacts in WedLinker based on names using partial matching. * This command allows users to search for contacts by providing one or more keywords. @@ -24,13 +20,13 @@ public class FindEmailCommand extends FindCommand { * @param predicate Keywords used to filter contacts by name. */ public FindEmailCommand(EmailContainsKeywordsPredicate predicate) { - this.predicate = predicate; + super(predicate); } @Override public CommandResult execute(Model model) { requireNonNull(model); - model.updateFilteredPersonList(predicate); + model.updateFilteredPersonList((EmailContainsKeywordsPredicate) predicate); if (!model.getFilteredPersonList().isEmpty()) { return new CommandResult(String.format(MESSAGE_FIND_EMAIL_PERSON_SUCCESS, predicate.getDisplayString())); @@ -46,18 +42,10 @@ public boolean equals(Object other) { } // instanceof handles nulls - if (!(other instanceof FindEmailCommand)) { + if (!(other instanceof FindEmailCommand otherFindCommand)) { return false; } - FindEmailCommand otherFindCommand = (FindEmailCommand) other; return predicate.equals(otherFindCommand.predicate); } - - @Override - public String toString() { - return new ToStringBuilder(this) - .add("predicate", predicate) - .toString(); - } } diff --git a/src/main/java/seedu/address/logic/commands/FindNameCommand.java b/src/main/java/seedu/address/logic/commands/FindNameCommand.java index 802b1c86733..2e3d9dc6451 100644 --- a/src/main/java/seedu/address/logic/commands/FindNameCommand.java +++ b/src/main/java/seedu/address/logic/commands/FindNameCommand.java @@ -2,10 +2,8 @@ import static java.util.Objects.requireNonNull; -import seedu.address.commons.util.ToStringBuilder; import seedu.address.model.Model; import seedu.address.model.person.NameContainsKeywordsPredicate; - /** * Finds and lists all persons in address book whose name contains any of the argument keywords. * Keyword matching is case-insensitive and allows partial matching. @@ -15,8 +13,6 @@ public class FindNameCommand extends FindCommand { public static final String MESSAGE_FIND_NAME_PERSON_SUCCESS = "Search for name containing \"%s\" was successful. " + " Showing results:"; - private final NameContainsKeywordsPredicate predicate; - /** * Command to filter contacts in WedLinker based on names using partial matching. * This command allows users to search for contacts by providing one or more keywords. @@ -25,13 +21,13 @@ public class FindNameCommand extends FindCommand { * @param predicate Keywords used to filter contacts by name. */ public FindNameCommand(NameContainsKeywordsPredicate predicate) { - this.predicate = predicate; + super(predicate); } @Override public CommandResult execute(Model model) { requireNonNull(model); - model.updateFilteredPersonList(predicate); + model.updateFilteredPersonList((NameContainsKeywordsPredicate) predicate); if (!model.getFilteredPersonList().isEmpty()) { return new CommandResult(String.format(MESSAGE_FIND_NAME_PERSON_SUCCESS, predicate.getDisplayString())); @@ -47,18 +43,10 @@ public boolean equals(Object other) { } // instanceof handles nulls - if (!(other instanceof FindNameCommand)) { + if (!(other instanceof FindNameCommand otherFindCommand)) { return false; } - FindNameCommand otherFindCommand = (FindNameCommand) other; return predicate.equals(otherFindCommand.predicate); } - - @Override - public String toString() { - return new ToStringBuilder(this) - .add("predicate", predicate) - .toString(); - } } diff --git a/src/main/java/seedu/address/logic/commands/FindPhoneCommand.java b/src/main/java/seedu/address/logic/commands/FindPhoneCommand.java index 63e8c739123..5a3964023c8 100644 --- a/src/main/java/seedu/address/logic/commands/FindPhoneCommand.java +++ b/src/main/java/seedu/address/logic/commands/FindPhoneCommand.java @@ -2,10 +2,8 @@ import static java.util.Objects.requireNonNull; -import seedu.address.commons.util.ToStringBuilder; import seedu.address.model.Model; import seedu.address.model.person.PhoneContainsKeywordsPredicate; - /** * Finds and lists all persons in address book whose phone number contains any of the argument keywords. * Keyword matching allows partial matching. @@ -15,7 +13,6 @@ public class FindPhoneCommand extends FindCommand { public static final String MESSAGE_FIND_PHONE_PERSON_SUCCESS = "Search for phone number containing \"%s\" " + " was successful. Showing results:"; - private final PhoneContainsKeywordsPredicate predicate; /** * Command to filter contacts in WedLinker based on phone numbers. @@ -24,13 +21,13 @@ public class FindPhoneCommand extends FindCommand { * @param predicate Keywords used to filter contacts by their phone number. */ public FindPhoneCommand(PhoneContainsKeywordsPredicate predicate) { - this.predicate = predicate; + super(predicate); } @Override public CommandResult execute(Model model) { requireNonNull(model); - model.updateFilteredPersonList(predicate); + model.updateFilteredPersonList((PhoneContainsKeywordsPredicate) predicate); if (!model.getFilteredPersonList().isEmpty()) { return new CommandResult(String.format(MESSAGE_FIND_PHONE_PERSON_SUCCESS, predicate.getDisplayString())); @@ -46,20 +43,12 @@ public boolean equals(Object other) { } // instanceof handles nulls - if (!(other instanceof FindPhoneCommand)) { + if (!(other instanceof FindPhoneCommand otherFindCommand)) { return false; } - FindPhoneCommand otherFindCommand = (FindPhoneCommand) other; return predicate.equals(otherFindCommand.predicate); } - @Override - public String toString() { - return new ToStringBuilder(this) - .add("predicate", predicate) - .toString(); - } - } diff --git a/src/main/java/seedu/address/logic/commands/FilterCommand.java b/src/main/java/seedu/address/logic/commands/FindTagCommand.java similarity index 64% rename from src/main/java/seedu/address/logic/commands/FilterCommand.java rename to src/main/java/seedu/address/logic/commands/FindTagCommand.java index 0c5a5bc7dc8..c5aca0b54d9 100644 --- a/src/main/java/seedu/address/logic/commands/FilterCommand.java +++ b/src/main/java/seedu/address/logic/commands/FindTagCommand.java @@ -2,9 +2,7 @@ import static java.util.Objects.requireNonNull; -import seedu.address.commons.util.ToStringBuilder; import seedu.address.logic.Messages; -import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.model.Model; import seedu.address.model.person.TagContainsKeywordsPredicate; @@ -12,7 +10,7 @@ * Finds and lists all persons in address book whose tag contains any of the argument keywords. * Keyword matching is case-insensitive. */ -public class FilterCommand extends Command { +public class FindTagCommand extends FindCommand { public static final String COMMAND_WORD = "filter"; @@ -21,16 +19,15 @@ public class FilterCommand extends Command { + "Parameters: KEYWORD [MORE_KEYWORDS]...\n" + "Example: " + COMMAND_WORD + " florist"; - private final TagContainsKeywordsPredicate predicate; - public FilterCommand(TagContainsKeywordsPredicate predicate) { - this.predicate = predicate; + public FindTagCommand(TagContainsKeywordsPredicate predicate) { + super(predicate); } @Override - public CommandResult execute(Model model) throws CommandException { + public CommandResult execute(Model model) { requireNonNull(model); - model.updateFilteredPersonListByTag(predicate); + model.updateFilteredPersonListByTag((TagContainsKeywordsPredicate) predicate); return new CommandResult( String.format(Messages.MESSAGE_PERSONS_LISTED_OVERVIEW, model.getFilteredPersonList().size())); } @@ -42,17 +39,11 @@ public boolean equals(Object other) { } // instanceof handles nulls - if (!(other instanceof FilterCommand otherFindCommand)) { + if (!(other instanceof FindTagCommand otherFindCommand)) { return false; } return predicate.equals(otherFindCommand.predicate); } - @Override - public String toString() { - return new ToStringBuilder(this) - .add("predicate", predicate) - .toString(); - } } diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java index a10d8fa5ea3..695cdbefdd4 100644 --- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java +++ b/src/main/java/seedu/address/logic/parser/AddressBookParser.java @@ -16,7 +16,7 @@ import seedu.address.logic.commands.DeleteTagCommand; import seedu.address.logic.commands.EditCommand; import seedu.address.logic.commands.ExitCommand; -import seedu.address.logic.commands.FilterCommand; +import seedu.address.logic.commands.FindTagCommand; import seedu.address.logic.commands.FindCommand; import seedu.address.logic.commands.HelpCommand; import seedu.address.logic.commands.ListCommand; @@ -62,7 +62,7 @@ public Command parseCommand(String userInput) throws ParseException { case DeleteCommand.COMMAND_WORD -> new DeleteCommandParser().parse(arguments); case ClearCommand.COMMAND_WORD -> new ClearCommand(); case FindCommand.COMMAND_WORD -> new FindCommandParser().parse(arguments); - case FilterCommand.COMMAND_WORD -> new FilterCommandParser().parse(arguments); + case FindTagCommand.COMMAND_WORD -> new FilterCommandParser().parse(arguments); case ListCommand.COMMAND_WORD -> new ListCommand(); case ExitCommand.COMMAND_WORD -> new ExitCommand(); case HelpCommand.COMMAND_WORD -> new HelpCommand(); diff --git a/src/main/java/seedu/address/logic/parser/FilterCommandParser.java b/src/main/java/seedu/address/logic/parser/FilterCommandParser.java index 661e224fb81..faae7ed2181 100644 --- a/src/main/java/seedu/address/logic/parser/FilterCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/FilterCommandParser.java @@ -4,7 +4,7 @@ import java.util.Arrays; -import seedu.address.logic.commands.FilterCommand; +import seedu.address.logic.commands.FindTagCommand; import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.person.TagContainsKeywordsPredicate; @@ -12,23 +12,23 @@ /** * Parses input arguments and creates a new FindCommand object */ -public class FilterCommandParser implements Parser { +public class FilterCommandParser implements Parser { /** - * Parses the given {@code String} of arguments in the context of the FilterCommand - * and returns a FilterCommand object for execution. + * Parses the given {@code String} of arguments in the context of the FindTagCommand + * and returns a FindTagCommand object for execution. * @throws ParseException if the user input does not conform the expected format */ - public FilterCommand parse(String args) throws ParseException { + public FindTagCommand parse(String args) throws ParseException { String trimmedArgs = args.trim(); if (trimmedArgs.isEmpty()) { throw new ParseException( - String.format(MESSAGE_INVALID_COMMAND_FORMAT, FilterCommand.MESSAGE_USAGE)); + String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindTagCommand.MESSAGE_USAGE)); } String[] nameKeywords = trimmedArgs.split("\\s+"); - return new FilterCommand(new TagContainsKeywordsPredicate(Arrays.asList(nameKeywords))); + return new FindTagCommand(new TagContainsKeywordsPredicate(Arrays.asList(nameKeywords))); } } diff --git a/src/main/java/seedu/address/model/person/AddressContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/person/AddressContainsKeywordsPredicate.java index 567131e221c..158770e9738 100644 --- a/src/main/java/seedu/address/model/person/AddressContainsKeywordsPredicate.java +++ b/src/main/java/seedu/address/model/person/AddressContainsKeywordsPredicate.java @@ -1,19 +1,15 @@ package seedu.address.model.person; import java.util.List; -import java.util.function.Predicate; import seedu.address.commons.util.StringUtil; -import seedu.address.commons.util.ToStringBuilder; /** * Tests that a {@code Person}'s {@code Address} matches any of the keywords given. */ -public class AddressContainsKeywordsPredicate implements Predicate { - private final List keywords; - +public class AddressContainsKeywordsPredicate extends TraitContainsKeywordsPredicate { public AddressContainsKeywordsPredicate(List keywords) { - this.keywords = keywords; + super(keywords); } @Override @@ -29,20 +25,10 @@ public boolean equals(Object other) { } // instanceof handles nulls - if (!(other instanceof AddressContainsKeywordsPredicate)) { + if (!(other instanceof AddressContainsKeywordsPredicate otherNameContainsKeywordsPredicate)) { return false; } - AddressContainsKeywordsPredicate otherNameContainsKeywordsPredicate = (AddressContainsKeywordsPredicate) other; return keywords.equals(otherNameContainsKeywordsPredicate.keywords); } - - @Override - public String toString() { - return new ToStringBuilder(this).add("keywords", keywords).toString(); - } - - public String getDisplayString() { - return String.join(", ", keywords); - } } diff --git a/src/main/java/seedu/address/model/person/EmailContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/person/EmailContainsKeywordsPredicate.java index da51cf71780..feaa73d75b6 100644 --- a/src/main/java/seedu/address/model/person/EmailContainsKeywordsPredicate.java +++ b/src/main/java/seedu/address/model/person/EmailContainsKeywordsPredicate.java @@ -1,19 +1,15 @@ package seedu.address.model.person; import java.util.List; -import java.util.function.Predicate; import seedu.address.commons.util.StringUtil; -import seedu.address.commons.util.ToStringBuilder; /** * Tests that a {@code Person}'s {@code Email} matches any of the keywords given. */ -public class EmailContainsKeywordsPredicate implements Predicate { - private final List keywords; - +public class EmailContainsKeywordsPredicate extends TraitContainsKeywordsPredicate { public EmailContainsKeywordsPredicate(List keywords) { - this.keywords = keywords; + super(keywords); } @Override @@ -29,20 +25,10 @@ public boolean equals(Object other) { } // instanceof handles nulls - if (!(other instanceof EmailContainsKeywordsPredicate)) { + if (!(other instanceof EmailContainsKeywordsPredicate otherNameContainsKeywordsPredicate)) { return false; } - EmailContainsKeywordsPredicate otherNameContainsKeywordsPredicate = (EmailContainsKeywordsPredicate) other; return keywords.equals(otherNameContainsKeywordsPredicate.keywords); } - - @Override - public String toString() { - return new ToStringBuilder(this).add("keywords", keywords).toString(); - } - - public String getDisplayString() { - return String.join(", ", keywords); - } } diff --git a/src/main/java/seedu/address/model/person/PhoneContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/person/PhoneContainsKeywordsPredicate.java index 3a4505419e4..8c622c5d226 100644 --- a/src/main/java/seedu/address/model/person/PhoneContainsKeywordsPredicate.java +++ b/src/main/java/seedu/address/model/person/PhoneContainsKeywordsPredicate.java @@ -1,19 +1,16 @@ package seedu.address.model.person; import java.util.List; -import java.util.function.Predicate; import seedu.address.commons.util.StringUtil; -import seedu.address.commons.util.ToStringBuilder; /** * Tests that a {@code Person}'s {@code Phone} matches any of the keywords given. */ -public class PhoneContainsKeywordsPredicate implements Predicate { - private final List keywords; +public class PhoneContainsKeywordsPredicate extends TraitContainsKeywordsPredicate { public PhoneContainsKeywordsPredicate(List keywords) { - this.keywords = keywords; + super(keywords); } @Override @@ -29,20 +26,10 @@ public boolean equals(Object other) { } // instanceof handles nulls - if (!(other instanceof PhoneContainsKeywordsPredicate)) { + if (!(other instanceof PhoneContainsKeywordsPredicate otherNameContainsKeywordsPredicate)) { return false; } - PhoneContainsKeywordsPredicate otherNameContainsKeywordsPredicate = (PhoneContainsKeywordsPredicate) other; return keywords.equals(otherNameContainsKeywordsPredicate.keywords); } - - @Override - public String toString() { - return new ToStringBuilder(this).add("keywords", keywords).toString(); - } - - public String getDisplayString() { - return String.join(", ", keywords); - } } diff --git a/src/test/java/seedu/address/logic/commands/FilterCommandTest.java b/src/test/java/seedu/address/logic/commands/FindTagCommandTest.java similarity index 88% rename from src/test/java/seedu/address/logic/commands/FilterCommandTest.java rename to src/test/java/seedu/address/logic/commands/FindTagCommandTest.java index 6c1b319e837..42853f413c8 100644 --- a/src/test/java/seedu/address/logic/commands/FilterCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/FindTagCommandTest.java @@ -22,7 +22,7 @@ -public class FilterCommandTest { +public class FindTagCommandTest { private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); private Model expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs()); @@ -33,14 +33,14 @@ public void equals() { TagContainsKeywordsPredicate secondPredicate = new TagContainsKeywordsPredicate(Collections.singletonList("second")); - FilterCommand filterFirstCommand = new FilterCommand(firstPredicate); - FilterCommand filterSecondCommand = new FilterCommand(secondPredicate); + FindTagCommand filterFirstCommand = new FindTagCommand(firstPredicate); + FindTagCommand filterSecondCommand = new FindTagCommand(secondPredicate); // same object -> returns true assertTrue(filterFirstCommand.equals(filterFirstCommand)); // same values -> returns true - FilterCommand filterFirstCommandCopy = new FilterCommand(firstPredicate); + FindTagCommand filterFirstCommandCopy = new FindTagCommand(firstPredicate); assertTrue(filterFirstCommand.equals(filterFirstCommandCopy)); // different types -> returns false @@ -57,7 +57,7 @@ public void equals() { public void execute_zeroKeywords_noPersonFound() { String expectedMessage = String.format(MESSAGE_PERSONS_LISTED_OVERVIEW, 0); TagContainsKeywordsPredicate predicate = preparePredicate(" "); - FilterCommand command = new FilterCommand(predicate); + FindTagCommand command = new FindTagCommand(predicate); expectedModel.updateFilteredPersonListByTag(predicate); assertCommandSuccess(command, model, expectedMessage, expectedModel); assertEquals(Collections.emptyList(), model.getFilteredPersonList()); @@ -67,7 +67,7 @@ public void execute_zeroKeywords_noPersonFound() { public void execute_multipleKeywords_multiplePersonsFound() { String expectedMessage = String.format(MESSAGE_PERSONS_LISTED_OVERVIEW, 3); TagContainsKeywordsPredicate predicate = preparePredicate("friends"); - FilterCommand command = new FilterCommand(predicate); + FindTagCommand command = new FindTagCommand(predicate); expectedModel.updateFilteredPersonListByTag(predicate); assertCommandSuccess(command, model, expectedMessage, expectedModel); assertEquals(Arrays.asList(ALICE, BENSON, DANIEL), model.getFilteredPersonList()); diff --git a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java b/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java index ffe05aca784..9572958d034 100644 --- a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java +++ b/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java @@ -20,7 +20,7 @@ import seedu.address.logic.commands.EditCommand; import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; import seedu.address.logic.commands.ExitCommand; -import seedu.address.logic.commands.FilterCommand; +import seedu.address.logic.commands.FindTagCommand; import seedu.address.logic.commands.FindCommand; import seedu.address.logic.commands.FindNameCommand; import seedu.address.logic.commands.HelpCommand; @@ -84,7 +84,7 @@ public void parseCommand_find() throws Exception { @Test public void parseCommand_filter() throws Exception { - assertTrue(parser.parseCommand(FilterCommand.COMMAND_WORD + " " + "foo") instanceof FilterCommand); + assertTrue(parser.parseCommand(FindTagCommand.COMMAND_WORD + " " + "foo") instanceof FindTagCommand); } @Test diff --git a/src/test/java/seedu/address/logic/parser/FilterCommandParserTest.java b/src/test/java/seedu/address/logic/parser/FindTagCommandParserTest.java similarity index 64% rename from src/test/java/seedu/address/logic/parser/FilterCommandParserTest.java rename to src/test/java/seedu/address/logic/parser/FindTagCommandParserTest.java index 4cfe0f0fa35..af581a8f48b 100644 --- a/src/test/java/seedu/address/logic/parser/FilterCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/FindTagCommandParserTest.java @@ -8,27 +8,27 @@ import org.junit.jupiter.api.Test; -import seedu.address.logic.commands.FilterCommand; +import seedu.address.logic.commands.FindTagCommand; import seedu.address.model.person.TagContainsKeywordsPredicate; -public class FilterCommandParserTest { +public class FindTagCommandParserTest { private FilterCommandParser parser = new FilterCommandParser(); @Test public void parse_emptyArg_throwsParseException() { - assertParseFailure(parser, " ", String.format(MESSAGE_INVALID_COMMAND_FORMAT, FilterCommand.MESSAGE_USAGE)); + assertParseFailure(parser, " ", String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindTagCommand.MESSAGE_USAGE)); } @Test public void parse_validArgs_returnsFilterCommand() { // no leading and trailing whitespaces - FilterCommand expectedFilterCommand = - new FilterCommand(new TagContainsKeywordsPredicate(List.of("friends"))); - assertParseSuccess(parser, "friends", expectedFilterCommand); + FindTagCommand expectedFindTagCommand = + new FindTagCommand(new TagContainsKeywordsPredicate(List.of("friends"))); + assertParseSuccess(parser, "friends", expectedFindTagCommand); // multiple whitespaces between keywords - assertParseSuccess(parser, "friends", expectedFilterCommand); + assertParseSuccess(parser, "friends", expectedFindTagCommand); } } From 28c13a60e43b82ccd0eeea4cb5076083bdc35ed6 Mon Sep 17 00:00:00 2001 From: Ricco Lim Date: Wed, 16 Oct 2024 23:22:21 +0800 Subject: [PATCH 17/33] Repackage FindCommand and remove Filter --- .../{ => findcommand}/FindAddressCommand.java | 3 ++- .../{ => findcommand}/FindCommand.java | 6 ++--- .../{ => findcommand}/FindEmailCommand.java | 3 ++- .../{ => findcommand}/FindNameCommand.java | 3 ++- .../{ => findcommand}/FindPhoneCommand.java | 3 ++- .../{ => findcommand}/FindTagCommand.java | 3 ++- .../logic/parser/FilterCommandParser.java | 2 +- .../logic/parser/FindCommandParser.java | 24 ++++++++++++++----- .../commands/FindAddressCommandTest.java | 6 +++-- .../logic/commands/FindEmailCommandTest.java | 6 +++-- .../logic/commands/FindNameCommandTest.java | 6 +++-- .../logic/commands/FindPhoneCommandTest.java | 6 +++-- .../logic/commands/FindTagCommandTest.java | 1 + .../logic/parser/AddressBookParserTest.java | 6 ++--- .../logic/parser/FindCommandParserTest.java | 10 ++++---- .../parser/FindTagCommandParserTest.java | 2 +- 16 files changed, 58 insertions(+), 32 deletions(-) rename src/main/java/seedu/address/logic/commands/{ => findcommand}/FindAddressCommand.java (94%) rename src/main/java/seedu/address/logic/commands/{ => findcommand}/FindCommand.java (92%) rename src/main/java/seedu/address/logic/commands/{ => findcommand}/FindEmailCommand.java (94%) rename src/main/java/seedu/address/logic/commands/{ => findcommand}/FindNameCommand.java (94%) rename src/main/java/seedu/address/logic/commands/{ => findcommand}/FindPhoneCommand.java (94%) rename src/main/java/seedu/address/logic/commands/{ => findcommand}/FindTagCommand.java (93%) diff --git a/src/main/java/seedu/address/logic/commands/FindAddressCommand.java b/src/main/java/seedu/address/logic/commands/findcommand/FindAddressCommand.java similarity index 94% rename from src/main/java/seedu/address/logic/commands/FindAddressCommand.java rename to src/main/java/seedu/address/logic/commands/findcommand/FindAddressCommand.java index 69e9a3e8717..d6ff3cde038 100644 --- a/src/main/java/seedu/address/logic/commands/FindAddressCommand.java +++ b/src/main/java/seedu/address/logic/commands/findcommand/FindAddressCommand.java @@ -1,7 +1,8 @@ -package seedu.address.logic.commands; +package seedu.address.logic.commands.findcommand; import static java.util.Objects.requireNonNull; +import seedu.address.logic.commands.CommandResult; import seedu.address.model.Model; import seedu.address.model.person.AddressContainsKeywordsPredicate; /** diff --git a/src/main/java/seedu/address/logic/commands/FindCommand.java b/src/main/java/seedu/address/logic/commands/findcommand/FindCommand.java similarity index 92% rename from src/main/java/seedu/address/logic/commands/FindCommand.java rename to src/main/java/seedu/address/logic/commands/findcommand/FindCommand.java index 4f5e1877daa..4f05c9533ac 100644 --- a/src/main/java/seedu/address/logic/commands/FindCommand.java +++ b/src/main/java/seedu/address/logic/commands/findcommand/FindCommand.java @@ -1,12 +1,12 @@ -package seedu.address.logic.commands; +package seedu.address.logic.commands.findcommand; import static java.util.Objects.requireNonNull; import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; import seedu.address.commons.util.ToStringBuilder; +import seedu.address.logic.commands.Command; +import seedu.address.logic.commands.CommandResult; import seedu.address.model.Model; -import seedu.address.model.person.NameContainsKeywordsPredicate; -import seedu.address.model.person.TagContainsKeywordsPredicate; import seedu.address.model.person.TraitContainsKeywordsPredicate; /** diff --git a/src/main/java/seedu/address/logic/commands/FindEmailCommand.java b/src/main/java/seedu/address/logic/commands/findcommand/FindEmailCommand.java similarity index 94% rename from src/main/java/seedu/address/logic/commands/FindEmailCommand.java rename to src/main/java/seedu/address/logic/commands/findcommand/FindEmailCommand.java index cecf69638fd..95588daebd1 100644 --- a/src/main/java/seedu/address/logic/commands/FindEmailCommand.java +++ b/src/main/java/seedu/address/logic/commands/findcommand/FindEmailCommand.java @@ -1,7 +1,8 @@ -package seedu.address.logic.commands; +package seedu.address.logic.commands.findcommand; import static java.util.Objects.requireNonNull; +import seedu.address.logic.commands.CommandResult; import seedu.address.model.Model; import seedu.address.model.person.EmailContainsKeywordsPredicate; /** diff --git a/src/main/java/seedu/address/logic/commands/FindNameCommand.java b/src/main/java/seedu/address/logic/commands/findcommand/FindNameCommand.java similarity index 94% rename from src/main/java/seedu/address/logic/commands/FindNameCommand.java rename to src/main/java/seedu/address/logic/commands/findcommand/FindNameCommand.java index 2e3d9dc6451..fa1c9b45ba4 100644 --- a/src/main/java/seedu/address/logic/commands/FindNameCommand.java +++ b/src/main/java/seedu/address/logic/commands/findcommand/FindNameCommand.java @@ -1,7 +1,8 @@ -package seedu.address.logic.commands; +package seedu.address.logic.commands.findcommand; import static java.util.Objects.requireNonNull; +import seedu.address.logic.commands.CommandResult; import seedu.address.model.Model; import seedu.address.model.person.NameContainsKeywordsPredicate; /** diff --git a/src/main/java/seedu/address/logic/commands/FindPhoneCommand.java b/src/main/java/seedu/address/logic/commands/findcommand/FindPhoneCommand.java similarity index 94% rename from src/main/java/seedu/address/logic/commands/FindPhoneCommand.java rename to src/main/java/seedu/address/logic/commands/findcommand/FindPhoneCommand.java index 5a3964023c8..3aff172c8e5 100644 --- a/src/main/java/seedu/address/logic/commands/FindPhoneCommand.java +++ b/src/main/java/seedu/address/logic/commands/findcommand/FindPhoneCommand.java @@ -1,7 +1,8 @@ -package seedu.address.logic.commands; +package seedu.address.logic.commands.findcommand; import static java.util.Objects.requireNonNull; +import seedu.address.logic.commands.CommandResult; import seedu.address.model.Model; import seedu.address.model.person.PhoneContainsKeywordsPredicate; /** diff --git a/src/main/java/seedu/address/logic/commands/FindTagCommand.java b/src/main/java/seedu/address/logic/commands/findcommand/FindTagCommand.java similarity index 93% rename from src/main/java/seedu/address/logic/commands/FindTagCommand.java rename to src/main/java/seedu/address/logic/commands/findcommand/FindTagCommand.java index c5aca0b54d9..3b4382c5001 100644 --- a/src/main/java/seedu/address/logic/commands/FindTagCommand.java +++ b/src/main/java/seedu/address/logic/commands/findcommand/FindTagCommand.java @@ -1,8 +1,9 @@ -package seedu.address.logic.commands; +package seedu.address.logic.commands.findcommand; import static java.util.Objects.requireNonNull; import seedu.address.logic.Messages; +import seedu.address.logic.commands.CommandResult; import seedu.address.model.Model; import seedu.address.model.person.TagContainsKeywordsPredicate; diff --git a/src/main/java/seedu/address/logic/parser/FilterCommandParser.java b/src/main/java/seedu/address/logic/parser/FilterCommandParser.java index faae7ed2181..e150ff1e85d 100644 --- a/src/main/java/seedu/address/logic/parser/FilterCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/FilterCommandParser.java @@ -4,7 +4,7 @@ import java.util.Arrays; -import seedu.address.logic.commands.FindTagCommand; +import seedu.address.logic.commands.findcommand.FindTagCommand; import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.person.TagContainsKeywordsPredicate; diff --git a/src/main/java/seedu/address/logic/parser/FindCommandParser.java b/src/main/java/seedu/address/logic/parser/FindCommandParser.java index 8374a05b2ac..be472eaba93 100644 --- a/src/main/java/seedu/address/logic/parser/FindCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/FindCommandParser.java @@ -11,16 +11,18 @@ import java.util.Arrays; import java.util.List; -import seedu.address.logic.commands.FindAddressCommand; -import seedu.address.logic.commands.FindCommand; -import seedu.address.logic.commands.FindEmailCommand; -import seedu.address.logic.commands.FindNameCommand; -import seedu.address.logic.commands.FindPhoneCommand; +import seedu.address.logic.commands.findcommand.FindAddressCommand; +import seedu.address.logic.commands.findcommand.FindCommand; +import seedu.address.logic.commands.findcommand.FindEmailCommand; +import seedu.address.logic.commands.findcommand.FindNameCommand; +import seedu.address.logic.commands.findcommand.FindPhoneCommand; +import seedu.address.logic.commands.findcommand.FindTagCommand; import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.person.AddressContainsKeywordsPredicate; import seedu.address.model.person.EmailContainsKeywordsPredicate; import seedu.address.model.person.NameContainsKeywordsPredicate; import seedu.address.model.person.PhoneContainsKeywordsPredicate; +import seedu.address.model.person.TagContainsKeywordsPredicate; /** @@ -38,7 +40,7 @@ public FindCommand parse(String args) throws ParseException { ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TAG); - argMultimap.verifyNoDuplicatePrefixesFor(PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS); + argMultimap.verifyNoDuplicatePrefixesFor(PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TAG); String trimmedArgs = args.trim(); if (trimmedArgs.isEmpty()) { @@ -51,6 +53,7 @@ public FindCommand parse(String args) throws ParseException { boolean hasPhonePrefix = argMultimap.getValue(PREFIX_PHONE).isPresent(); boolean hasEmailPrefix = argMultimap.getValue(PREFIX_EMAIL).isPresent(); boolean hasAddressPrefix = argMultimap.getValue(PREFIX_ADDRESS).isPresent(); + boolean hasTagPrefix = argMultimap.getValue(PREFIX_TAG).isPresent(); if (hasNamePrefix) { String nameInput = argMultimap.getValue(PREFIX_NAME).get().trim(); // Get the actual name input @@ -88,6 +91,15 @@ public FindCommand parse(String args) throws ParseException { return new FindAddressCommand(new AddressContainsKeywordsPredicate(addressKeywords)); } + if (hasTagPrefix) { + String tagInput = argMultimap.getValue(PREFIX_TAG).get().trim(); // Get the actual tag input + if (tagInput.isEmpty()) { + throw new ParseException("Tag cannot be empty!"); + } + List tagKeywords = Arrays.asList(tagInput.split("\\s+")); + return new FindTagCommand(new TagContainsKeywordsPredicate(tagKeywords)); + } + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE)); } diff --git a/src/test/java/seedu/address/logic/commands/FindAddressCommandTest.java b/src/test/java/seedu/address/logic/commands/FindAddressCommandTest.java index 68eb6ec05a2..4d92c636ee2 100644 --- a/src/test/java/seedu/address/logic/commands/FindAddressCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/FindAddressCommandTest.java @@ -4,8 +4,8 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; -import static seedu.address.logic.commands.FindAddressCommand.MESSAGE_FIND_ADDRESS_PERSON_SUCCESS; -import static seedu.address.logic.commands.FindCommand.MESSAGE_FIND_PERSON_UNSUCCESSFUL; +import static seedu.address.logic.commands.findcommand.FindAddressCommand.MESSAGE_FIND_ADDRESS_PERSON_SUCCESS; +import static seedu.address.logic.commands.findcommand.FindCommand.MESSAGE_FIND_PERSON_UNSUCCESSFUL; import static seedu.address.testutil.TypicalPersons.ALICE; import static seedu.address.testutil.TypicalPersons.BENSON; import static seedu.address.testutil.TypicalPersons.CARL; @@ -17,6 +17,8 @@ import org.junit.jupiter.api.Test; +import seedu.address.logic.commands.findcommand.FindAddressCommand; +import seedu.address.logic.commands.findcommand.FindCommand; import seedu.address.model.Model; import seedu.address.model.ModelManager; import seedu.address.model.UserPrefs; diff --git a/src/test/java/seedu/address/logic/commands/FindEmailCommandTest.java b/src/test/java/seedu/address/logic/commands/FindEmailCommandTest.java index 76cf393c6c4..e23814a1b4e 100644 --- a/src/test/java/seedu/address/logic/commands/FindEmailCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/FindEmailCommandTest.java @@ -4,8 +4,8 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; -import static seedu.address.logic.commands.FindCommand.MESSAGE_FIND_PERSON_UNSUCCESSFUL; -import static seedu.address.logic.commands.FindEmailCommand.MESSAGE_FIND_EMAIL_PERSON_SUCCESS; +import static seedu.address.logic.commands.findcommand.FindCommand.MESSAGE_FIND_PERSON_UNSUCCESSFUL; +import static seedu.address.logic.commands.findcommand.FindEmailCommand.MESSAGE_FIND_EMAIL_PERSON_SUCCESS; import static seedu.address.testutil.TypicalPersons.ALICE; import static seedu.address.testutil.TypicalPersons.BENSON; import static seedu.address.testutil.TypicalPersons.CARL; @@ -18,6 +18,8 @@ import org.junit.jupiter.api.Test; +import seedu.address.logic.commands.findcommand.FindCommand; +import seedu.address.logic.commands.findcommand.FindEmailCommand; import seedu.address.model.Model; import seedu.address.model.ModelManager; import seedu.address.model.UserPrefs; diff --git a/src/test/java/seedu/address/logic/commands/FindNameCommandTest.java b/src/test/java/seedu/address/logic/commands/FindNameCommandTest.java index 50a40b1dfc0..2a385c1a56f 100644 --- a/src/test/java/seedu/address/logic/commands/FindNameCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/FindNameCommandTest.java @@ -4,8 +4,8 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; -import static seedu.address.logic.commands.FindCommand.MESSAGE_FIND_PERSON_UNSUCCESSFUL; -import static seedu.address.logic.commands.FindNameCommand.MESSAGE_FIND_NAME_PERSON_SUCCESS; +import static seedu.address.logic.commands.findcommand.FindCommand.MESSAGE_FIND_PERSON_UNSUCCESSFUL; +import static seedu.address.logic.commands.findcommand.FindNameCommand.MESSAGE_FIND_NAME_PERSON_SUCCESS; import static seedu.address.testutil.TypicalPersons.ALICE; import static seedu.address.testutil.TypicalPersons.BENSON; import static seedu.address.testutil.TypicalPersons.CARL; @@ -20,6 +20,8 @@ import org.junit.jupiter.api.Test; +import seedu.address.logic.commands.findcommand.FindCommand; +import seedu.address.logic.commands.findcommand.FindNameCommand; import seedu.address.model.Model; import seedu.address.model.ModelManager; import seedu.address.model.UserPrefs; diff --git a/src/test/java/seedu/address/logic/commands/FindPhoneCommandTest.java b/src/test/java/seedu/address/logic/commands/FindPhoneCommandTest.java index 32e8b42f6b7..c6eaf42da55 100644 --- a/src/test/java/seedu/address/logic/commands/FindPhoneCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/FindPhoneCommandTest.java @@ -4,8 +4,8 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; -import static seedu.address.logic.commands.FindCommand.MESSAGE_FIND_PERSON_UNSUCCESSFUL; -import static seedu.address.logic.commands.FindPhoneCommand.MESSAGE_FIND_PHONE_PERSON_SUCCESS; +import static seedu.address.logic.commands.findcommand.FindCommand.MESSAGE_FIND_PERSON_UNSUCCESSFUL; +import static seedu.address.logic.commands.findcommand.FindPhoneCommand.MESSAGE_FIND_PHONE_PERSON_SUCCESS; import static seedu.address.testutil.TypicalPersons.ALICE; import static seedu.address.testutil.TypicalPersons.BENSON; import static seedu.address.testutil.TypicalPersons.CARL; @@ -20,6 +20,8 @@ import org.junit.jupiter.api.Test; +import seedu.address.logic.commands.findcommand.FindCommand; +import seedu.address.logic.commands.findcommand.FindPhoneCommand; import seedu.address.model.Model; import seedu.address.model.ModelManager; import seedu.address.model.UserPrefs; diff --git a/src/test/java/seedu/address/logic/commands/FindTagCommandTest.java b/src/test/java/seedu/address/logic/commands/FindTagCommandTest.java index 42853f413c8..bc79137ace3 100644 --- a/src/test/java/seedu/address/logic/commands/FindTagCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/FindTagCommandTest.java @@ -15,6 +15,7 @@ import org.junit.jupiter.api.Test; +import seedu.address.logic.commands.findcommand.FindTagCommand; import seedu.address.model.Model; import seedu.address.model.ModelManager; import seedu.address.model.UserPrefs; diff --git a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java b/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java index 9572958d034..05a97884639 100644 --- a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java +++ b/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java @@ -20,9 +20,9 @@ import seedu.address.logic.commands.EditCommand; import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; import seedu.address.logic.commands.ExitCommand; -import seedu.address.logic.commands.FindTagCommand; -import seedu.address.logic.commands.FindCommand; -import seedu.address.logic.commands.FindNameCommand; +import seedu.address.logic.commands.findcommand.FindTagCommand; +import seedu.address.logic.commands.findcommand.FindCommand; +import seedu.address.logic.commands.findcommand.FindNameCommand; import seedu.address.logic.commands.HelpCommand; import seedu.address.logic.commands.ListCommand; import seedu.address.logic.commands.TagCommand; diff --git a/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java b/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java index 8505d01f197..7c0c3fc9025 100644 --- a/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java @@ -10,11 +10,11 @@ import org.junit.jupiter.api.Test; -import seedu.address.logic.commands.FindAddressCommand; -import seedu.address.logic.commands.FindCommand; -import seedu.address.logic.commands.FindEmailCommand; -import seedu.address.logic.commands.FindNameCommand; -import seedu.address.logic.commands.FindPhoneCommand; +import seedu.address.logic.commands.findcommand.FindAddressCommand; +import seedu.address.logic.commands.findcommand.FindCommand; +import seedu.address.logic.commands.findcommand.FindEmailCommand; +import seedu.address.logic.commands.findcommand.FindNameCommand; +import seedu.address.logic.commands.findcommand.FindPhoneCommand; import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.person.AddressContainsKeywordsPredicate; import seedu.address.model.person.EmailContainsKeywordsPredicate; diff --git a/src/test/java/seedu/address/logic/parser/FindTagCommandParserTest.java b/src/test/java/seedu/address/logic/parser/FindTagCommandParserTest.java index af581a8f48b..88f8b20cc28 100644 --- a/src/test/java/seedu/address/logic/parser/FindTagCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/FindTagCommandParserTest.java @@ -8,7 +8,7 @@ import org.junit.jupiter.api.Test; -import seedu.address.logic.commands.FindTagCommand; +import seedu.address.logic.commands.findcommand.FindTagCommand; import seedu.address.model.person.TagContainsKeywordsPredicate; public class FindTagCommandParserTest { From f0c8a9cd58674ca4c17e3e103127f8d0336e414f Mon Sep 17 00:00:00 2001 From: Han Bin Date: Wed, 16 Oct 2024 23:31:48 +0800 Subject: [PATCH 18/33] Fix check style issues Fix check style issues in Wedding classes. Fix check style issues in Wedding test classes. --- .../logic/parser/AddressBookParser.java | 2 + .../java/seedu/address/model/AddressBook.java | 32 ++--- .../CreateWeddingCommandParserTest.java | 1 - .../DeleteWeddingCommandParserTest.java | 1 - .../seedu/address/model/AddressBookTest.java | 2 +- .../model/wedding/UniqueWeddingListTest.java | 25 ++-- .../model/wedding/WeddingNameTest.java | 47 +++---- .../address/model/wedding/WeddingTest.java | 124 +++++++++--------- .../seedu/address/testutil/TypicalTags.java | 4 - .../address/testutil/TypicalWeddings.java | 8 +- 10 files changed, 127 insertions(+), 119 deletions(-) delete mode 100644 src/test/java/seedu/address/testutil/TypicalTags.java diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java index 6b0dd162fa9..31fcf307138 100644 --- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java +++ b/src/main/java/seedu/address/logic/parser/AddressBookParser.java @@ -76,6 +76,8 @@ public Command parseCommand(String userInput) throws ParseException { case DeleteWeddingCommand.COMMAND_WORD -> new DeleteWeddingCommandParser().parse(arguments); case TagCommand.COMMAND_WORD -> new TagCommandParser().parse(arguments); case UntagCommand.COMMAND_WORD -> new UntagCommandParser().parse(arguments); + case AssignWeddingCommand.COMMAND_WORD -> new AssignWeddingCommandParser().parse(arguments); + case UnassignWeddingCommand.COMMAND_WORD -> new UnassignWeddingCommandParser().parse(arguments); default -> { logger.finer("This user input caused a ParseException: " + userInput); throw new ParseException(MESSAGE_UNKNOWN_COMMAND); diff --git a/src/main/java/seedu/address/model/AddressBook.java b/src/main/java/seedu/address/model/AddressBook.java index 07156971140..43e8ccd23bb 100644 --- a/src/main/java/seedu/address/model/AddressBook.java +++ b/src/main/java/seedu/address/model/AddressBook.java @@ -51,14 +51,6 @@ public AddressBook(ReadOnlyAddressBook toBeCopied) { //// list overwrite operations - /** - * Replaces the contents of the person list with {@code persons}. - * {@code persons} must not contain duplicate persons. - */ - public void setPersons(List persons) { - this.persons.setPersons(persons); - } - /** * Resets the existing data of this {@code AddressBook} with {@code newData}. */ @@ -78,14 +70,6 @@ public void setPersons(List persons) { this.persons.setPersons(persons); } - /** - * Replaces the contents of the tag list with {@code tags}. - * {@code tags} must not contain duplicate tags. - */ - public void setTags(List tags) { - this.tags.setTags(tags); - } - //// person-level operations /** @@ -142,6 +126,14 @@ public boolean hasTag(Tag tag) { return tags.contains(tag); } + /** + * Replaces the contents of the tag list with {@code tags}. + * {@code tags} must not contain duplicate tags. + */ + public void setTags(List tags) { + this.tags.setTags(tags); + } + /** * Adds a wedding to the Wedlinker * The wedding must not already exist in the Wedlinker @@ -162,6 +154,14 @@ public void setWedding(Wedding target, Wedding editedWedding) { weddings.setWedding(target, editedWedding); } + /** + * Replaces the contents of the wedding list with {@code weddings}. + * {@code weddings} must not contain duplicate weddings. + */ + public void setWeddings(List weddings) { + this.weddings.setWeddings(weddings); + } + /** * Returns true if a wedding with the same name as the {@code wedding} exists in the Wedlinker. */ diff --git a/src/test/java/seedu/address/logic/parser/CreateWeddingCommandParserTest.java b/src/test/java/seedu/address/logic/parser/CreateWeddingCommandParserTest.java index 6b324e42b0e..e5bfc2c7aac 100644 --- a/src/test/java/seedu/address/logic/parser/CreateWeddingCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/CreateWeddingCommandParserTest.java @@ -13,7 +13,6 @@ import seedu.address.logic.Messages; import seedu.address.logic.commands.CreateWeddingCommand; -import seedu.address.model.wedding.Wedding; import seedu.address.model.wedding.WeddingName; public class CreateWeddingCommandParserTest { diff --git a/src/test/java/seedu/address/logic/parser/DeleteWeddingCommandParserTest.java b/src/test/java/seedu/address/logic/parser/DeleteWeddingCommandParserTest.java index e59b23947a9..f7d1ee91f19 100644 --- a/src/test/java/seedu/address/logic/parser/DeleteWeddingCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/DeleteWeddingCommandParserTest.java @@ -13,7 +13,6 @@ import seedu.address.logic.Messages; import seedu.address.logic.commands.DeleteWeddingCommand; -import seedu.address.model.wedding.Wedding; import seedu.address.model.wedding.WeddingName; public class DeleteWeddingCommandParserTest { diff --git a/src/test/java/seedu/address/model/AddressBookTest.java b/src/test/java/seedu/address/model/AddressBookTest.java index ad98bf77264..fcb07b79759 100644 --- a/src/test/java/seedu/address/model/AddressBookTest.java +++ b/src/test/java/seedu/address/model/AddressBookTest.java @@ -8,8 +8,8 @@ import static seedu.address.testutil.Assert.assertThrows; import static seedu.address.testutil.TypicalPersons.ALICE; import static seedu.address.testutil.TypicalPersons.FLORIST; -import static seedu.address.testutil.TypicalWeddings.AMY_WEDDING; import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; +import static seedu.address.testutil.TypicalWeddings.AMY_WEDDING; import java.util.Arrays; import java.util.Collection; diff --git a/src/test/java/seedu/address/model/wedding/UniqueWeddingListTest.java b/src/test/java/seedu/address/model/wedding/UniqueWeddingListTest.java index 0eeab5e8cac..5e58ec8e4e8 100644 --- a/src/test/java/seedu/address/model/wedding/UniqueWeddingListTest.java +++ b/src/test/java/seedu/address/model/wedding/UniqueWeddingListTest.java @@ -1,17 +1,20 @@ package seedu.address.model.wedding; -import org.junit.jupiter.api.Test; -import seedu.address.model.wedding.exceptions.DuplicateWeddingException; -import seedu.address.model.wedding.exceptions.WeddingNotFoundException; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static seedu.address.testutil.Assert.assertThrows; +import static seedu.address.testutil.TypicalWeddings.AMY_WEDDING; +import static seedu.address.testutil.TypicalWeddings.BOB_WEDDING; import java.util.Arrays; import java.util.Collections; import java.util.List; -import static org.junit.jupiter.api.Assertions.*; -import static seedu.address.testutil.Assert.assertThrows; -import static seedu.address.testutil.TypicalWeddings.AMY_WEDDING; -import static seedu.address.testutil.TypicalWeddings.BOB_WEDDING; +import org.junit.jupiter.api.Test; + +import seedu.address.model.wedding.exceptions.DuplicateWeddingException; +import seedu.address.model.wedding.exceptions.WeddingNotFoundException; public class UniqueWeddingListTest { private final UniqueWeddingList uniqueWeddingList = new UniqueWeddingList(); @@ -22,18 +25,18 @@ public void contains_nullWedding_throwsNullPointerException() { } @Test - public void contains_WeddingNotInList_returnsFalse() { + public void contains_weddingNotInList_returnsFalse() { assertFalse(uniqueWeddingList.contains(AMY_WEDDING)); } @Test - public void contains_WeddingInList_returnsTrue() { + public void contains_weddingInList_returnsTrue() { uniqueWeddingList.add(AMY_WEDDING); assertTrue(uniqueWeddingList.contains(AMY_WEDDING)); } @Test - public void contains_WeddingWithSameIdentityFieldsInList_returnsTrue() { + public void contains_weddingWithSameIdentityFieldsInList_returnsTrue() { uniqueWeddingList.add(AMY_WEDDING); Wedding sameWedding = new Wedding(new WeddingName("Amy's Wedding")); assertTrue(uniqueWeddingList.contains(sameWedding)); @@ -96,7 +99,7 @@ public void remove_nullWedding_throwsNullPointerException() { } @Test - public void remove_WeddingDoesNotExist_throwsWeddingNotFoundException() { + public void remove_weddingDoesNotExist_throwsWeddingNotFoundException() { assertThrows(WeddingNotFoundException.class, () -> uniqueWeddingList.remove(AMY_WEDDING)); } diff --git a/src/test/java/seedu/address/model/wedding/WeddingNameTest.java b/src/test/java/seedu/address/model/wedding/WeddingNameTest.java index cc265d88c72..f6995f021d0 100644 --- a/src/test/java/seedu/address/model/wedding/WeddingNameTest.java +++ b/src/test/java/seedu/address/model/wedding/WeddingNameTest.java @@ -1,10 +1,13 @@ package seedu.address.model.wedding; -import org.junit.jupiter.api.Test; -import seedu.address.model.wedding.WeddingName; - -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import static seedu.address.testutil.Assert.assertThrows; +import static seedu.address.testutil.TypicalWeddings.VALID_WEDDING_STRING_AMY_WEDDING; +import static seedu.address.testutil.TypicalWeddings.VALID_WEDDING_STRING_BOB_WEDDING; + +import org.junit.jupiter.api.Test; public class WeddingNameTest { @@ -46,44 +49,44 @@ public void isValidName_invalidName_returnsFalse() { @Test public void equals() { - WeddingName WeddingName = new WeddingName("friend"); + WeddingName weddingName = new WeddingName(VALID_WEDDING_STRING_AMY_WEDDING); - assertTrue(WeddingName.equals(WeddingName)); + assertTrue(weddingName.equals(weddingName)); - WeddingName WeddingNameCopy = new WeddingName("friend"); - assertTrue(WeddingName.equals(WeddingNameCopy)); + WeddingName weddingNameCopy = new WeddingName(VALID_WEDDING_STRING_AMY_WEDDING); + assertTrue(weddingName.equals(weddingNameCopy)); - assertFalse(WeddingName.equals(5)); + assertFalse(weddingName.equals(5)); - assertFalse(WeddingName.equals(null)); + assertFalse(weddingName.equals(null)); - WeddingName differentWeddingName = new WeddingName("colleague"); - assertFalse(WeddingName.equals(differentWeddingName)); + WeddingName differentWeddingName = new WeddingName(VALID_WEDDING_STRING_BOB_WEDDING); + assertFalse(weddingName.equals(differentWeddingName)); } @Test public void hashCode_sameWeddingName_returnsSameHashCode() { - WeddingName WeddingName = new WeddingName("friend"); - WeddingName WeddingNameCopy = new WeddingName("friend"); - assertEquals(WeddingName.hashCode(), WeddingNameCopy.hashCode()); + WeddingName weddingName = new WeddingName(VALID_WEDDING_STRING_AMY_WEDDING); + WeddingName weddingNameCopy = new WeddingName(VALID_WEDDING_STRING_AMY_WEDDING); + assertEquals(weddingName.hashCode(), weddingNameCopy.hashCode()); } @Test public void hashCode_differentWeddingName_returnsDifferentHashCode() { - WeddingName WeddingName = new WeddingName("friend"); - WeddingName differentWeddingName = new WeddingName("colleague"); - assertFalse(WeddingName.hashCode() == differentWeddingName.hashCode()); + WeddingName weddingName = new WeddingName(VALID_WEDDING_STRING_AMY_WEDDING); + WeddingName differentWeddingName = new WeddingName(VALID_WEDDING_STRING_BOB_WEDDING); + assertFalse(weddingName.hashCode() == differentWeddingName.hashCode()); } @Test public void toString_validWeddingName_returnsStringRepresentation() { - WeddingName WeddingName = new WeddingName("friend"); - assertEquals("friend", WeddingName.toString()); + WeddingName amyWeddingName = new WeddingName(VALID_WEDDING_STRING_AMY_WEDDING); + assertEquals("Amy's Wedding", amyWeddingName.toString()); } @Test public void matches_validRegex_returnsTrue() { - WeddingName WeddingName = new WeddingName("friend"); - assertTrue(WeddingName.matches("[\\p{Alnum}][\\p{Alnum} ]*")); + WeddingName amyWeddingName = new WeddingName(VALID_WEDDING_STRING_AMY_WEDDING); + assertTrue(amyWeddingName.matches("[\\p{Alnum}'][\\p{Alnum} ']*")); } } diff --git a/src/test/java/seedu/address/model/wedding/WeddingTest.java b/src/test/java/seedu/address/model/wedding/WeddingTest.java index 835808e4549..aba2c20399e 100644 --- a/src/test/java/seedu/address/model/wedding/WeddingTest.java +++ b/src/test/java/seedu/address/model/wedding/WeddingTest.java @@ -1,113 +1,117 @@ package seedu.address.model.wedding; -import org.junit.jupiter.api.Test; -import seedu.address.model.tag.Tag; -import seedu.address.model.tag.TagName; - -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import static seedu.address.testutil.Assert.assertThrows; +import static seedu.address.testutil.TypicalWeddings.AMY_WEDDING; +import static seedu.address.testutil.TypicalWeddings.BOB_WEDDING; +import static seedu.address.testutil.TypicalWeddings.VALID_WEDDING_NAME_AMY_WEDDING; +import static seedu.address.testutil.TypicalWeddings.VALID_WEDDING_NAME_BOB_WEDDING; + +import org.junit.jupiter.api.Test; public class WeddingTest { @Test public void constructor_null_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> new Tag(null)); + assertThrows(NullPointerException.class, () -> new Wedding(null)); } @Test - public void constructor_invalidTagName_throwsIllegalArgumentException() { - String invalidTagName = ""; - assertThrows(IllegalArgumentException.class, () -> new Tag(new TagName(invalidTagName))); + public void constructor_invalidWeddingName_throwsIllegalArgumentException() { + String invalidWeddingName = ""; + assertThrows(IllegalArgumentException.class, () -> new Wedding(new WeddingName(invalidWeddingName))); } @Test - public void isValidTagName() { - // null tag name - assertThrows(NullPointerException.class, () -> Tag.isValidTagName(null)); + public void isValidWeddingName() { + // null Wedding name + assertThrows(NullPointerException.class, () -> Wedding.isValidWeddingName(null)); } @Test - public void isValidTagName_validTagName_returnsTrue() { - // Valid tag names - assertTrue(Tag.isValidTagName("friend")); - assertTrue(Tag.isValidTagName("work")); - assertTrue(Tag.isValidTagName("123")); - assertTrue(Tag.isValidTagName("friend 123")); // Alphanumeric with spaces + public void isValidWeddingName_validWeddingName_returnsTrue() { + // Valid Wedding names + assertTrue(Wedding.isValidWeddingName("friend")); + assertTrue(Wedding.isValidWeddingName("work")); + assertTrue(Wedding.isValidWeddingName("123")); + assertTrue(Wedding.isValidWeddingName("friend 123")); // Alphanumeric with spaces } @Test - public void isValidTagName_invalidTagName_returnsFalse() { - // Invalid tag names - assertFalse(Tag.isValidTagName("")); // Empty string - assertFalse(Tag.isValidTagName(" ")); // Spaces only - assertFalse(Tag.isValidTagName("@home")); // Special character not allowed - assertFalse(Tag.isValidTagName("friend!")); // Special character not allowed + public void isValidWeddingName_invalidWeddingName_returnsFalse() { + // Invalid Wedding names + assertFalse(Wedding.isValidWeddingName("")); // Empty string + assertFalse(Wedding.isValidWeddingName(" ")); // Spaces only + assertFalse(Wedding.isValidWeddingName("@home")); // Special character not allowed + assertFalse(Wedding.isValidWeddingName("friend!")); // Special character not allowed } @Test - public void isSameTag_sameTag_returnsTrue() { - Tag tag = new Tag(new TagName("friend")); - assertTrue(tag.isSameTag(tag)); + public void isSameWedding_sameWedding_returnsTrue() { + Wedding amyWedding = AMY_WEDDING; + assertTrue(amyWedding.isSameWedding(amyWedding)); } @Test - public void isSameTag_identicalTagName_returnsTrue() { - Tag tag1 = new Tag(new TagName("friend")); - Tag tag2 = new Tag(new TagName("friend")); - assertTrue(tag1.isSameTag(tag2)); + public void isSameWedding_identicalWeddingName_returnsTrue() { + Wedding amyWedding1 = AMY_WEDDING; + Wedding amyWedding2 = AMY_WEDDING; + assertTrue(amyWedding1.isSameWedding(amyWedding2)); } @Test - public void isSameTag_differentTagName_returnsFalse() { - Tag tag1 = new Tag(new TagName("friend")); - Tag tag2 = new Tag(new TagName("colleague")); - assertFalse(tag1.isSameTag(tag2)); + public void isSameWedding_differentWeddingName_returnsFalse() { + Wedding amyWedding = AMY_WEDDING; + Wedding bobWeding = BOB_WEDDING; + assertFalse(amyWedding.isSameWedding(bobWeding)); } @Test - public void equals_identicalTagName_returnsTrue() { - Tag tag1 = new Tag(new TagName("friend")); - Tag tag2 = new Tag(new TagName("friend")); - assertTrue(tag1.equals(tag2)); + public void equals_identicalWeddingName_returnsTrue() { + Wedding wedding1 = new Wedding(VALID_WEDDING_NAME_AMY_WEDDING); + Wedding wedding2 = new Wedding(VALID_WEDDING_NAME_AMY_WEDDING); + assertTrue(wedding1.equals(wedding2)); } @Test - public void equals_differentTagName_returnsFalse() { - Tag tag1 = new Tag(new TagName("friend")); - Tag tag2 = new Tag(new TagName("colleague")); - assertFalse(tag1.equals(tag2)); + public void equals_differentWeddingName_returnsFalse() { + Wedding wedding1 = new Wedding(VALID_WEDDING_NAME_AMY_WEDDING); + Wedding wedding2 = new Wedding(VALID_WEDDING_NAME_BOB_WEDDING); + assertFalse(wedding1.equals(wedding2)); } @Test - public void toString_validTag_returnsExpectedFormat() { - Tag tag = new Tag(new TagName("friend")); - assertTrue(tag.toString().equals("[friend]")); + public void toString_validWedding_returnsExpectedFormat() { + Wedding amyWedding = AMY_WEDDING; + assertTrue(amyWedding.toString().equals("[Amy's Wedding]")); } @Test - public void noPersonsTaggedCheck() { - Tag florist = new Tag(new TagName("Florist")); - assertEquals(0, florist.getNumberOfPersonsTagged()); + public void noPersonsWeddinggedCheck() { + Wedding amyWedding = new Wedding(VALID_WEDDING_NAME_AMY_WEDDING); + assertEquals(0, amyWedding.getNumPersonsForWedding()); } @Test - public void incrementTaggedCount() { - Tag florist = new Tag(new TagName("Florist")); - florist.increaseTaggedCount(); - assertEquals(1, florist.getNumberOfPersonsTagged()); + public void increasePeopleCount() { + Wedding amyWedding = new Wedding(VALID_WEDDING_NAME_AMY_WEDDING); + amyWedding.increasePeopleCount(); + assertEquals(1, amyWedding.getNumPersonsForWedding()); } @Test - public void decrementTaggedCount() { - Tag florist = new Tag(new TagName("Florist"));; - florist.increaseTaggedCount(); - florist.decreaseTaggedCount(); - assertEquals(0, florist.getNumberOfPersonsTagged()); + public void decrementPeopleCount() { + Wedding amyWedding = new Wedding(VALID_WEDDING_NAME_AMY_WEDDING); + amyWedding.increasePeopleCount(); + amyWedding.decreasePeopleCount(); + assertEquals(0, amyWedding.getNumPersonsForWedding()); } @Test public void canBeDeleted() { - Tag florist = new Tag(new TagName("Florist")); - assertTrue(florist.canBeDeleted()); + Wedding amyWedding = new Wedding(VALID_WEDDING_NAME_AMY_WEDDING); + assertTrue(amyWedding.canBeDeleted()); } } diff --git a/src/test/java/seedu/address/testutil/TypicalTags.java b/src/test/java/seedu/address/testutil/TypicalTags.java deleted file mode 100644 index 6d3f57344dd..00000000000 --- a/src/test/java/seedu/address/testutil/TypicalTags.java +++ /dev/null @@ -1,4 +0,0 @@ -package seedu.address.testutil; - -public class TypicalTags { -} diff --git a/src/test/java/seedu/address/testutil/TypicalWeddings.java b/src/test/java/seedu/address/testutil/TypicalWeddings.java index 70633e4cbaf..31b0c71b95b 100644 --- a/src/test/java/seedu/address/testutil/TypicalWeddings.java +++ b/src/test/java/seedu/address/testutil/TypicalWeddings.java @@ -7,8 +7,10 @@ * A utility class containing a list of {@code Wedding} objects to be used in tests. */ public class TypicalWeddings { - public static final WeddingName VALID_WEDDING_NAME_AMY_WEDDING = new WeddingName("Amy's Wedding"); - public static final WeddingName VALID_WEDDING_NAME_BOB_WEDDING = new WeddingName("Bob's Wedding"); + public static final String VALID_WEDDING_STRING_AMY_WEDDING = "Amy's Wedding"; + public static final String VALID_WEDDING_STRING_BOB_WEDDING = "Bob's Wedding"; + public static final WeddingName VALID_WEDDING_NAME_AMY_WEDDING = new WeddingName(VALID_WEDDING_STRING_AMY_WEDDING); + public static final WeddingName VALID_WEDDING_NAME_BOB_WEDDING = new WeddingName(VALID_WEDDING_STRING_BOB_WEDDING); public static final Wedding AMY_WEDDING = new Wedding(VALID_WEDDING_NAME_AMY_WEDDING); public static final Wedding BOB_WEDDING = new Wedding(VALID_WEDDING_NAME_BOB_WEDDING); -} \ No newline at end of file +} From 129ecd35c7181b4622ae15c0a7426934ddac4b8e Mon Sep 17 00:00:00 2001 From: Ricco Lim Date: Thu, 17 Oct 2024 00:57:30 +0800 Subject: [PATCH 19/33] Amend tests for FindTag --- .../findcommand/FindAddressCommand.java | 2 +- .../commands/findcommand/FindCommand.java | 3 +- .../findcommand/FindEmailCommand.java | 2 +- .../commands/findcommand/FindNameCommand.java | 2 +- .../findcommand/FindPhoneCommand.java | 2 +- .../commands/findcommand/FindTagCommand.java | 20 +++++------ .../logic/parser/AddressBookParser.java | 4 +-- .../logic/parser/FilterCommandParser.java | 34 ------------------- .../logic/parser/FindCommandParser.java | 10 +++--- .../AddressContainsKeywordsPredicate.java | 3 +- .../EmailContainsKeywordsPredicate.java | 3 +- .../NameContainsKeywordsPredicate.java | 3 +- .../PhoneContainsKeywordsPredicate.java | 3 +- .../TagContainsKeywordsPredicate.java | 4 +-- .../TraitContainsKeywordsPredicate.java | 2 +- .../logic/commands/CommandTestUtil.java | 2 +- .../commands/FindAddressCommandTest.java | 2 +- .../logic/commands/FindEmailCommandTest.java | 2 +- .../logic/commands/FindNameCommandTest.java | 2 +- .../logic/commands/FindPhoneCommandTest.java | 2 +- .../logic/commands/FindTagCommandTest.java | 9 ++--- .../logic/parser/AddressBookParserTest.java | 12 ++----- .../logic/parser/FindCommandParserTest.java | 8 ++--- .../parser/FindTagCommandParserTest.java | 34 ------------------- .../seedu/address/model/ModelManagerTest.java | 2 +- .../AddressContainsKeywordsPredicateTest.java | 1 + .../EmailContainsKeywordsPredicateTest.java | 1 + .../NameContainsKeywordsPredicateTest.java | 1 + .../PhoneContainsKeywordsPredicateTest.java | 1 + 29 files changed, 53 insertions(+), 123 deletions(-) delete mode 100644 src/main/java/seedu/address/logic/parser/FilterCommandParser.java rename src/main/java/seedu/address/model/person/{ => keywordspredicate}/AddressContainsKeywordsPredicate.java (90%) rename src/main/java/seedu/address/model/person/{ => keywordspredicate}/EmailContainsKeywordsPredicate.java (90%) rename src/main/java/seedu/address/model/person/{ => keywordspredicate}/NameContainsKeywordsPredicate.java (90%) rename src/main/java/seedu/address/model/person/{ => keywordspredicate}/PhoneContainsKeywordsPredicate.java (90%) rename src/main/java/seedu/address/model/person/{ => keywordspredicate}/TagContainsKeywordsPredicate.java (83%) rename src/main/java/seedu/address/model/person/{ => keywordspredicate}/TraitContainsKeywordsPredicate.java (95%) delete mode 100644 src/test/java/seedu/address/logic/parser/FindTagCommandParserTest.java diff --git a/src/main/java/seedu/address/logic/commands/findcommand/FindAddressCommand.java b/src/main/java/seedu/address/logic/commands/findcommand/FindAddressCommand.java index d6ff3cde038..20b29b02c00 100644 --- a/src/main/java/seedu/address/logic/commands/findcommand/FindAddressCommand.java +++ b/src/main/java/seedu/address/logic/commands/findcommand/FindAddressCommand.java @@ -4,7 +4,7 @@ import seedu.address.logic.commands.CommandResult; import seedu.address.model.Model; -import seedu.address.model.person.AddressContainsKeywordsPredicate; +import seedu.address.model.person.keywordspredicate.AddressContainsKeywordsPredicate; /** * Finds and lists all persons in address book whose address contains any of the argument keywords. * Keyword matching is case-insensitive and allows partial matching. diff --git a/src/main/java/seedu/address/logic/commands/findcommand/FindCommand.java b/src/main/java/seedu/address/logic/commands/findcommand/FindCommand.java index 4f05c9533ac..ce9a23bd9a5 100644 --- a/src/main/java/seedu/address/logic/commands/findcommand/FindCommand.java +++ b/src/main/java/seedu/address/logic/commands/findcommand/FindCommand.java @@ -1,13 +1,12 @@ package seedu.address.logic.commands.findcommand; -import static java.util.Objects.requireNonNull; import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; import seedu.address.commons.util.ToStringBuilder; import seedu.address.logic.commands.Command; import seedu.address.logic.commands.CommandResult; import seedu.address.model.Model; -import seedu.address.model.person.TraitContainsKeywordsPredicate; +import seedu.address.model.person.keywordspredicate.TraitContainsKeywordsPredicate; /** * Finds and lists all persons in address book whose name contains any of the argument keywords. diff --git a/src/main/java/seedu/address/logic/commands/findcommand/FindEmailCommand.java b/src/main/java/seedu/address/logic/commands/findcommand/FindEmailCommand.java index 95588daebd1..0a563bcac15 100644 --- a/src/main/java/seedu/address/logic/commands/findcommand/FindEmailCommand.java +++ b/src/main/java/seedu/address/logic/commands/findcommand/FindEmailCommand.java @@ -4,7 +4,7 @@ import seedu.address.logic.commands.CommandResult; import seedu.address.model.Model; -import seedu.address.model.person.EmailContainsKeywordsPredicate; +import seedu.address.model.person.keywordspredicate.EmailContainsKeywordsPredicate; /** * Finds and lists all persons in address book whose email contains any of the argument keywords. * Keyword matching is case-insensitive and allows partial matching, including numbers and symbols. diff --git a/src/main/java/seedu/address/logic/commands/findcommand/FindNameCommand.java b/src/main/java/seedu/address/logic/commands/findcommand/FindNameCommand.java index fa1c9b45ba4..52c6478dc61 100644 --- a/src/main/java/seedu/address/logic/commands/findcommand/FindNameCommand.java +++ b/src/main/java/seedu/address/logic/commands/findcommand/FindNameCommand.java @@ -4,7 +4,7 @@ import seedu.address.logic.commands.CommandResult; import seedu.address.model.Model; -import seedu.address.model.person.NameContainsKeywordsPredicate; +import seedu.address.model.person.keywordspredicate.NameContainsKeywordsPredicate; /** * Finds and lists all persons in address book whose name contains any of the argument keywords. * Keyword matching is case-insensitive and allows partial matching. diff --git a/src/main/java/seedu/address/logic/commands/findcommand/FindPhoneCommand.java b/src/main/java/seedu/address/logic/commands/findcommand/FindPhoneCommand.java index 3aff172c8e5..700e278a02d 100644 --- a/src/main/java/seedu/address/logic/commands/findcommand/FindPhoneCommand.java +++ b/src/main/java/seedu/address/logic/commands/findcommand/FindPhoneCommand.java @@ -4,7 +4,7 @@ import seedu.address.logic.commands.CommandResult; import seedu.address.model.Model; -import seedu.address.model.person.PhoneContainsKeywordsPredicate; +import seedu.address.model.person.keywordspredicate.PhoneContainsKeywordsPredicate; /** * Finds and lists all persons in address book whose phone number contains any of the argument keywords. * Keyword matching allows partial matching. diff --git a/src/main/java/seedu/address/logic/commands/findcommand/FindTagCommand.java b/src/main/java/seedu/address/logic/commands/findcommand/FindTagCommand.java index 3b4382c5001..cdb24e55cf1 100644 --- a/src/main/java/seedu/address/logic/commands/findcommand/FindTagCommand.java +++ b/src/main/java/seedu/address/logic/commands/findcommand/FindTagCommand.java @@ -2,10 +2,9 @@ import static java.util.Objects.requireNonNull; -import seedu.address.logic.Messages; import seedu.address.logic.commands.CommandResult; import seedu.address.model.Model; -import seedu.address.model.person.TagContainsKeywordsPredicate; +import seedu.address.model.person.keywordspredicate.TagContainsKeywordsPredicate; /** * Finds and lists all persons in address book whose tag contains any of the argument keywords. @@ -13,13 +12,8 @@ */ public class FindTagCommand extends FindCommand { - public static final String COMMAND_WORD = "filter"; - - public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all persons whose tags contain any of " - + "the specified keywords (case-insensitive) and displays them as a list with index numbers.\n" - + "Parameters: KEYWORD [MORE_KEYWORDS]...\n" - + "Example: " + COMMAND_WORD + " florist"; - + public static final String MESSAGE_FIND_TAG_PERSON_SUCCESS = "Search for tag containing \"%s\" was successful. " + + " Showing results:"; public FindTagCommand(TagContainsKeywordsPredicate predicate) { super(predicate); @@ -29,8 +23,12 @@ public FindTagCommand(TagContainsKeywordsPredicate predicate) { public CommandResult execute(Model model) { requireNonNull(model); model.updateFilteredPersonListByTag((TagContainsKeywordsPredicate) predicate); - return new CommandResult( - String.format(Messages.MESSAGE_PERSONS_LISTED_OVERVIEW, model.getFilteredPersonList().size())); + + if (!model.getFilteredPersonList().isEmpty()) { + return new CommandResult(String.format(MESSAGE_FIND_TAG_PERSON_SUCCESS, predicate.getDisplayString())); + } else { + return new CommandResult(MESSAGE_FIND_PERSON_UNSUCCESSFUL); + } } @Override diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java index 695cdbefdd4..cb46346dda4 100644 --- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java +++ b/src/main/java/seedu/address/logic/parser/AddressBookParser.java @@ -16,12 +16,11 @@ import seedu.address.logic.commands.DeleteTagCommand; import seedu.address.logic.commands.EditCommand; import seedu.address.logic.commands.ExitCommand; -import seedu.address.logic.commands.FindTagCommand; -import seedu.address.logic.commands.FindCommand; import seedu.address.logic.commands.HelpCommand; import seedu.address.logic.commands.ListCommand; import seedu.address.logic.commands.TagCommand; import seedu.address.logic.commands.UntagCommand; +import seedu.address.logic.commands.findcommand.FindCommand; import seedu.address.logic.parser.exceptions.ParseException; /** @@ -62,7 +61,6 @@ public Command parseCommand(String userInput) throws ParseException { case DeleteCommand.COMMAND_WORD -> new DeleteCommandParser().parse(arguments); case ClearCommand.COMMAND_WORD -> new ClearCommand(); case FindCommand.COMMAND_WORD -> new FindCommandParser().parse(arguments); - case FindTagCommand.COMMAND_WORD -> new FilterCommandParser().parse(arguments); case ListCommand.COMMAND_WORD -> new ListCommand(); case ExitCommand.COMMAND_WORD -> new ExitCommand(); case HelpCommand.COMMAND_WORD -> new HelpCommand(); diff --git a/src/main/java/seedu/address/logic/parser/FilterCommandParser.java b/src/main/java/seedu/address/logic/parser/FilterCommandParser.java deleted file mode 100644 index e150ff1e85d..00000000000 --- a/src/main/java/seedu/address/logic/parser/FilterCommandParser.java +++ /dev/null @@ -1,34 +0,0 @@ -package seedu.address.logic.parser; - -import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; - -import java.util.Arrays; - -import seedu.address.logic.commands.findcommand.FindTagCommand; -import seedu.address.logic.parser.exceptions.ParseException; -import seedu.address.model.person.TagContainsKeywordsPredicate; - - -/** - * Parses input arguments and creates a new FindCommand object - */ -public class FilterCommandParser implements Parser { - - /** - * Parses the given {@code String} of arguments in the context of the FindTagCommand - * and returns a FindTagCommand object for execution. - * @throws ParseException if the user input does not conform the expected format - */ - public FindTagCommand parse(String args) throws ParseException { - String trimmedArgs = args.trim(); - if (trimmedArgs.isEmpty()) { - throw new ParseException( - String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindTagCommand.MESSAGE_USAGE)); - } - - String[] nameKeywords = trimmedArgs.split("\\s+"); - - return new FindTagCommand(new TagContainsKeywordsPredicate(Arrays.asList(nameKeywords))); - } - -} diff --git a/src/main/java/seedu/address/logic/parser/FindCommandParser.java b/src/main/java/seedu/address/logic/parser/FindCommandParser.java index be472eaba93..67831401966 100644 --- a/src/main/java/seedu/address/logic/parser/FindCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/FindCommandParser.java @@ -18,11 +18,11 @@ import seedu.address.logic.commands.findcommand.FindPhoneCommand; import seedu.address.logic.commands.findcommand.FindTagCommand; import seedu.address.logic.parser.exceptions.ParseException; -import seedu.address.model.person.AddressContainsKeywordsPredicate; -import seedu.address.model.person.EmailContainsKeywordsPredicate; -import seedu.address.model.person.NameContainsKeywordsPredicate; -import seedu.address.model.person.PhoneContainsKeywordsPredicate; -import seedu.address.model.person.TagContainsKeywordsPredicate; +import seedu.address.model.person.keywordspredicate.AddressContainsKeywordsPredicate; +import seedu.address.model.person.keywordspredicate.EmailContainsKeywordsPredicate; +import seedu.address.model.person.keywordspredicate.NameContainsKeywordsPredicate; +import seedu.address.model.person.keywordspredicate.PhoneContainsKeywordsPredicate; +import seedu.address.model.person.keywordspredicate.TagContainsKeywordsPredicate; /** diff --git a/src/main/java/seedu/address/model/person/AddressContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/person/keywordspredicate/AddressContainsKeywordsPredicate.java similarity index 90% rename from src/main/java/seedu/address/model/person/AddressContainsKeywordsPredicate.java rename to src/main/java/seedu/address/model/person/keywordspredicate/AddressContainsKeywordsPredicate.java index 158770e9738..a8ac94a0bea 100644 --- a/src/main/java/seedu/address/model/person/AddressContainsKeywordsPredicate.java +++ b/src/main/java/seedu/address/model/person/keywordspredicate/AddressContainsKeywordsPredicate.java @@ -1,8 +1,9 @@ -package seedu.address.model.person; +package seedu.address.model.person.keywordspredicate; import java.util.List; import seedu.address.commons.util.StringUtil; +import seedu.address.model.person.Person; /** * Tests that a {@code Person}'s {@code Address} matches any of the keywords given. diff --git a/src/main/java/seedu/address/model/person/EmailContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/person/keywordspredicate/EmailContainsKeywordsPredicate.java similarity index 90% rename from src/main/java/seedu/address/model/person/EmailContainsKeywordsPredicate.java rename to src/main/java/seedu/address/model/person/keywordspredicate/EmailContainsKeywordsPredicate.java index feaa73d75b6..918f6f2c9f4 100644 --- a/src/main/java/seedu/address/model/person/EmailContainsKeywordsPredicate.java +++ b/src/main/java/seedu/address/model/person/keywordspredicate/EmailContainsKeywordsPredicate.java @@ -1,8 +1,9 @@ -package seedu.address.model.person; +package seedu.address.model.person.keywordspredicate; import java.util.List; import seedu.address.commons.util.StringUtil; +import seedu.address.model.person.Person; /** * Tests that a {@code Person}'s {@code Email} matches any of the keywords given. diff --git a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/person/keywordspredicate/NameContainsKeywordsPredicate.java similarity index 90% rename from src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java rename to src/main/java/seedu/address/model/person/keywordspredicate/NameContainsKeywordsPredicate.java index abd7ce89166..b5d356aad5b 100644 --- a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java +++ b/src/main/java/seedu/address/model/person/keywordspredicate/NameContainsKeywordsPredicate.java @@ -1,8 +1,9 @@ -package seedu.address.model.person; +package seedu.address.model.person.keywordspredicate; import java.util.List; import seedu.address.commons.util.StringUtil; +import seedu.address.model.person.Person; /** * Tests that a {@code Person}'s {@code Name} matches any of the keywords given. diff --git a/src/main/java/seedu/address/model/person/PhoneContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/person/keywordspredicate/PhoneContainsKeywordsPredicate.java similarity index 90% rename from src/main/java/seedu/address/model/person/PhoneContainsKeywordsPredicate.java rename to src/main/java/seedu/address/model/person/keywordspredicate/PhoneContainsKeywordsPredicate.java index 8c622c5d226..fd9ee33c785 100644 --- a/src/main/java/seedu/address/model/person/PhoneContainsKeywordsPredicate.java +++ b/src/main/java/seedu/address/model/person/keywordspredicate/PhoneContainsKeywordsPredicate.java @@ -1,8 +1,9 @@ -package seedu.address.model.person; +package seedu.address.model.person.keywordspredicate; import java.util.List; import seedu.address.commons.util.StringUtil; +import seedu.address.model.person.Person; /** * Tests that a {@code Person}'s {@code Phone} matches any of the keywords given. diff --git a/src/main/java/seedu/address/model/person/TagContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/person/keywordspredicate/TagContainsKeywordsPredicate.java similarity index 83% rename from src/main/java/seedu/address/model/person/TagContainsKeywordsPredicate.java rename to src/main/java/seedu/address/model/person/keywordspredicate/TagContainsKeywordsPredicate.java index 3bd564acff3..e0ebd65fc40 100644 --- a/src/main/java/seedu/address/model/person/TagContainsKeywordsPredicate.java +++ b/src/main/java/seedu/address/model/person/keywordspredicate/TagContainsKeywordsPredicate.java @@ -1,4 +1,4 @@ -package seedu.address.model.person; +package seedu.address.model.person.keywordspredicate; import java.util.List; @@ -17,7 +17,7 @@ public TagContainsKeywordsPredicate(List keywords) { @Override public boolean test(Tag tag) { return keywords.stream() - .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(tag.getTagName().toString(), keyword)); + .anyMatch(keyword -> StringUtil.containsPartialWordIgnoreCase(tag.getTagName().toString(), keyword)); } @Override diff --git a/src/main/java/seedu/address/model/person/TraitContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/person/keywordspredicate/TraitContainsKeywordsPredicate.java similarity index 95% rename from src/main/java/seedu/address/model/person/TraitContainsKeywordsPredicate.java rename to src/main/java/seedu/address/model/person/keywordspredicate/TraitContainsKeywordsPredicate.java index 7355a34393f..47592039df8 100644 --- a/src/main/java/seedu/address/model/person/TraitContainsKeywordsPredicate.java +++ b/src/main/java/seedu/address/model/person/keywordspredicate/TraitContainsKeywordsPredicate.java @@ -1,4 +1,4 @@ -package seedu.address.model.person; +package seedu.address.model.person.keywordspredicate; import java.util.List; import java.util.function.Predicate; diff --git a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java index 293d44e15d2..98e5cc1bb80 100644 --- a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java +++ b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java @@ -17,8 +17,8 @@ import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.model.AddressBook; import seedu.address.model.Model; -import seedu.address.model.person.NameContainsKeywordsPredicate; import seedu.address.model.person.Person; +import seedu.address.model.person.keywordspredicate.NameContainsKeywordsPredicate; import seedu.address.model.tag.Tag; import seedu.address.model.tag.TagName; import seedu.address.testutil.EditPersonDescriptorBuilder; diff --git a/src/test/java/seedu/address/logic/commands/FindAddressCommandTest.java b/src/test/java/seedu/address/logic/commands/FindAddressCommandTest.java index 4d92c636ee2..0e5125f82f4 100644 --- a/src/test/java/seedu/address/logic/commands/FindAddressCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/FindAddressCommandTest.java @@ -22,7 +22,7 @@ import seedu.address.model.Model; import seedu.address.model.ModelManager; import seedu.address.model.UserPrefs; -import seedu.address.model.person.AddressContainsKeywordsPredicate; +import seedu.address.model.person.keywordspredicate.AddressContainsKeywordsPredicate; public class FindAddressCommandTest { private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); diff --git a/src/test/java/seedu/address/logic/commands/FindEmailCommandTest.java b/src/test/java/seedu/address/logic/commands/FindEmailCommandTest.java index e23814a1b4e..f29fed5b0d6 100644 --- a/src/test/java/seedu/address/logic/commands/FindEmailCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/FindEmailCommandTest.java @@ -23,7 +23,7 @@ import seedu.address.model.Model; import seedu.address.model.ModelManager; import seedu.address.model.UserPrefs; -import seedu.address.model.person.EmailContainsKeywordsPredicate; +import seedu.address.model.person.keywordspredicate.EmailContainsKeywordsPredicate; public class FindEmailCommandTest { diff --git a/src/test/java/seedu/address/logic/commands/FindNameCommandTest.java b/src/test/java/seedu/address/logic/commands/FindNameCommandTest.java index 2a385c1a56f..d1b5ed103e9 100644 --- a/src/test/java/seedu/address/logic/commands/FindNameCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/FindNameCommandTest.java @@ -25,7 +25,7 @@ import seedu.address.model.Model; import seedu.address.model.ModelManager; import seedu.address.model.UserPrefs; -import seedu.address.model.person.NameContainsKeywordsPredicate; +import seedu.address.model.person.keywordspredicate.NameContainsKeywordsPredicate; /** * Contains integration tests (interaction with the Model) for {@code FindNameCommand}. diff --git a/src/test/java/seedu/address/logic/commands/FindPhoneCommandTest.java b/src/test/java/seedu/address/logic/commands/FindPhoneCommandTest.java index c6eaf42da55..963a231e0da 100644 --- a/src/test/java/seedu/address/logic/commands/FindPhoneCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/FindPhoneCommandTest.java @@ -25,7 +25,7 @@ import seedu.address.model.Model; import seedu.address.model.ModelManager; import seedu.address.model.UserPrefs; -import seedu.address.model.person.PhoneContainsKeywordsPredicate; +import seedu.address.model.person.keywordspredicate.PhoneContainsKeywordsPredicate; public class FindPhoneCommandTest { private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); diff --git a/src/test/java/seedu/address/logic/commands/FindTagCommandTest.java b/src/test/java/seedu/address/logic/commands/FindTagCommandTest.java index bc79137ace3..77830c16045 100644 --- a/src/test/java/seedu/address/logic/commands/FindTagCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/FindTagCommandTest.java @@ -3,8 +3,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import static seedu.address.logic.Messages.MESSAGE_PERSONS_LISTED_OVERVIEW; import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; +import static seedu.address.logic.commands.findcommand.FindCommand.MESSAGE_FIND_PERSON_UNSUCCESSFUL; +import static seedu.address.logic.commands.findcommand.FindTagCommand.MESSAGE_FIND_TAG_PERSON_SUCCESS; import static seedu.address.testutil.TypicalPersons.ALICE; import static seedu.address.testutil.TypicalPersons.BENSON; import static seedu.address.testutil.TypicalPersons.DANIEL; @@ -19,7 +20,7 @@ import seedu.address.model.Model; import seedu.address.model.ModelManager; import seedu.address.model.UserPrefs; -import seedu.address.model.person.TagContainsKeywordsPredicate; +import seedu.address.model.person.keywordspredicate.TagContainsKeywordsPredicate; @@ -56,7 +57,7 @@ public void equals() { @Test public void execute_zeroKeywords_noPersonFound() { - String expectedMessage = String.format(MESSAGE_PERSONS_LISTED_OVERVIEW, 0); + String expectedMessage = String.format(MESSAGE_FIND_PERSON_UNSUCCESSFUL); TagContainsKeywordsPredicate predicate = preparePredicate(" "); FindTagCommand command = new FindTagCommand(predicate); expectedModel.updateFilteredPersonListByTag(predicate); @@ -66,8 +67,8 @@ public void execute_zeroKeywords_noPersonFound() { @Test public void execute_multipleKeywords_multiplePersonsFound() { - String expectedMessage = String.format(MESSAGE_PERSONS_LISTED_OVERVIEW, 3); TagContainsKeywordsPredicate predicate = preparePredicate("friends"); + String expectedMessage = String.format(MESSAGE_FIND_TAG_PERSON_SUCCESS, predicate.getDisplayString()); FindTagCommand command = new FindTagCommand(predicate); expectedModel.updateFilteredPersonListByTag(predicate); assertCommandSuccess(command, model, expectedMessage, expectedModel); diff --git a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java b/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java index 05a97884639..9afe7b43653 100644 --- a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java +++ b/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java @@ -20,15 +20,14 @@ import seedu.address.logic.commands.EditCommand; import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; import seedu.address.logic.commands.ExitCommand; -import seedu.address.logic.commands.findcommand.FindTagCommand; -import seedu.address.logic.commands.findcommand.FindCommand; -import seedu.address.logic.commands.findcommand.FindNameCommand; import seedu.address.logic.commands.HelpCommand; import seedu.address.logic.commands.ListCommand; import seedu.address.logic.commands.TagCommand; +import seedu.address.logic.commands.findcommand.FindCommand; +import seedu.address.logic.commands.findcommand.FindNameCommand; import seedu.address.logic.parser.exceptions.ParseException; -import seedu.address.model.person.NameContainsKeywordsPredicate; import seedu.address.model.person.Person; +import seedu.address.model.person.keywordspredicate.NameContainsKeywordsPredicate; import seedu.address.model.tag.Tag; import seedu.address.model.tag.TagName; import seedu.address.testutil.EditPersonDescriptorBuilder; @@ -82,11 +81,6 @@ public void parseCommand_find() throws Exception { assertEquals(new FindNameCommand(new NameContainsKeywordsPredicate(keywords)), command); } - @Test - public void parseCommand_filter() throws Exception { - assertTrue(parser.parseCommand(FindTagCommand.COMMAND_WORD + " " + "foo") instanceof FindTagCommand); - } - @Test public void parseCommand_help() throws Exception { assertTrue(parser.parseCommand(HelpCommand.COMMAND_WORD) instanceof HelpCommand); diff --git a/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java b/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java index 7c0c3fc9025..263e92ffb0c 100644 --- a/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java @@ -16,10 +16,10 @@ import seedu.address.logic.commands.findcommand.FindNameCommand; import seedu.address.logic.commands.findcommand.FindPhoneCommand; import seedu.address.logic.parser.exceptions.ParseException; -import seedu.address.model.person.AddressContainsKeywordsPredicate; -import seedu.address.model.person.EmailContainsKeywordsPredicate; -import seedu.address.model.person.NameContainsKeywordsPredicate; -import seedu.address.model.person.PhoneContainsKeywordsPredicate; +import seedu.address.model.person.keywordspredicate.AddressContainsKeywordsPredicate; +import seedu.address.model.person.keywordspredicate.EmailContainsKeywordsPredicate; +import seedu.address.model.person.keywordspredicate.NameContainsKeywordsPredicate; +import seedu.address.model.person.keywordspredicate.PhoneContainsKeywordsPredicate; public class FindCommandParserTest { diff --git a/src/test/java/seedu/address/logic/parser/FindTagCommandParserTest.java b/src/test/java/seedu/address/logic/parser/FindTagCommandParserTest.java deleted file mode 100644 index 88f8b20cc28..00000000000 --- a/src/test/java/seedu/address/logic/parser/FindTagCommandParserTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package seedu.address.logic.parser; - -import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; -import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure; -import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess; - -import java.util.List; - -import org.junit.jupiter.api.Test; - -import seedu.address.logic.commands.findcommand.FindTagCommand; -import seedu.address.model.person.TagContainsKeywordsPredicate; - -public class FindTagCommandParserTest { - - private FilterCommandParser parser = new FilterCommandParser(); - - @Test - public void parse_emptyArg_throwsParseException() { - assertParseFailure(parser, " ", String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindTagCommand.MESSAGE_USAGE)); - } - - @Test - public void parse_validArgs_returnsFilterCommand() { - // no leading and trailing whitespaces - FindTagCommand expectedFindTagCommand = - new FindTagCommand(new TagContainsKeywordsPredicate(List.of("friends"))); - assertParseSuccess(parser, "friends", expectedFindTagCommand); - - // multiple whitespaces between keywords - assertParseSuccess(parser, "friends", expectedFindTagCommand); - } - -} diff --git a/src/test/java/seedu/address/model/ModelManagerTest.java b/src/test/java/seedu/address/model/ModelManagerTest.java index 5939636affc..cd88e94ba5d 100644 --- a/src/test/java/seedu/address/model/ModelManagerTest.java +++ b/src/test/java/seedu/address/model/ModelManagerTest.java @@ -16,7 +16,7 @@ import org.junit.jupiter.api.Test; import seedu.address.commons.core.GuiSettings; -import seedu.address.model.person.NameContainsKeywordsPredicate; +import seedu.address.model.person.keywordspredicate.NameContainsKeywordsPredicate; import seedu.address.model.tag.Tag; import seedu.address.model.tag.TagName; import seedu.address.testutil.AddressBookBuilder; diff --git a/src/test/java/seedu/address/model/person/AddressContainsKeywordsPredicateTest.java b/src/test/java/seedu/address/model/person/AddressContainsKeywordsPredicateTest.java index 5278431cb7e..9865f8961a6 100644 --- a/src/test/java/seedu/address/model/person/AddressContainsKeywordsPredicateTest.java +++ b/src/test/java/seedu/address/model/person/AddressContainsKeywordsPredicateTest.java @@ -10,6 +10,7 @@ import org.junit.jupiter.api.Test; +import seedu.address.model.person.keywordspredicate.AddressContainsKeywordsPredicate; import seedu.address.testutil.PersonBuilder; public class AddressContainsKeywordsPredicateTest { diff --git a/src/test/java/seedu/address/model/person/EmailContainsKeywordsPredicateTest.java b/src/test/java/seedu/address/model/person/EmailContainsKeywordsPredicateTest.java index bd18478a6fc..bbc9f6b4670 100644 --- a/src/test/java/seedu/address/model/person/EmailContainsKeywordsPredicateTest.java +++ b/src/test/java/seedu/address/model/person/EmailContainsKeywordsPredicateTest.java @@ -10,6 +10,7 @@ import org.junit.jupiter.api.Test; +import seedu.address.model.person.keywordspredicate.EmailContainsKeywordsPredicate; import seedu.address.testutil.PersonBuilder; public class EmailContainsKeywordsPredicateTest { diff --git a/src/test/java/seedu/address/model/person/NameContainsKeywordsPredicateTest.java b/src/test/java/seedu/address/model/person/NameContainsKeywordsPredicateTest.java index 6b3fd90ade7..466c78d1fbf 100644 --- a/src/test/java/seedu/address/model/person/NameContainsKeywordsPredicateTest.java +++ b/src/test/java/seedu/address/model/person/NameContainsKeywordsPredicateTest.java @@ -10,6 +10,7 @@ import org.junit.jupiter.api.Test; +import seedu.address.model.person.keywordspredicate.NameContainsKeywordsPredicate; import seedu.address.testutil.PersonBuilder; public class NameContainsKeywordsPredicateTest { diff --git a/src/test/java/seedu/address/model/person/PhoneContainsKeywordsPredicateTest.java b/src/test/java/seedu/address/model/person/PhoneContainsKeywordsPredicateTest.java index 8bd95a4d613..124a7d40cd1 100644 --- a/src/test/java/seedu/address/model/person/PhoneContainsKeywordsPredicateTest.java +++ b/src/test/java/seedu/address/model/person/PhoneContainsKeywordsPredicateTest.java @@ -10,6 +10,7 @@ import org.junit.jupiter.api.Test; +import seedu.address.model.person.keywordspredicate.PhoneContainsKeywordsPredicate; import seedu.address.testutil.PersonBuilder; public class PhoneContainsKeywordsPredicateTest { From 4894692be03605cc21cc6258c9b1fd7fb0532ef2 Mon Sep 17 00:00:00 2001 From: Han Bin Date: Thu, 17 Oct 2024 01:15:18 +0800 Subject: [PATCH 20/33] Add tests for UnassignWeddingCommand.java Add tests for UnassignWeddingCommand. --- .../address/logic/commands/EditCommand.java | 4 +- .../commands/UnassignWeddingCommand.java | 4 - .../logic/parser/EditCommandParser.java | 1 + .../typicalPersonsAddressBook.json | 3 +- .../logic/commands/CommandTestUtil.java | 4 - .../logic/commands/DeleteTagCommandTest.java | 4 +- .../commands/UnassignWeddingCommandTest.java | 101 ++++++++++++++++++ .../parser/DeleteTagCommandParserTest.java | 4 +- .../seedu/address/model/AddressBookTest.java | 2 +- .../seedu/address/model/ModelManagerTest.java | 2 +- .../address/model/tag/UniqueTagListTest.java | 4 +- .../testutil/EditPersonDescriptorBuilder.java | 16 +++ .../seedu/address/testutil/PersonUtil.java | 15 ++- .../address/testutil/TypicalPersons.java | 28 ++--- .../seedu/address/testutil/TypicalTags.java | 17 +++ 15 files changed, 172 insertions(+), 37 deletions(-) create mode 100644 src/test/java/seedu/address/logic/commands/UnassignWeddingCommandTest.java create mode 100644 src/test/java/seedu/address/testutil/TypicalTags.java diff --git a/src/main/java/seedu/address/logic/commands/EditCommand.java b/src/main/java/seedu/address/logic/commands/EditCommand.java index 328ec7190da..d930d1d5581 100644 --- a/src/main/java/seedu/address/logic/commands/EditCommand.java +++ b/src/main/java/seedu/address/logic/commands/EditCommand.java @@ -201,7 +201,7 @@ public Optional
getAddress() { * A defensive copy of {@code tags} is used internally. */ public void setTags(Set tags) { - this.tags = (tags != null) ? new HashSet<>(tags) : null; + this.tags = (tags != null) ? new HashSet<>(tags) : new HashSet<>(); } /** @@ -218,7 +218,7 @@ public Optional> getTags() { * A defensive copy of {@code weddings} is used internally. */ public void setWeddings(Set weddings) { - this.weddings = (weddings != null) ? new HashSet<>(weddings) : null; + this.weddings = (weddings != null) ? new HashSet<>(weddings) : new HashSet<>(); } /** diff --git a/src/main/java/seedu/address/logic/commands/UnassignWeddingCommand.java b/src/main/java/seedu/address/logic/commands/UnassignWeddingCommand.java index 01689e1afbb..480b0849a02 100644 --- a/src/main/java/seedu/address/logic/commands/UnassignWeddingCommand.java +++ b/src/main/java/seedu/address/logic/commands/UnassignWeddingCommand.java @@ -71,10 +71,6 @@ public CommandResult execute(Model model) throws CommandException { throw new CommandException(MESSAGE_WEDDING_NOT_FOUND_IN_CONTACT); } - if (weddingsToRemove.isEmpty()) { - throw new CommandException(MESSAGE_WEDDING_NOT_FOUND_IN_CONTACT); - } - if (!updatedWeddings.containsAll(weddingsToRemove)) { throw new CommandException(MESSAGE_WEDDING_NOT_FOUND_IN_CONTACT); } diff --git a/src/main/java/seedu/address/logic/parser/EditCommandParser.java b/src/main/java/seedu/address/logic/parser/EditCommandParser.java index 91093d2b233..3b578fe67fe 100644 --- a/src/main/java/seedu/address/logic/parser/EditCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/EditCommandParser.java @@ -61,6 +61,7 @@ public EditCommand parse(String args) throws ParseException { if (argMultimap.getValue(PREFIX_ADDRESS).isPresent()) { editPersonDescriptor.setAddress(ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS).orElse(""))); } + parseTagsForEdit(argMultimap.getAllValues(PREFIX_TAG)).ifPresent(editPersonDescriptor::setTags); parseWeddingsForEdit(argMultimap.getAllValues(PREFIX_WEDDING)).ifPresent(editPersonDescriptor::setWeddings); diff --git a/src/test/data/JsonSerializableAddressBookTest/typicalPersonsAddressBook.json b/src/test/data/JsonSerializableAddressBookTest/typicalPersonsAddressBook.json index 323f6d95174..6ed28d78ed6 100644 --- a/src/test/data/JsonSerializableAddressBookTest/typicalPersonsAddressBook.json +++ b/src/test/data/JsonSerializableAddressBookTest/typicalPersonsAddressBook.json @@ -5,7 +5,8 @@ "phone" : "94351253", "email" : "alice@example.com", "address" : "123, Jurong West Ave 6, #08-111", - "tags" : [ "friends" ] + "tags" : [ "friends" ], + "weddings": ["Amy's Wedding"] }, { "name" : "Benson Meier", "phone" : "98765432", diff --git a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java index 7490c036343..6bc88aa5f06 100644 --- a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java +++ b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java @@ -20,8 +20,6 @@ import seedu.address.model.Model; import seedu.address.model.person.NameContainsKeywordsPredicate; import seedu.address.model.person.Person; -import seedu.address.model.tag.Tag; -import seedu.address.model.tag.TagName; import seedu.address.testutil.EditPersonDescriptorBuilder; /** @@ -96,8 +94,6 @@ public class CommandTestUtil { public static final EditCommand.EditPersonDescriptor DESC_AMY; public static final EditCommand.EditPersonDescriptor DESC_BOB; - public static final Tag TEST_TAG_FLORIST = new Tag(new TagName(VALID_TAG_FLORIST)); - static { DESC_AMY = new EditPersonDescriptorBuilder().withName(VALID_NAME_AMY) .withPhone(VALID_PHONE_AMY).withEmail(VALID_EMAIL_AMY).withAddress(VALID_ADDRESS_AMY) diff --git a/src/test/java/seedu/address/logic/commands/DeleteTagCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteTagCommandTest.java index 29ccad16588..b614ada6ec4 100644 --- a/src/test/java/seedu/address/logic/commands/DeleteTagCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/DeleteTagCommandTest.java @@ -4,9 +4,9 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure; import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; -import static seedu.address.testutil.TypicalPersons.FLORIST; -import static seedu.address.testutil.TypicalPersons.PHOTOGRAPHER; import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; +import static seedu.address.testutil.TypicalTags.FLORIST; +import static seedu.address.testutil.TypicalTags.PHOTOGRAPHER; import org.junit.jupiter.api.Test; diff --git a/src/test/java/seedu/address/logic/commands/UnassignWeddingCommandTest.java b/src/test/java/seedu/address/logic/commands/UnassignWeddingCommandTest.java new file mode 100644 index 00000000000..d5926b38a71 --- /dev/null +++ b/src/test/java/seedu/address/logic/commands/UnassignWeddingCommandTest.java @@ -0,0 +1,101 @@ +package seedu.address.logic.commands; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; +import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON; +import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; +import static seedu.address.testutil.TypicalWeddings.AMY_WEDDING; +import static seedu.address.testutil.TypicalWeddings.BOB_WEDDING; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import org.junit.jupiter.api.Test; + +import seedu.address.logic.Messages; +import seedu.address.model.Model; +import seedu.address.model.ModelManager; +import seedu.address.model.UserPrefs; +import seedu.address.model.person.Person; +import seedu.address.model.wedding.Wedding; + +public class UnassignWeddingCommandTest { + private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + + @Test + public void unassignWedding_success() { + Person personToEdit = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); + HashSet weddingsToRemove = new HashSet<>(Arrays.asList(AMY_WEDDING)); + + UnassignWeddingCommand unassignWeddingCommand = new UnassignWeddingCommand( + INDEX_FIRST_PERSON, weddingsToRemove); + + String expectedMessage = String.format(UnassignWeddingCommand.MESSAGE_REMOVE_WEDDING_SUCCESS, "Amy's Wedding", + personToEdit.getName().toString()); + + Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); + Set updatedWeddings = new HashSet<>(personToEdit.getWeddings()); + updatedWeddings.removeAll(weddingsToRemove); + Person editedPerson = new Person( + personToEdit.getName(), + personToEdit.getPhone(), + personToEdit.getEmail(), + personToEdit.getAddress(), + personToEdit.getTags(), + updatedWeddings); + expectedModel.setPerson(personToEdit, editedPerson); + + CommandTestUtil.assertCommandSuccess(unassignWeddingCommand, model, expectedMessage, expectedModel); + } + + @Test + public void unassignWeddingZeroWeddings_fail() { + HashSet weddingsToRemove = new HashSet<>(Arrays.asList(AMY_WEDDING)); + UnassignWeddingCommand unassignWeddingCommand = new UnassignWeddingCommand( + INDEX_SECOND_PERSON, weddingsToRemove); + String expectedMessage = Messages.MESSAGE_WEDDING_NOT_FOUND_IN_CONTACT; + CommandTestUtil.assertCommandFailure(unassignWeddingCommand, model, expectedMessage); + } + + @Test + public void unassignWeddingNoMatchingWedding_fail() { + HashSet weddingsToRemove = new HashSet<>(Arrays.asList(BOB_WEDDING)); + UnassignWeddingCommand unassignWeddingCommand = new UnassignWeddingCommand( + INDEX_FIRST_PERSON, weddingsToRemove); + String expectedMessage = Messages.MESSAGE_WEDDING_NOT_FOUND_IN_CONTACT; + CommandTestUtil.assertCommandFailure(unassignWeddingCommand, model, expectedMessage); + } + + @Test + public void sameCommandTest_success() { + HashSet weddingsToRemove = new HashSet<>(Arrays.asList(BOB_WEDDING)); + UnassignWeddingCommand command1 = new UnassignWeddingCommand(INDEX_FIRST_PERSON, weddingsToRemove); + assertTrue(command1.equals(command1)); + } + + @Test + public void differentCommandType_fail() { + HashSet weddingsToRemove = new HashSet<>(); + UnassignWeddingCommand command1 = new UnassignWeddingCommand(INDEX_FIRST_PERSON, weddingsToRemove); + assertFalse(command1.equals(null)); + } + + @Test + public void differentIndex_fail() { + HashSet weddingsToRemove = new HashSet<>(); + UnassignWeddingCommand command1 = new UnassignWeddingCommand(INDEX_FIRST_PERSON, weddingsToRemove); + UnassignWeddingCommand command2 = new UnassignWeddingCommand(INDEX_SECOND_PERSON, weddingsToRemove); + assertFalse(command1.equals(command2)); + } + + @Test + public void differentWeddings_fail() { + HashSet weddingsToRemove1 = new HashSet<>(); + HashSet weddingsToRemove2 = new HashSet<>(Arrays.asList(AMY_WEDDING)); + UnassignWeddingCommand command1 = new UnassignWeddingCommand(INDEX_FIRST_PERSON, weddingsToRemove1); + UnassignWeddingCommand command2 = new UnassignWeddingCommand(INDEX_SECOND_PERSON, weddingsToRemove2); + assertFalse(command1.equals(command2)); + } +} diff --git a/src/test/java/seedu/address/logic/parser/DeleteTagCommandParserTest.java b/src/test/java/seedu/address/logic/parser/DeleteTagCommandParserTest.java index 855010ec946..0307bb64028 100644 --- a/src/test/java/seedu/address/logic/parser/DeleteTagCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/DeleteTagCommandParserTest.java @@ -1,9 +1,9 @@ package seedu.address.logic.parser; import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; -import static seedu.address.logic.commands.CommandTestUtil.TEST_TAG_FLORIST; import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure; import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess; +import static seedu.address.testutil.TypicalTags.FLORIST; import org.junit.jupiter.api.Test; @@ -15,7 +15,7 @@ public class DeleteTagCommandParserTest { @Test public void parse_validArgs_returnsDeleteTagCommand() { - assertParseSuccess(parser, " t/florist", new DeleteTagCommand(TEST_TAG_FLORIST)); + assertParseSuccess(parser, " t/florist", new DeleteTagCommand(FLORIST)); } @Test diff --git a/src/test/java/seedu/address/model/AddressBookTest.java b/src/test/java/seedu/address/model/AddressBookTest.java index fcb07b79759..ac39fe90f7d 100644 --- a/src/test/java/seedu/address/model/AddressBookTest.java +++ b/src/test/java/seedu/address/model/AddressBookTest.java @@ -7,8 +7,8 @@ import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND; import static seedu.address.testutil.Assert.assertThrows; import static seedu.address.testutil.TypicalPersons.ALICE; -import static seedu.address.testutil.TypicalPersons.FLORIST; import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; +import static seedu.address.testutil.TypicalTags.FLORIST; import static seedu.address.testutil.TypicalWeddings.AMY_WEDDING; import java.util.Arrays; diff --git a/src/test/java/seedu/address/model/ModelManagerTest.java b/src/test/java/seedu/address/model/ModelManagerTest.java index 5939636affc..3f20d13e609 100644 --- a/src/test/java/seedu/address/model/ModelManagerTest.java +++ b/src/test/java/seedu/address/model/ModelManagerTest.java @@ -7,7 +7,7 @@ import static seedu.address.testutil.Assert.assertThrows; import static seedu.address.testutil.TypicalPersons.ALICE; import static seedu.address.testutil.TypicalPersons.BENSON; -import static seedu.address.testutil.TypicalPersons.FLORIST; +import static seedu.address.testutil.TypicalTags.FLORIST; import java.nio.file.Path; import java.nio.file.Paths; diff --git a/src/test/java/seedu/address/model/tag/UniqueTagListTest.java b/src/test/java/seedu/address/model/tag/UniqueTagListTest.java index 062f784f835..cdc247b1502 100644 --- a/src/test/java/seedu/address/model/tag/UniqueTagListTest.java +++ b/src/test/java/seedu/address/model/tag/UniqueTagListTest.java @@ -4,8 +4,8 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static seedu.address.testutil.Assert.assertThrows; -import static seedu.address.testutil.TypicalPersons.FLORIST; -import static seedu.address.testutil.TypicalPersons.PHOTOGRAPHER; +import static seedu.address.testutil.TypicalTags.FLORIST; +import static seedu.address.testutil.TypicalTags.PHOTOGRAPHER; import java.util.Arrays; import java.util.Collections; diff --git a/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java b/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java index 5e5a196a8ea..56e8970dc00 100644 --- a/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java +++ b/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java @@ -12,6 +12,8 @@ import seedu.address.model.person.Phone; import seedu.address.model.tag.Tag; import seedu.address.model.tag.TagName; +import seedu.address.model.wedding.Wedding; +import seedu.address.model.wedding.WeddingName; /** * A utility class to help with building EditPersonDescriptor objects. @@ -38,6 +40,8 @@ public EditPersonDescriptorBuilder(Person person) { descriptor.setEmail(person.getEmail()); descriptor.setAddress(person.getAddress()); descriptor.setTags(person.getTags()); + // Figure out why this is not possible + //descriptor.setWeddings(person.getWeddings()); } /** @@ -82,6 +86,18 @@ public EditPersonDescriptorBuilder withTags(String... tags) { return this; } + /** + * Parses the {@code weddings} into a {@code Set} and set it to the {@code EditPersonDescriptor} + * that we are building. + */ + + public EditPersonDescriptorBuilder withWeddings(String... weddings) { + Set weddingSet = Stream.of(weddings).map(WeddingName::new).map(Wedding::new) + .collect(Collectors.toSet()); + descriptor.setWeddings(weddingSet); + return this; + } + public EditPersonDescriptor build() { return descriptor; } diff --git a/src/test/java/seedu/address/testutil/PersonUtil.java b/src/test/java/seedu/address/testutil/PersonUtil.java index ee92d61b655..8628a0f31c9 100644 --- a/src/test/java/seedu/address/testutil/PersonUtil.java +++ b/src/test/java/seedu/address/testutil/PersonUtil.java @@ -5,6 +5,7 @@ import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; +import static seedu.address.logic.parser.CliSyntax.PREFIX_WEDDING; import java.util.Set; @@ -12,6 +13,7 @@ import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; import seedu.address.model.person.Person; import seedu.address.model.tag.Tag; +import seedu.address.model.wedding.Wedding; /** * A utility class for Person. @@ -35,7 +37,10 @@ public static String getPersonDetails(Person person) { sb.append(PREFIX_EMAIL + person.getEmail().value + " "); sb.append(PREFIX_ADDRESS + person.getAddress().value + " "); person.getTags().stream().forEach( - s -> sb.append(PREFIX_TAG + s.getTagName().toString() + " ") + s -> sb.append(PREFIX_TAG + s.getTagName().toString() + " ") + ); + person.getWeddings().stream().forEach( + s -> sb.append(PREFIX_WEDDING + s.getWeddingName().toString() + " ") ); return sb.toString(); } @@ -57,6 +62,14 @@ public static String getEditPersonDescriptorDetails(EditPersonDescriptor descrip tags.forEach(s -> sb.append(PREFIX_TAG).append(s.getTagName()).append(" ")); } } + if (descriptor.getWeddings().isPresent()) { + Set weddings = descriptor.getWeddings().get(); + if (weddings.isEmpty()) { + sb.append(PREFIX_WEDDING); + } else { + weddings.forEach(s -> sb.append(PREFIX_WEDDING).append(s.getWeddingName()).append(" ")); + } + } return sb.toString(); } } diff --git a/src/test/java/seedu/address/testutil/TypicalPersons.java b/src/test/java/seedu/address/testutil/TypicalPersons.java index a1fa93f8d88..b91084289e0 100644 --- a/src/test/java/seedu/address/testutil/TypicalPersons.java +++ b/src/test/java/seedu/address/testutil/TypicalPersons.java @@ -20,12 +20,13 @@ import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_CLIVE; import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_DOMINIC; import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_ERIC; -import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_FLORIST; import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_FRIEND; import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND; import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_NEIGHBOR; -import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_PHOTOGRAPHER; -import static seedu.address.logic.commands.CommandTestUtil.VALID_WEDDING_AMY; +import static seedu.address.testutil.TypicalTags.FLORIST; +import static seedu.address.testutil.TypicalTags.PHOTOGRAPHER; +import static seedu.address.testutil.TypicalWeddings.AMY_WEDDING; +import static seedu.address.testutil.TypicalWeddings.BOB_WEDDING; import java.util.ArrayList; import java.util.Arrays; @@ -33,10 +34,6 @@ import seedu.address.model.AddressBook; import seedu.address.model.person.Person; -import seedu.address.model.tag.Tag; -import seedu.address.model.tag.TagName; -import seedu.address.model.wedding.Wedding; -import seedu.address.model.wedding.WeddingName; /** * A utility class containing a list of {@code Person} objects to be used in tests. @@ -46,7 +43,8 @@ public class TypicalPersons { public static final Person ALICE = new PersonBuilder().withName("Alice Pauline") .withAddress("123, Jurong West Ave 6, #08-111").withEmail("alice@example.com") .withPhone("94351253") - .withTags("friends").build(); + .withTags("friends") + .withWeddings("Amy's Wedding").build(); public static final Person BENSON = new PersonBuilder().withName("Benson Meier") .withAddress("311, Clementi Ave 2, #02-25") .withEmail("johnd@example.com").withPhone("98765432") @@ -83,13 +81,6 @@ public class TypicalPersons { .withEmail(VALID_EMAIL_ERIC).withAddress(VALID_ADDRESS_ERIC).withTags(VALID_TAG_NEIGHBOR) .build(); - // Manually added Tags - public static final Tag FLORIST = new Tag(new TagName(VALID_TAG_FLORIST)); - public static final Tag PHOTOGRAPHER = new Tag(new TagName(VALID_TAG_PHOTOGRAPHER)); - public static final Wedding AMY_WEDDING = new Wedding(new WeddingName(VALID_WEDDING_AMY)); - - public static final String KEYWORD_MATCHING_MEIER = "Meier"; // A keyword that matches MEIER - private TypicalPersons() {} // prevents instantiation /** @@ -97,11 +88,14 @@ private TypicalPersons() {} // prevents instantiation */ public static AddressBook getTypicalAddressBook() { AddressBook ab = new AddressBook(); + ab.addTag(FLORIST); + ab.addTag(PHOTOGRAPHER); + ab.addWedding(AMY_WEDDING); + ab.addWedding(BOB_WEDDING); + for (Person person : getTypicalPersons()) { ab.addPerson(person); } - ab.addTag(FLORIST); - ab.addTag(PHOTOGRAPHER); return ab; } diff --git a/src/test/java/seedu/address/testutil/TypicalTags.java b/src/test/java/seedu/address/testutil/TypicalTags.java new file mode 100644 index 00000000000..633d2f354fa --- /dev/null +++ b/src/test/java/seedu/address/testutil/TypicalTags.java @@ -0,0 +1,17 @@ +package seedu.address.testutil; + +import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_FLORIST; +import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_PHOTOGRAPHER; + +import seedu.address.model.tag.Tag; +import seedu.address.model.tag.TagName; + +/** + * A utility class containing a list of {@code Wedding} objects to be used in tests. + */ +public class TypicalTags { + public static final TagName VALID_TAG_NAME_FLORIST = new TagName(VALID_TAG_FLORIST); + public static final TagName VALID_TAG_NAME_PHOTOGRAPHER = new TagName(VALID_TAG_PHOTOGRAPHER); + public static final Tag FLORIST = new Tag(VALID_TAG_NAME_FLORIST); + public static final Tag PHOTOGRAPHER = new Tag(VALID_TAG_NAME_PHOTOGRAPHER); +} From 1e523d7064ca983d6613e7c61b6c319dc449e3e7 Mon Sep 17 00:00:00 2001 From: Ricco Lim Date: Thu, 17 Oct 2024 01:18:49 +0800 Subject: [PATCH 21/33] Write tests for TagContainsKeywordsPredicateTest --- .../FindAddressCommandTest.java | 4 +- .../FindEmailCommandTest.java | 4 +- .../FindNameCommandTest.java | 4 +- .../FindPhoneCommandTest.java | 4 +- .../{ => findcommand}/FindTagCommandTest.java | 3 +- .../AddressContainsKeywordsPredicateTest.java | 3 +- .../EmailContainsKeywordsPredicateTest.java | 3 +- .../NameContainsKeywordsPredicateTest.java | 3 +- .../PhoneContainsKeywordsPredicateTest.java | 3 +- .../TagContainsKeywordsPredicateTest.java | 69 +++++++++++++++++++ 10 files changed, 78 insertions(+), 22 deletions(-) rename src/test/java/seedu/address/logic/commands/{ => findcommand}/FindAddressCommandTest.java (97%) rename src/test/java/seedu/address/logic/commands/{ => findcommand}/FindEmailCommandTest.java (97%) rename src/test/java/seedu/address/logic/commands/{ => findcommand}/FindNameCommandTest.java (97%) rename src/test/java/seedu/address/logic/commands/{ => findcommand}/FindPhoneCommandTest.java (97%) rename src/test/java/seedu/address/logic/commands/{ => findcommand}/FindTagCommandTest.java (97%) rename src/test/java/seedu/address/model/person/{ => keywordspredicate}/AddressContainsKeywordsPredicateTest.java (96%) rename src/test/java/seedu/address/model/person/{ => keywordspredicate}/EmailContainsKeywordsPredicateTest.java (96%) rename src/test/java/seedu/address/model/person/{ => keywordspredicate}/NameContainsKeywordsPredicateTest.java (96%) rename src/test/java/seedu/address/model/person/{ => keywordspredicate}/PhoneContainsKeywordsPredicateTest.java (96%) create mode 100644 src/test/java/seedu/address/model/person/keywordspredicate/TagContainsKeywordsPredicateTest.java diff --git a/src/test/java/seedu/address/logic/commands/FindAddressCommandTest.java b/src/test/java/seedu/address/logic/commands/findcommand/FindAddressCommandTest.java similarity index 97% rename from src/test/java/seedu/address/logic/commands/FindAddressCommandTest.java rename to src/test/java/seedu/address/logic/commands/findcommand/FindAddressCommandTest.java index 0e5125f82f4..19388990906 100644 --- a/src/test/java/seedu/address/logic/commands/FindAddressCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/findcommand/FindAddressCommandTest.java @@ -1,4 +1,4 @@ -package seedu.address.logic.commands; +package seedu.address.logic.commands.findcommand; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -17,8 +17,6 @@ import org.junit.jupiter.api.Test; -import seedu.address.logic.commands.findcommand.FindAddressCommand; -import seedu.address.logic.commands.findcommand.FindCommand; import seedu.address.model.Model; import seedu.address.model.ModelManager; import seedu.address.model.UserPrefs; diff --git a/src/test/java/seedu/address/logic/commands/FindEmailCommandTest.java b/src/test/java/seedu/address/logic/commands/findcommand/FindEmailCommandTest.java similarity index 97% rename from src/test/java/seedu/address/logic/commands/FindEmailCommandTest.java rename to src/test/java/seedu/address/logic/commands/findcommand/FindEmailCommandTest.java index f29fed5b0d6..5152a38da1b 100644 --- a/src/test/java/seedu/address/logic/commands/FindEmailCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/findcommand/FindEmailCommandTest.java @@ -1,4 +1,4 @@ -package seedu.address.logic.commands; +package seedu.address.logic.commands.findcommand; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -18,8 +18,6 @@ import org.junit.jupiter.api.Test; -import seedu.address.logic.commands.findcommand.FindCommand; -import seedu.address.logic.commands.findcommand.FindEmailCommand; import seedu.address.model.Model; import seedu.address.model.ModelManager; import seedu.address.model.UserPrefs; diff --git a/src/test/java/seedu/address/logic/commands/FindNameCommandTest.java b/src/test/java/seedu/address/logic/commands/findcommand/FindNameCommandTest.java similarity index 97% rename from src/test/java/seedu/address/logic/commands/FindNameCommandTest.java rename to src/test/java/seedu/address/logic/commands/findcommand/FindNameCommandTest.java index d1b5ed103e9..21b61fd1964 100644 --- a/src/test/java/seedu/address/logic/commands/FindNameCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/findcommand/FindNameCommandTest.java @@ -1,4 +1,4 @@ -package seedu.address.logic.commands; +package seedu.address.logic.commands.findcommand; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -20,8 +20,6 @@ import org.junit.jupiter.api.Test; -import seedu.address.logic.commands.findcommand.FindCommand; -import seedu.address.logic.commands.findcommand.FindNameCommand; import seedu.address.model.Model; import seedu.address.model.ModelManager; import seedu.address.model.UserPrefs; diff --git a/src/test/java/seedu/address/logic/commands/FindPhoneCommandTest.java b/src/test/java/seedu/address/logic/commands/findcommand/FindPhoneCommandTest.java similarity index 97% rename from src/test/java/seedu/address/logic/commands/FindPhoneCommandTest.java rename to src/test/java/seedu/address/logic/commands/findcommand/FindPhoneCommandTest.java index 963a231e0da..5a15899bc19 100644 --- a/src/test/java/seedu/address/logic/commands/FindPhoneCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/findcommand/FindPhoneCommandTest.java @@ -1,4 +1,4 @@ -package seedu.address.logic.commands; +package seedu.address.logic.commands.findcommand; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -20,8 +20,6 @@ import org.junit.jupiter.api.Test; -import seedu.address.logic.commands.findcommand.FindCommand; -import seedu.address.logic.commands.findcommand.FindPhoneCommand; import seedu.address.model.Model; import seedu.address.model.ModelManager; import seedu.address.model.UserPrefs; diff --git a/src/test/java/seedu/address/logic/commands/FindTagCommandTest.java b/src/test/java/seedu/address/logic/commands/findcommand/FindTagCommandTest.java similarity index 97% rename from src/test/java/seedu/address/logic/commands/FindTagCommandTest.java rename to src/test/java/seedu/address/logic/commands/findcommand/FindTagCommandTest.java index 77830c16045..fce9c291f01 100644 --- a/src/test/java/seedu/address/logic/commands/FindTagCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/findcommand/FindTagCommandTest.java @@ -1,4 +1,4 @@ -package seedu.address.logic.commands; +package seedu.address.logic.commands.findcommand; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -16,7 +16,6 @@ import org.junit.jupiter.api.Test; -import seedu.address.logic.commands.findcommand.FindTagCommand; import seedu.address.model.Model; import seedu.address.model.ModelManager; import seedu.address.model.UserPrefs; diff --git a/src/test/java/seedu/address/model/person/AddressContainsKeywordsPredicateTest.java b/src/test/java/seedu/address/model/person/keywordspredicate/AddressContainsKeywordsPredicateTest.java similarity index 96% rename from src/test/java/seedu/address/model/person/AddressContainsKeywordsPredicateTest.java rename to src/test/java/seedu/address/model/person/keywordspredicate/AddressContainsKeywordsPredicateTest.java index 9865f8961a6..98c8578c60c 100644 --- a/src/test/java/seedu/address/model/person/AddressContainsKeywordsPredicateTest.java +++ b/src/test/java/seedu/address/model/person/keywordspredicate/AddressContainsKeywordsPredicateTest.java @@ -1,4 +1,4 @@ -package seedu.address.model.person; +package seedu.address.model.person.keywordspredicate; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -10,7 +10,6 @@ import org.junit.jupiter.api.Test; -import seedu.address.model.person.keywordspredicate.AddressContainsKeywordsPredicate; import seedu.address.testutil.PersonBuilder; public class AddressContainsKeywordsPredicateTest { diff --git a/src/test/java/seedu/address/model/person/EmailContainsKeywordsPredicateTest.java b/src/test/java/seedu/address/model/person/keywordspredicate/EmailContainsKeywordsPredicateTest.java similarity index 96% rename from src/test/java/seedu/address/model/person/EmailContainsKeywordsPredicateTest.java rename to src/test/java/seedu/address/model/person/keywordspredicate/EmailContainsKeywordsPredicateTest.java index bbc9f6b4670..2c01a5c47d6 100644 --- a/src/test/java/seedu/address/model/person/EmailContainsKeywordsPredicateTest.java +++ b/src/test/java/seedu/address/model/person/keywordspredicate/EmailContainsKeywordsPredicateTest.java @@ -1,4 +1,4 @@ -package seedu.address.model.person; +package seedu.address.model.person.keywordspredicate; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -10,7 +10,6 @@ import org.junit.jupiter.api.Test; -import seedu.address.model.person.keywordspredicate.EmailContainsKeywordsPredicate; import seedu.address.testutil.PersonBuilder; public class EmailContainsKeywordsPredicateTest { diff --git a/src/test/java/seedu/address/model/person/NameContainsKeywordsPredicateTest.java b/src/test/java/seedu/address/model/person/keywordspredicate/NameContainsKeywordsPredicateTest.java similarity index 96% rename from src/test/java/seedu/address/model/person/NameContainsKeywordsPredicateTest.java rename to src/test/java/seedu/address/model/person/keywordspredicate/NameContainsKeywordsPredicateTest.java index 466c78d1fbf..83bb7d247a8 100644 --- a/src/test/java/seedu/address/model/person/NameContainsKeywordsPredicateTest.java +++ b/src/test/java/seedu/address/model/person/keywordspredicate/NameContainsKeywordsPredicateTest.java @@ -1,4 +1,4 @@ -package seedu.address.model.person; +package seedu.address.model.person.keywordspredicate; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -10,7 +10,6 @@ import org.junit.jupiter.api.Test; -import seedu.address.model.person.keywordspredicate.NameContainsKeywordsPredicate; import seedu.address.testutil.PersonBuilder; public class NameContainsKeywordsPredicateTest { diff --git a/src/test/java/seedu/address/model/person/PhoneContainsKeywordsPredicateTest.java b/src/test/java/seedu/address/model/person/keywordspredicate/PhoneContainsKeywordsPredicateTest.java similarity index 96% rename from src/test/java/seedu/address/model/person/PhoneContainsKeywordsPredicateTest.java rename to src/test/java/seedu/address/model/person/keywordspredicate/PhoneContainsKeywordsPredicateTest.java index 124a7d40cd1..41b620cb45b 100644 --- a/src/test/java/seedu/address/model/person/PhoneContainsKeywordsPredicateTest.java +++ b/src/test/java/seedu/address/model/person/keywordspredicate/PhoneContainsKeywordsPredicateTest.java @@ -1,4 +1,4 @@ -package seedu.address.model.person; +package seedu.address.model.person.keywordspredicate; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -10,7 +10,6 @@ import org.junit.jupiter.api.Test; -import seedu.address.model.person.keywordspredicate.PhoneContainsKeywordsPredicate; import seedu.address.testutil.PersonBuilder; public class PhoneContainsKeywordsPredicateTest { diff --git a/src/test/java/seedu/address/model/person/keywordspredicate/TagContainsKeywordsPredicateTest.java b/src/test/java/seedu/address/model/person/keywordspredicate/TagContainsKeywordsPredicateTest.java new file mode 100644 index 00000000000..78bb4242d1a --- /dev/null +++ b/src/test/java/seedu/address/model/person/keywordspredicate/TagContainsKeywordsPredicateTest.java @@ -0,0 +1,69 @@ +package seedu.address.model.person.keywordspredicate; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Arrays; +import java.util.Collections; + +import org.junit.jupiter.api.Test; + +import seedu.address.model.tag.Tag; +import seedu.address.model.tag.TagName; + +public class TagContainsKeywordsPredicateTest { + + @Test + public void equals() { + // Test same object -> returns true + TagContainsKeywordsPredicate firstPredicate = + new TagContainsKeywordsPredicate(Collections.singletonList("photo")); + assertEquals(firstPredicate, firstPredicate); + + // Test null -> returns false + assertNotEquals(null, firstPredicate); + + // Test different types -> returns false + assertNotEquals(5, firstPredicate); + + // Test different predicates -> returns false + TagContainsKeywordsPredicate secondPredicate = + new TagContainsKeywordsPredicate(Collections.singletonList("rural")); + assertNotEquals(firstPredicate, secondPredicate); + + // Test same predicate with same keyword -> returns true + TagContainsKeywordsPredicate firstPredicateCopy = + new TagContainsKeywordsPredicate(Collections.singletonList("photo")); + assertEquals(firstPredicate, firstPredicateCopy); + } + + @Test + public void test_tagContainsKeywords() { + // One keyword that fully matches the tag + TagContainsKeywordsPredicate predicate = + new TagContainsKeywordsPredicate(Collections.singletonList("photographer")); + assertTrue(predicate.test(new Tag(new TagName("Photographer")))); + + // One keyword that partially matches the tag + predicate = new TagContainsKeywordsPredicate(Collections.singletonList("photo")); + assertTrue(predicate.test(new Tag(new TagName("Photographer")))); + + // Multiple keywords, one matches partially + predicate = new TagContainsKeywordsPredicate(Arrays.asList("Photographer", "Venue Planner")); + assertTrue(predicate.test(new Tag(new TagName("Photographer")))); + + // Multiple keywords, none match + predicate = new TagContainsKeywordsPredicate(Arrays.asList("florist", "venue")); + assertFalse(predicate.test(new Tag(new TagName("Photographer")))); + + // Test case-insensitive match + predicate = new TagContainsKeywordsPredicate(Collections.singletonList("photo")); + assertTrue(predicate.test(new Tag(new TagName("Photographer")))); + + // Test no keywords -> should return false + predicate = new TagContainsKeywordsPredicate(Collections.emptyList()); + assertFalse(predicate.test(new Tag(new TagName("Photographer")))); + } +} From 2a65bdc66d66e98eaa51bb2cf92c7f7d366a2203 Mon Sep 17 00:00:00 2001 From: Han Bin Date: Thu, 17 Oct 2024 01:48:21 +0800 Subject: [PATCH 22/33] Add tests for AssignWeddingCommand.java Add tests for AssignWeddingCommand. --- .../java/seedu/address/logic/Messages.java | 1 + .../address/logic/commands/EditCommand.java | 4 +- .../commands/UnassignWeddingCommand.java | 3 +- .../typicalPersonsAddressBook.json | 3 +- .../commands/AssignWeddingCommandTest.java | 94 +++++++++++++++++++ .../commands/UnassignWeddingCommandTest.java | 9 +- .../address/testutil/TypicalPersons.java | 3 +- 7 files changed, 106 insertions(+), 11 deletions(-) create mode 100644 src/test/java/seedu/address/logic/commands/AssignWeddingCommandTest.java diff --git a/src/main/java/seedu/address/logic/Messages.java b/src/main/java/seedu/address/logic/Messages.java index a0ac28f383d..aa244dac89b 100644 --- a/src/main/java/seedu/address/logic/Messages.java +++ b/src/main/java/seedu/address/logic/Messages.java @@ -25,6 +25,7 @@ public class Messages { public static final String MESSAGE_TAG_NOT_FOUND_IN_CONTACT = "Some tags were not found in the person's tag list."; public static final String MESSAGE_ADD_TAG_SUCCESS = "Added tag(s) %1$s to %2$s."; public static final String MESSAGE_ADD_WEDDING_SUCCESS = "Added wedding(s) %1$s to %2$s."; + public static final String MESSAGE_REMOVE_WEDDING_SUCCESS = "Removed wedding(s) %1$s from %2$s."; public static final String MESSAGE_WEDDING_NOT_FOUND = "One or more specified weddings do not exist in " + "the Wedlinker."; public static final String MESSAGE_WEDDING_NOT_FOUND_IN_CONTACT = "Some weddings were not found in " diff --git a/src/main/java/seedu/address/logic/commands/EditCommand.java b/src/main/java/seedu/address/logic/commands/EditCommand.java index d930d1d5581..328ec7190da 100644 --- a/src/main/java/seedu/address/logic/commands/EditCommand.java +++ b/src/main/java/seedu/address/logic/commands/EditCommand.java @@ -201,7 +201,7 @@ public Optional
getAddress() { * A defensive copy of {@code tags} is used internally. */ public void setTags(Set tags) { - this.tags = (tags != null) ? new HashSet<>(tags) : new HashSet<>(); + this.tags = (tags != null) ? new HashSet<>(tags) : null; } /** @@ -218,7 +218,7 @@ public Optional> getTags() { * A defensive copy of {@code weddings} is used internally. */ public void setWeddings(Set weddings) { - this.weddings = (weddings != null) ? new HashSet<>(weddings) : new HashSet<>(); + this.weddings = (weddings != null) ? new HashSet<>(weddings) : null; } /** diff --git a/src/main/java/seedu/address/logic/commands/UnassignWeddingCommand.java b/src/main/java/seedu/address/logic/commands/UnassignWeddingCommand.java index 480b0849a02..9c39bfbbeaf 100644 --- a/src/main/java/seedu/address/logic/commands/UnassignWeddingCommand.java +++ b/src/main/java/seedu/address/logic/commands/UnassignWeddingCommand.java @@ -1,6 +1,7 @@ package seedu.address.logic.commands; import static seedu.address.logic.Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX; +import static seedu.address.logic.Messages.MESSAGE_REMOVE_WEDDING_SUCCESS; import static seedu.address.logic.Messages.MESSAGE_WEDDING_NOT_FOUND_IN_CONTACT; import java.util.HashSet; @@ -19,7 +20,7 @@ */ public class UnassignWeddingCommand extends Command { public static final String COMMAND_WORD = "unassign-wedding"; - public static final String MESSAGE_REMOVE_WEDDING_SUCCESS = "Removed wedding(s) %1$s from %2$s."; + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Removes one or multiple weddings from the person identified " diff --git a/src/test/data/JsonSerializableAddressBookTest/typicalPersonsAddressBook.json b/src/test/data/JsonSerializableAddressBookTest/typicalPersonsAddressBook.json index 6ed28d78ed6..323f6d95174 100644 --- a/src/test/data/JsonSerializableAddressBookTest/typicalPersonsAddressBook.json +++ b/src/test/data/JsonSerializableAddressBookTest/typicalPersonsAddressBook.json @@ -5,8 +5,7 @@ "phone" : "94351253", "email" : "alice@example.com", "address" : "123, Jurong West Ave 6, #08-111", - "tags" : [ "friends" ], - "weddings": ["Amy's Wedding"] + "tags" : [ "friends" ] }, { "name" : "Benson Meier", "phone" : "98765432", diff --git a/src/test/java/seedu/address/logic/commands/AssignWeddingCommandTest.java b/src/test/java/seedu/address/logic/commands/AssignWeddingCommandTest.java new file mode 100644 index 00000000000..005fb16d4fe --- /dev/null +++ b/src/test/java/seedu/address/logic/commands/AssignWeddingCommandTest.java @@ -0,0 +1,94 @@ +package seedu.address.logic.commands; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; +import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON; +import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; +import static seedu.address.testutil.TypicalWeddings.AMY_WEDDING; +import static seedu.address.testutil.TypicalWeddings.BOB_WEDDING; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import org.junit.jupiter.api.Test; + +import seedu.address.logic.Messages; +import seedu.address.model.Model; +import seedu.address.model.ModelManager; +import seedu.address.model.UserPrefs; +import seedu.address.model.person.Person; +import seedu.address.model.wedding.Wedding; +import seedu.address.model.wedding.WeddingName; + +public class AssignWeddingCommandTest { + private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + + @Test + public void assignWedding_success() { + Person personToEdit = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); + HashSet weddingsToAdd = new HashSet<>(Arrays.asList(AMY_WEDDING)); + + AssignWeddingCommand assignWeddingCommand = new AssignWeddingCommand( + INDEX_FIRST_PERSON, weddingsToAdd); + + String expectedMessage = String.format(Messages.MESSAGE_ADD_WEDDING_SUCCESS, "Amy's Wedding", + personToEdit.getName().toString()); + + Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); + Set updatedWeddings = new HashSet<>(personToEdit.getWeddings()); + updatedWeddings.addAll(weddingsToAdd); + Person editedPerson = new Person( + personToEdit.getName(), + personToEdit.getPhone(), + personToEdit.getEmail(), + personToEdit.getAddress(), + personToEdit.getTags(), + updatedWeddings); + expectedModel.setPerson(personToEdit, editedPerson); + + CommandTestUtil.assertCommandSuccess(assignWeddingCommand, model, expectedMessage, expectedModel); + } + + @Test + public void assignWeddingZeroWeddings_fail() { + Wedding unseenWedding = new Wedding(new WeddingName("UNKNOWN WEDDING")); + HashSet weddingsToAdd = new HashSet<>(Arrays.asList(unseenWedding)); + AssignWeddingCommand assignWeddingCommand = new AssignWeddingCommand( + INDEX_FIRST_PERSON, weddingsToAdd); + String expectedMessage = Messages.MESSAGE_WEDDING_NOT_FOUND; + CommandTestUtil.assertCommandFailure(assignWeddingCommand, model, expectedMessage); + } + + @Test + public void sameCommandTest_success() { + HashSet weddingsToRemove = new HashSet<>(Arrays.asList(BOB_WEDDING)); + AssignWeddingCommand command1 = new AssignWeddingCommand(INDEX_FIRST_PERSON, weddingsToRemove); + assertTrue(command1.equals(command1)); + } + + @Test + public void differentCommandType_fail() { + HashSet weddingsToRemove = new HashSet<>(); + AssignWeddingCommand command1 = new AssignWeddingCommand(INDEX_FIRST_PERSON, weddingsToRemove); + assertFalse(command1.equals(null)); + } + + @Test + public void differentIndex_fail() { + HashSet weddingsToRemove = new HashSet<>(); + AssignWeddingCommand command1 = new AssignWeddingCommand(INDEX_FIRST_PERSON, weddingsToRemove); + AssignWeddingCommand command2 = new AssignWeddingCommand(INDEX_SECOND_PERSON, weddingsToRemove); + assertFalse(command1.equals(command2)); + } + + @Test + public void differentWeddings_fail() { + HashSet weddingsToRemove1 = new HashSet<>(); + HashSet weddingsToRemove2 = new HashSet<>(Arrays.asList(AMY_WEDDING)); + AssignWeddingCommand command1 = new AssignWeddingCommand(INDEX_FIRST_PERSON, weddingsToRemove1); + AssignWeddingCommand command2 = new AssignWeddingCommand(INDEX_SECOND_PERSON, weddingsToRemove2); + assertFalse(command1.equals(command2)); + } +} diff --git a/src/test/java/seedu/address/logic/commands/UnassignWeddingCommandTest.java b/src/test/java/seedu/address/logic/commands/UnassignWeddingCommandTest.java index d5926b38a71..df0793a5819 100644 --- a/src/test/java/seedu/address/logic/commands/UnassignWeddingCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/UnassignWeddingCommandTest.java @@ -20,19 +20,20 @@ import seedu.address.model.UserPrefs; import seedu.address.model.person.Person; import seedu.address.model.wedding.Wedding; +import seedu.address.model.wedding.WeddingName; public class UnassignWeddingCommandTest { private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); @Test public void unassignWedding_success() { - Person personToEdit = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); - HashSet weddingsToRemove = new HashSet<>(Arrays.asList(AMY_WEDDING)); + Person personToEdit = model.getFilteredPersonList().get(INDEX_SECOND_PERSON.getZeroBased()); + HashSet weddingsToRemove = new HashSet<>(Arrays.asList(new Wedding(new WeddingName("Wedding 2")))); UnassignWeddingCommand unassignWeddingCommand = new UnassignWeddingCommand( - INDEX_FIRST_PERSON, weddingsToRemove); + INDEX_SECOND_PERSON, weddingsToRemove); - String expectedMessage = String.format(UnassignWeddingCommand.MESSAGE_REMOVE_WEDDING_SUCCESS, "Amy's Wedding", + String expectedMessage = String.format(Messages.MESSAGE_REMOVE_WEDDING_SUCCESS, "Wedding 2", personToEdit.getName().toString()); Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); diff --git a/src/test/java/seedu/address/testutil/TypicalPersons.java b/src/test/java/seedu/address/testutil/TypicalPersons.java index b91084289e0..712f733df21 100644 --- a/src/test/java/seedu/address/testutil/TypicalPersons.java +++ b/src/test/java/seedu/address/testutil/TypicalPersons.java @@ -43,8 +43,7 @@ public class TypicalPersons { public static final Person ALICE = new PersonBuilder().withName("Alice Pauline") .withAddress("123, Jurong West Ave 6, #08-111").withEmail("alice@example.com") .withPhone("94351253") - .withTags("friends") - .withWeddings("Amy's Wedding").build(); + .withTags("friends").build(); public static final Person BENSON = new PersonBuilder().withName("Benson Meier") .withAddress("311, Clementi Ave 2, #02-25") .withEmail("johnd@example.com").withPhone("98765432") From 4ca324935ac59283677b1f3558c601d19af59e56 Mon Sep 17 00:00:00 2001 From: Han Bin Date: Thu, 17 Oct 2024 05:18:23 +0800 Subject: [PATCH 23/33] Add tests for DeleteWeddingCommand.java Add tests for DeleteWeddingCommand. --- .../commands/DeleteWeddingCommandTest.java | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 src/test/java/seedu/address/logic/commands/DeleteWeddingCommandTest.java diff --git a/src/test/java/seedu/address/logic/commands/DeleteWeddingCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteWeddingCommandTest.java new file mode 100644 index 00000000000..e9f33db6dfd --- /dev/null +++ b/src/test/java/seedu/address/logic/commands/DeleteWeddingCommandTest.java @@ -0,0 +1,71 @@ +package seedu.address.logic.commands; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure; +import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; +import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; +import static seedu.address.testutil.TypicalWeddings.AMY_WEDDING; +import static seedu.address.testutil.TypicalWeddings.BOB_WEDDING; + +import org.junit.jupiter.api.Test; + +import seedu.address.logic.Messages; +import seedu.address.model.Model; +import seedu.address.model.ModelManager; +import seedu.address.model.UserPrefs; +import seedu.address.model.wedding.Wedding; + +public class DeleteWeddingCommandTest { + private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + + @Test + public void execute_validDeleteWeddingCommand_success() { + Wedding weddingToDelete = model.getFilteredWeddingList().get(0); + DeleteWeddingCommand deleteWeddingCommand = new DeleteWeddingCommand(weddingToDelete); + + String expectedMessage = String.format(DeleteWeddingCommand.MESSAGE_DELETE_WEDDING_SUCCESS, + Messages.format(weddingToDelete)); + + ModelManager expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); + expectedModel.deleteWedding(weddingToDelete); + + assertCommandSuccess(deleteWeddingCommand, model, expectedMessage, expectedModel); + } + + @Test void execute_invalidNotFoundDeleteWeddingCommand() { + Wedding weddingToDelete = model.getFilteredWeddingList().get(0); + + String expectedMessage = String.format(DeleteWeddingCommand.MESSAGE_DELETE_WEDDING_FAILURE_NOT_FOUND, + Messages.format(weddingToDelete)); + + ModelManager expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); + expectedModel.deleteWedding(weddingToDelete); + + DeleteWeddingCommand expectedDeleteWeddingCommand = new DeleteWeddingCommand(weddingToDelete); + + assertCommandFailure(expectedDeleteWeddingCommand, expectedModel, expectedMessage); + } + + @Test + public void equals() { + DeleteWeddingCommand deleteFloristWeddingCommand = new DeleteWeddingCommand(AMY_WEDDING); + DeleteWeddingCommand deletePhotographerWeddingCommandCopy = new DeleteWeddingCommand(BOB_WEDDING); + + // same object -> returns true + assertTrue(deleteFloristWeddingCommand.equals(deleteFloristWeddingCommand)); + + // same values -> returns true + DeleteWeddingCommand deleteFloristWeddingCommandCopy = new DeleteWeddingCommand(AMY_WEDDING); + assertTrue(deleteFloristWeddingCommand.equals(deleteFloristWeddingCommandCopy)); + + // different types -> return false + assertFalse(deleteFloristWeddingCommand.equals(1)); + + // null -> returns false + assertFalse(deleteFloristWeddingCommand.equals(null)); + + // different Wedding -> returns false + assertFalse(deleteFloristWeddingCommand.equals(deletePhotographerWeddingCommandCopy)); + } +} From f1ff1791a6ad0a572104721b21723cba4c604671 Mon Sep 17 00:00:00 2001 From: Han Bin Date: Thu, 17 Oct 2024 06:05:21 +0800 Subject: [PATCH 24/33] Add tests for CreateWeddingCommand.java Add tests for CreateWeddingCommand. --- .../commands/CreateWeddingCommandTest.java | 262 ++++++++++++++++++ 1 file changed, 262 insertions(+) create mode 100644 src/test/java/seedu/address/logic/commands/CreateWeddingCommandTest.java diff --git a/src/test/java/seedu/address/logic/commands/CreateWeddingCommandTest.java b/src/test/java/seedu/address/logic/commands/CreateWeddingCommandTest.java new file mode 100644 index 00000000000..1a013326843 --- /dev/null +++ b/src/test/java/seedu/address/logic/commands/CreateWeddingCommandTest.java @@ -0,0 +1,262 @@ +package seedu.address.logic.commands; + +import static java.util.Objects.requireNonNull; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static seedu.address.testutil.Assert.assertThrows; +import static seedu.address.testutil.TypicalWeddings.VALID_WEDDING_NAME_AMY_WEDDING; +import static seedu.address.testutil.TypicalWeddings.VALID_WEDDING_NAME_BOB_WEDDING; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.function.Predicate; + +import org.junit.jupiter.api.Test; + +import javafx.collections.ObservableList; +import seedu.address.commons.core.GuiSettings; +import seedu.address.logic.Messages; +import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.AddressBook; +import seedu.address.model.Model; +import seedu.address.model.ReadOnlyAddressBook; +import seedu.address.model.ReadOnlyUserPrefs; +import seedu.address.model.person.Person; +import seedu.address.model.tag.Tag; +import seedu.address.model.wedding.Wedding; + +public class CreateWeddingCommandTest { + + @Test + public void constructor_nullWedding_throwsNullPointerException() { + assertThrows(NullPointerException.class, () -> new CreateWeddingCommand(null)); + } + + @Test + public void execute_weddingAcceptedByModel_addSuccessful() throws Exception { + ModelStubAcceptingWeddingAdded modelStub = new ModelStubAcceptingWeddingAdded(); + Wedding validWedding = new Wedding(VALID_WEDDING_NAME_AMY_WEDDING); + + CommandResult commandResult = new CreateWeddingCommand(validWedding).execute(modelStub); + assertEquals(String.format(CreateWeddingCommand.MESSAGE_SUCCESS, Messages.format(validWedding)), + commandResult.getFeedbackToUser()); + assertEquals(Arrays.asList(validWedding), modelStub.weddingsAdded); + } + + @Test + public void execute_duplicateWedding_throwsCommandException() { + Wedding validWedding = new Wedding(VALID_WEDDING_NAME_AMY_WEDDING); + CreateWeddingCommand createWeddingCommand = new CreateWeddingCommand(validWedding); + ModelStub modelStub = new ModelStubWithWedding(validWedding); + + assertThrows(CommandException.class, + CreateWeddingCommand.MESSAGE_DUPLICATE_WEDDING, () -> createWeddingCommand.execute(modelStub)); + } + + @Test + public void equals() { + Wedding amyWedding = new Wedding(VALID_WEDDING_NAME_AMY_WEDDING); + Wedding bobWedding = new Wedding(VALID_WEDDING_NAME_BOB_WEDDING); + CreateWeddingCommand createAmyWeddingCommand = new CreateWeddingCommand(amyWedding); + CreateWeddingCommand createBobWeddingCommand = new CreateWeddingCommand(bobWedding); + + // same object -> returns ture + assertEquals(createAmyWeddingCommand, createAmyWeddingCommand); + + // same values -> returns false + CreateWeddingCommand createFloristCommandCopy = new CreateWeddingCommand(amyWedding); + assertEquals(createAmyWeddingCommand, createFloristCommandCopy); + + // different types -> returns false + assertFalse(createAmyWeddingCommand.equals(1)); + + // null -> return false + assertFalse(createAmyWeddingCommand.equals(null)); + + // different Wedding -> return false + assertFalse(createAmyWeddingCommand.equals(createBobWeddingCommand)); + } + + /** + * A default model stub that have all methods failing. + */ + private class ModelStub implements Model { + @Override + public void setUserPrefs(ReadOnlyUserPrefs userPrefs) { + throw new AssertionError("This method should not be called."); + } + + @Override + public ReadOnlyUserPrefs getUserPrefs() { + throw new AssertionError("This method should not be called."); + } + + @Override + public GuiSettings getGuiSettings() { + throw new AssertionError("This method should not be called."); + } + + @Override + public void setGuiSettings(GuiSettings guiSettings) { + throw new AssertionError("This method should not be called."); + } + + @Override + public Path getAddressBookFilePath() { + throw new AssertionError("This method should not be called."); + } + + @Override + public void setAddressBookFilePath(Path addressBookFilePath) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void addPerson(Person person) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void setAddressBook(ReadOnlyAddressBook newData) { + throw new AssertionError("This method should not be called."); + } + + @Override + public ReadOnlyAddressBook getAddressBook() { + throw new AssertionError("This method should not be called."); + } + + @Override + public boolean hasPerson(Person person) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void deletePerson(Person target) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void setPerson(Person target, Person editedPerson) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void setTag(Tag target, Tag editedWedding) { + throw new AssertionError("This method should not be called."); + } + + @Override + public ObservableList getFilteredPersonList() { + throw new AssertionError("This method should not be called."); + } + + @Override + public void updateFilteredPersonList(Predicate predicate) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void updateFilteredPersonListByTag(Predicate tagPredicate) { + throw new AssertionError("This method should not be called."); + } + + @Override + public boolean hasTag(Tag toAdd) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void addTag(Tag toAdd) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void updateFilteredTagList(Predicate predicate) { + throw new AssertionError("This method should not be called."); + } + + @Override + public boolean hasWedding(Wedding toAdd) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void addWedding(Wedding toAdd) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void setWedding(Wedding target, Wedding editedWedding) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void deleteTag(Tag tag) { + throw new AssertionError("This method should not be called."); + } + + + @Override + public ObservableList getFilteredTagList() { + throw new AssertionError("This method should not be called."); + } + @Override + public void updateFilteredWeddingList(Predicate predicate) { + throw new AssertionError("This method should not be called."); + } + + @Override + public ObservableList getFilteredWeddingList() { + throw new AssertionError("This method should not be called."); + } + + @Override + public void deleteWedding(Wedding wedding) { + throw new AssertionError("This method should not be called."); + } + } + + /** + * A Model stub that contains a single Wedding. + */ + private class ModelStubWithWedding extends CreateWeddingCommandTest.ModelStub { + private final Wedding wedding; + + ModelStubWithWedding(Wedding wedding) { + requireNonNull(wedding); + this.wedding = wedding; + } + + @Override + public boolean hasWedding(Wedding wedding) { + requireNonNull(wedding); + return this.wedding.isSameWedding(wedding); + } + } + + /** + * A Model stub that always accept the Wedding being added. + */ + private class ModelStubAcceptingWeddingAdded extends CreateWeddingCommandTest.ModelStub { + final ArrayList weddingsAdded = new ArrayList<>(); + + @Override + public boolean hasWedding(Wedding wedding) { + requireNonNull(wedding); + return weddingsAdded.stream().anyMatch(wedding::isSameWedding); + } + + @Override + public void addWedding(Wedding wedding) { + requireNonNull(wedding); + weddingsAdded.add(wedding); + } + + @Override + public ReadOnlyAddressBook getAddressBook() { + return new AddressBook(); + } + } +} From 9edb103cca3bbdd1af6c156cf0e0201260363990 Mon Sep 17 00:00:00 2001 From: Han Bin Date: Thu, 17 Oct 2024 06:35:36 +0800 Subject: [PATCH 25/33] Add feature force for Assign Wedding Add ability to force the assignment of wedding. Creates a new Wedding Object if the Wedding does not already exist when using force. --- .../logic/commands/AssignWeddingCommand.java | 14 +++++++++++++- .../logic/parser/AssignWeddingCommandParser.java | 10 ++++++++-- .../java/seedu/address/logic/parser/CliSyntax.java | 1 + 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/address/logic/commands/AssignWeddingCommand.java b/src/main/java/seedu/address/logic/commands/AssignWeddingCommand.java index 84d4fdf7ed3..291c0e46daf 100644 --- a/src/main/java/seedu/address/logic/commands/AssignWeddingCommand.java +++ b/src/main/java/seedu/address/logic/commands/AssignWeddingCommand.java @@ -32,6 +32,7 @@ public class AssignWeddingCommand extends Command { private final Index index; private final HashSet weddingsToAdd; + private boolean force = false; /** * Constructs a {@code AssignWedding} Command to add weddings to a person. @@ -43,6 +44,12 @@ public AssignWeddingCommand(Index index, HashSet weddingsToAdd) { this.weddingsToAdd = weddingsToAdd; } + public AssignWeddingCommand(Index index, HashSet weddingsToAdd, boolean force) { + this.index = index; + this.weddingsToAdd = weddingsToAdd; + this.force = force; + } + /** * Generates a command execution success message showing the added weddings and the person. * @@ -68,7 +75,12 @@ public CommandResult execute(Model model) throws CommandException { for (Wedding wedding : weddingsToAdd) { if (!model.hasWedding(wedding)) { - throw new CommandException(MESSAGE_WEDDING_NOT_FOUND); + if (this.force) { + CreateWeddingCommand newWedding = new CreateWeddingCommand(wedding); + newWedding.execute(model); + } else { + throw new CommandException(MESSAGE_WEDDING_NOT_FOUND); + } } } diff --git a/src/main/java/seedu/address/logic/parser/AssignWeddingCommandParser.java b/src/main/java/seedu/address/logic/parser/AssignWeddingCommandParser.java index d86c84f875b..06f3f555c89 100644 --- a/src/main/java/seedu/address/logic/parser/AssignWeddingCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/AssignWeddingCommandParser.java @@ -2,6 +2,7 @@ import static java.util.Objects.requireNonNull; import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static seedu.address.logic.parser.CliSyntax.PREFIX_FORCE; import static seedu.address.logic.parser.CliSyntax.PREFIX_WEDDING; import java.util.HashSet; @@ -32,7 +33,7 @@ public class AssignWeddingCommandParser implements Parser public AssignWeddingCommand parse(String args) throws ParseException { requireNonNull(args); - ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_WEDDING); + ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_WEDDING, PREFIX_FORCE); Index index; if (!arePrefixesPresent(argMultimap, PREFIX_WEDDING)) { @@ -63,7 +64,12 @@ public AssignWeddingCommand parse(String args) throws ParseException { .map(Wedding::new) .collect(Collectors.toList())); - return new AssignWeddingCommand(index, weddings); + if (arePrefixesPresent(argMultimap, PREFIX_FORCE)) { + return new AssignWeddingCommand(index, weddings, true); + } else { + return new AssignWeddingCommand(index, weddings); + } + } /** diff --git a/src/main/java/seedu/address/logic/parser/CliSyntax.java b/src/main/java/seedu/address/logic/parser/CliSyntax.java index 66d74a4997e..adc6af7988a 100644 --- a/src/main/java/seedu/address/logic/parser/CliSyntax.java +++ b/src/main/java/seedu/address/logic/parser/CliSyntax.java @@ -12,4 +12,5 @@ public class CliSyntax { public static final Prefix PREFIX_ADDRESS = new Prefix("a/"); public static final Prefix PREFIX_TAG = new Prefix("t/"); public static final Prefix PREFIX_WEDDING = new Prefix("w/"); + public static final Prefix PREFIX_FORCE = new Prefix("f/"); } From 0b628814f8b84b14f7b20baa29c08bf8e53c2a75 Mon Sep 17 00:00:00 2001 From: Han Bin Date: Thu, 17 Oct 2024 07:39:04 +0800 Subject: [PATCH 26/33] Add test for AssignWeddingCommandParser.java Add test for force functionality. --- .../parser/AssignWeddingCommandParserTest.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/test/java/seedu/address/logic/parser/AssignWeddingCommandParserTest.java b/src/test/java/seedu/address/logic/parser/AssignWeddingCommandParserTest.java index b73f119281a..8296b7c85dc 100644 --- a/src/test/java/seedu/address/logic/parser/AssignWeddingCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/AssignWeddingCommandParserTest.java @@ -56,4 +56,20 @@ public void parse_invalidArgs_throwsParseException() { assertParseFailure(parser, "1 w/ w/Jeslyn's_Wedding", WeddingName.MESSAGE_CONSTRAINTS); } + + @Test + public void parse_validArgsWithForce_returnsAssignWeddingCommand() { + Index targetIndex = Index.fromOneBased(1); + + // Expected weddings + Wedding wedding1 = new Wedding(new WeddingName("Jeslyn's Wedding")); + Wedding wedding2 = new Wedding(new WeddingName("Wedding April 17th 2025")); + + AssignWeddingCommand expectedCommand = new AssignWeddingCommand(targetIndex, + new HashSet<>(Arrays.asList(wedding1, wedding2)), true); + + String userInput = "1 w/Jeslyn's Wedding w/Wedding April 17th 2025 f/"; + + assertParseSuccess(parser, userInput, expectedCommand); + } } From 5705d04e7cad9a76d63bf76f71bee1038dc15aa7 Mon Sep 17 00:00:00 2001 From: Han Bin Date: Thu, 17 Oct 2024 07:46:58 +0800 Subject: [PATCH 27/33] Fix check style for AssignWeddingCommand.java Add javadoc to explain overloaded constructor. --- .../seedu/address/logic/commands/AssignWeddingCommand.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/seedu/address/logic/commands/AssignWeddingCommand.java b/src/main/java/seedu/address/logic/commands/AssignWeddingCommand.java index 291c0e46daf..a030692a1c6 100644 --- a/src/main/java/seedu/address/logic/commands/AssignWeddingCommand.java +++ b/src/main/java/seedu/address/logic/commands/AssignWeddingCommand.java @@ -44,6 +44,12 @@ public AssignWeddingCommand(Index index, HashSet weddingsToAdd) { this.weddingsToAdd = weddingsToAdd; } + /** + * Constructs a {@code AssignWedding} Command to add weddings to a person with the force flag. + * @param index The index of the person in the person list. + * @param weddingsToAdd The list of weddings to be added. + * @param force Whether the command should force the assignment by creating the Wedding object. + */ public AssignWeddingCommand(Index index, HashSet weddingsToAdd, boolean force) { this.index = index; this.weddingsToAdd = weddingsToAdd; From bcebfd06f0269b2f8c0da068612489239f17e9c7 Mon Sep 17 00:00:00 2001 From: Han Bin Date: Thu, 17 Oct 2024 07:52:07 +0800 Subject: [PATCH 28/33] Add test for AssignWeddingCommandTest.java Add test to test for force functionality in AssignWeddingCommand. --- .../logic/commands/AssignWeddingCommandTest.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/test/java/seedu/address/logic/commands/AssignWeddingCommandTest.java b/src/test/java/seedu/address/logic/commands/AssignWeddingCommandTest.java index 005fb16d4fe..f7a72543255 100644 --- a/src/test/java/seedu/address/logic/commands/AssignWeddingCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AssignWeddingCommandTest.java @@ -91,4 +91,19 @@ public void differentWeddings_fail() { AssignWeddingCommand command2 = new AssignWeddingCommand(INDEX_SECOND_PERSON, weddingsToRemove2); assertFalse(command1.equals(command2)); } + + @Test + public void forceAssignWedding_success() { + Person personToEdit = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); + Wedding unseenWedding = new Wedding(new WeddingName("UNKNOWN WEDDING")); + HashSet weddingsToAdd = new HashSet<>(Arrays.asList(unseenWedding)); + AssignWeddingCommand assignWeddingCommand = new AssignWeddingCommand( + INDEX_FIRST_PERSON, weddingsToAdd, true); + String expectedMessage = String.format( + Messages.MESSAGE_ADD_WEDDING_SUCCESS, + unseenWedding.getWeddingName().toString(), + personToEdit.getName().toString()); + CommandTestUtil.assertCommandSuccess(assignWeddingCommand, model, expectedMessage, model); + + } } From f1662cfb1151896bcf4a1127749985149b134f6c Mon Sep 17 00:00:00 2001 From: Han Bin Date: Thu, 17 Oct 2024 18:32:28 +0800 Subject: [PATCH 29/33] Remove redundant method in UniqueWeddingList.java Remove setTag from UniqueWeddingList.java. --- .../java/seedu/address/model/wedding/UniqueWeddingList.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/main/java/seedu/address/model/wedding/UniqueWeddingList.java b/src/main/java/seedu/address/model/wedding/UniqueWeddingList.java index f21850e55c9..f505573430b 100644 --- a/src/main/java/seedu/address/model/wedding/UniqueWeddingList.java +++ b/src/main/java/seedu/address/model/wedding/UniqueWeddingList.java @@ -67,11 +67,6 @@ public void setWedding(Wedding target, Wedding editedWedding) { internalList.set(index, editedWedding); } - public void setTag(UniqueWeddingList replacement) { - requireNonNull(replacement); - internalList.setAll(replacement.internalList); - } - /** * Removes the equivalent wedding from the list. * The wedding must exist in the list. From f293c13880e1f14bcf89812ad357f565cc760f8a Mon Sep 17 00:00:00 2001 From: Han Bin Date: Thu, 17 Oct 2024 18:37:58 +0800 Subject: [PATCH 30/33] Fix bug in Test class Bug fix for compatibility with Weddings in EditPersonDescriptorBuilder.java. --- .../seedu/address/testutil/EditPersonDescriptorBuilder.java | 2 +- src/test/java/seedu/address/testutil/PersonUtil.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java b/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java index 56e8970dc00..bc7fb68d2e0 100644 --- a/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java +++ b/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java @@ -41,7 +41,7 @@ public EditPersonDescriptorBuilder(Person person) { descriptor.setAddress(person.getAddress()); descriptor.setTags(person.getTags()); // Figure out why this is not possible - //descriptor.setWeddings(person.getWeddings()); + descriptor.setWeddings(person.getWeddings()); } /** diff --git a/src/test/java/seedu/address/testutil/PersonUtil.java b/src/test/java/seedu/address/testutil/PersonUtil.java index 8628a0f31c9..699f7f266fb 100644 --- a/src/test/java/seedu/address/testutil/PersonUtil.java +++ b/src/test/java/seedu/address/testutil/PersonUtil.java @@ -62,6 +62,7 @@ public static String getEditPersonDescriptorDetails(EditPersonDescriptor descrip tags.forEach(s -> sb.append(PREFIX_TAG).append(s.getTagName()).append(" ")); } } + sb.append(" "); if (descriptor.getWeddings().isPresent()) { Set weddings = descriptor.getWeddings().get(); if (weddings.isEmpty()) { From d0f5987eea1f6b0161e8af39bf1317f67a993d4e Mon Sep 17 00:00:00 2001 From: Han Bin Date: Thu, 17 Oct 2024 18:46:33 +0800 Subject: [PATCH 31/33] Add Message prompt for Force functionality Add Message to instruct users on Force functionality in AssignWeddingCommand --- src/main/java/seedu/address/logic/Messages.java | 2 ++ .../seedu/address/logic/commands/AssignWeddingCommand.java | 4 +++- .../address/logic/commands/AssignWeddingCommandTest.java | 3 ++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/address/logic/Messages.java b/src/main/java/seedu/address/logic/Messages.java index cc7799e3a1a..6d4eb530dd4 100644 --- a/src/main/java/seedu/address/logic/Messages.java +++ b/src/main/java/seedu/address/logic/Messages.java @@ -30,6 +30,8 @@ public class Messages { + "the Wedlinker."; public static final String MESSAGE_WEDDING_NOT_FOUND_IN_CONTACT = "Some weddings were not found in " + "the person's wedding list."; + public static final String MESSAGE_FORCE_ASSIGN_WEDDING_TO_CONTACT = "Use f/ to force the assignment of wedding(s)." + + " This will create the required Wedding objects."; /** * Returns an error message indicating the duplicate prefixes. diff --git a/src/main/java/seedu/address/logic/commands/AssignWeddingCommand.java b/src/main/java/seedu/address/logic/commands/AssignWeddingCommand.java index 16dbfc19c34..8daaee7721d 100644 --- a/src/main/java/seedu/address/logic/commands/AssignWeddingCommand.java +++ b/src/main/java/seedu/address/logic/commands/AssignWeddingCommand.java @@ -1,6 +1,7 @@ package seedu.address.logic.commands; import static seedu.address.logic.Messages.MESSAGE_ADD_WEDDING_SUCCESS; +import static seedu.address.logic.Messages.MESSAGE_FORCE_ASSIGN_WEDDING_TO_CONTACT; import static seedu.address.logic.Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX; import static seedu.address.logic.Messages.MESSAGE_WEDDING_NOT_FOUND; @@ -86,7 +87,8 @@ public CommandResult execute(Model model) throws CommandException { CreateWeddingCommand newWedding = new CreateWeddingCommand(wedding); newWedding.execute(model); } else { - throw new CommandException(MESSAGE_WEDDING_NOT_FOUND); + throw new CommandException( + MESSAGE_WEDDING_NOT_FOUND + "\n" + MESSAGE_FORCE_ASSIGN_WEDDING_TO_CONTACT); } } } diff --git a/src/test/java/seedu/address/logic/commands/AssignWeddingCommandTest.java b/src/test/java/seedu/address/logic/commands/AssignWeddingCommandTest.java index f7a72543255..80b93ccc7bc 100644 --- a/src/test/java/seedu/address/logic/commands/AssignWeddingCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AssignWeddingCommandTest.java @@ -57,7 +57,8 @@ public void assignWeddingZeroWeddings_fail() { HashSet weddingsToAdd = new HashSet<>(Arrays.asList(unseenWedding)); AssignWeddingCommand assignWeddingCommand = new AssignWeddingCommand( INDEX_FIRST_PERSON, weddingsToAdd); - String expectedMessage = Messages.MESSAGE_WEDDING_NOT_FOUND; + String expectedMessage = Messages.MESSAGE_WEDDING_NOT_FOUND + "\n" + + Messages.MESSAGE_FORCE_ASSIGN_WEDDING_TO_CONTACT; CommandTestUtil.assertCommandFailure(assignWeddingCommand, model, expectedMessage); } From f50bc2662ba44874ea47f98fdfa0bfe00695a4a8 Mon Sep 17 00:00:00 2001 From: Han Bin Date: Thu, 17 Oct 2024 18:55:13 +0800 Subject: [PATCH 32/33] Edit variable naming in AssignWeddingCommandTest.java Rename newWedding to newWeddingCommand. --- .../seedu/address/logic/commands/AssignWeddingCommand.java | 4 ++-- .../address/logic/commands/DeleteWeddingCommandTest.java | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/address/logic/commands/AssignWeddingCommand.java b/src/main/java/seedu/address/logic/commands/AssignWeddingCommand.java index 8daaee7721d..365295183cf 100644 --- a/src/main/java/seedu/address/logic/commands/AssignWeddingCommand.java +++ b/src/main/java/seedu/address/logic/commands/AssignWeddingCommand.java @@ -84,8 +84,8 @@ public CommandResult execute(Model model) throws CommandException { for (Wedding wedding : weddingsToAdd) { if (!model.hasWedding(wedding)) { if (this.force) { - CreateWeddingCommand newWedding = new CreateWeddingCommand(wedding); - newWedding.execute(model); + CreateWeddingCommand newWeddingCommand = new CreateWeddingCommand(wedding); + newWeddingCommand.execute(model); } else { throw new CommandException( MESSAGE_WEDDING_NOT_FOUND + "\n" + MESSAGE_FORCE_ASSIGN_WEDDING_TO_CONTACT); diff --git a/src/test/java/seedu/address/logic/commands/DeleteWeddingCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteWeddingCommandTest.java index e9f33db6dfd..7be526db9c3 100644 --- a/src/test/java/seedu/address/logic/commands/DeleteWeddingCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/DeleteWeddingCommandTest.java @@ -33,7 +33,8 @@ public void execute_validDeleteWeddingCommand_success() { assertCommandSuccess(deleteWeddingCommand, model, expectedMessage, expectedModel); } - @Test void execute_invalidNotFoundDeleteWeddingCommand() { + @Test + public void execute_invalidNotFoundDeleteWeddingCommand() { Wedding weddingToDelete = model.getFilteredWeddingList().get(0); String expectedMessage = String.format(DeleteWeddingCommand.MESSAGE_DELETE_WEDDING_FAILURE_NOT_FOUND, From 5f87c914ba50d4cce38a3d11399829c1db7a6f04 Mon Sep 17 00:00:00 2001 From: Ricco Lim Date: Thu, 17 Oct 2024 20:55:27 +0800 Subject: [PATCH 33/33] CodeCoverage --- .../commands/findcommand/FindCommand.java | 15 +---------- .../TraitContainsKeywordsPredicate.java | 13 +--------- .../logic/parser/FindCommandParserTest.java | 25 +++++++++++++++++++ .../TagContainsKeywordsPredicateTest.java | 4 +-- 4 files changed, 29 insertions(+), 28 deletions(-) diff --git a/src/main/java/seedu/address/logic/commands/findcommand/FindCommand.java b/src/main/java/seedu/address/logic/commands/findcommand/FindCommand.java index ce9a23bd9a5..282131e5464 100644 --- a/src/main/java/seedu/address/logic/commands/findcommand/FindCommand.java +++ b/src/main/java/seedu/address/logic/commands/findcommand/FindCommand.java @@ -23,8 +23,6 @@ public abstract class FindCommand extends Command { + "Parameters: PREFIX/ KEYWORDS [MORE_KEYWORDS]...\n" + "Example: " + COMMAND_WORD + " " + PREFIX_NAME + " alice charlie"; - public static final String MESSAGE_FIND_PERSON_SUCCESS = "Search for \"%s\" was successful. Showing results:"; - public static final String MESSAGE_FIND_PERSON_UNSUCCESSFUL = "No contacts found."; protected final TraitContainsKeywordsPredicate predicate; @@ -37,18 +35,7 @@ public FindCommand(TraitContainsKeywordsPredicate predicate) { public abstract CommandResult execute(Model model); @Override - public boolean equals(Object other) { - if (other == this) { - return true; - } - - // instanceof handles nulls - if (!(other instanceof FindCommand otherFindCommand)) { - return false; - } - - return predicate.equals(otherFindCommand.predicate); - } + public abstract boolean equals(Object other); @Override public String toString() { diff --git a/src/main/java/seedu/address/model/person/keywordspredicate/TraitContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/person/keywordspredicate/TraitContainsKeywordsPredicate.java index 47592039df8..48542b82af7 100644 --- a/src/main/java/seedu/address/model/person/keywordspredicate/TraitContainsKeywordsPredicate.java +++ b/src/main/java/seedu/address/model/person/keywordspredicate/TraitContainsKeywordsPredicate.java @@ -18,18 +18,7 @@ public TraitContainsKeywordsPredicate(List keywords) { public abstract boolean test(T t); @Override - public boolean equals(Object other) { - if (other == this) { - return true; - } - - // instanceof handles nulls - if (!(other instanceof TraitContainsKeywordsPredicate otherNameContainsKeywordsPredicate)) { - return false; - } - - return keywords.equals(otherNameContainsKeywordsPredicate.keywords); - } + public abstract boolean equals(Object other); @Override public String toString() { diff --git a/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java b/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java index 263e92ffb0c..717d0b96642 100644 --- a/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java @@ -15,11 +15,13 @@ import seedu.address.logic.commands.findcommand.FindEmailCommand; import seedu.address.logic.commands.findcommand.FindNameCommand; import seedu.address.logic.commands.findcommand.FindPhoneCommand; +import seedu.address.logic.commands.findcommand.FindTagCommand; import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.person.keywordspredicate.AddressContainsKeywordsPredicate; import seedu.address.model.person.keywordspredicate.EmailContainsKeywordsPredicate; import seedu.address.model.person.keywordspredicate.NameContainsKeywordsPredicate; import seedu.address.model.person.keywordspredicate.PhoneContainsKeywordsPredicate; +import seedu.address.model.person.keywordspredicate.TagContainsKeywordsPredicate; public class FindCommandParserTest { @@ -174,4 +176,27 @@ public void parse_missingEmailWithTrailingWhiteSpace_throwsParseException() { assertEquals("Email address cannot be empty!", thrown.getMessage()); } + @Test + public void parse_validFindTagArgs_returnsFindTagCommand() { + // no leading and trailing whitespaces + FindTagCommand expectedFindCommand = + new FindTagCommand(new TagContainsKeywordsPredicate(Arrays.asList("florist"))); + assertParseSuccess(parser, "find t/florist", expectedFindCommand); + + // multiple whitespaces between keywords + assertParseSuccess(parser, "find t/ \t florist", expectedFindCommand); + } + + @Test + public void parse_missingTagAfterPrefix_throwsParseException() { + String input = "find t/"; // Nothing after tag prefix + ParseException thrown = assertThrows(ParseException.class, () -> { + parser.parse(input); + }); + + // Check for correct error message + assertEquals("Tag cannot be empty!", thrown.getMessage()); + + } + } diff --git a/src/test/java/seedu/address/model/person/keywordspredicate/TagContainsKeywordsPredicateTest.java b/src/test/java/seedu/address/model/person/keywordspredicate/TagContainsKeywordsPredicateTest.java index 78bb4242d1a..78e1210c908 100644 --- a/src/test/java/seedu/address/model/person/keywordspredicate/TagContainsKeywordsPredicateTest.java +++ b/src/test/java/seedu/address/model/person/keywordspredicate/TagContainsKeywordsPredicateTest.java @@ -23,14 +23,14 @@ public void equals() { assertEquals(firstPredicate, firstPredicate); // Test null -> returns false - assertNotEquals(null, firstPredicate); + assertFalse(firstPredicate.equals(null)); // Test different types -> returns false assertNotEquals(5, firstPredicate); // Test different predicates -> returns false TagContainsKeywordsPredicate secondPredicate = - new TagContainsKeywordsPredicate(Collections.singletonList("rural")); + new TagContainsKeywordsPredicate(Collections.singletonList("venue")); assertNotEquals(firstPredicate, secondPredicate); // Test same predicate with same keyword -> returns true