diff --git a/src/main/java/seedu/address/logic/commands/FindByContactCommand.java b/src/main/java/seedu/address/logic/commands/FindByContactCommand.java new file mode 100644 index 00000000000..9e1565a443e --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/FindByContactCommand.java @@ -0,0 +1,33 @@ +package seedu.address.logic.commands; + +import seedu.address.model.person.ContactContainsKeywordsPredicate; + +/** + * Finds and lists all persons in address book whose contact contains any of the argument keywords. + */ +public class FindByContactCommand extends AbstractFindCommand { + public static final String COMMAND_WORD = "find /c"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all persons whose contact numbers " + + "contain any of the specified keywords (case-insensitive) and displays them as a list with indices.\n" + + "Parameters: KEYWORD [MORE_KEYWORDS]...\n" + + "Example: " + COMMAND_WORD + " 91112345 999 995"; + public FindByContactCommand(ContactContainsKeywordsPredicate predicate) { + super(predicate); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + // instanceof handles nulls + if (!(other instanceof FindByContactCommand)) { + return false; + } + + FindByContactCommand otherFindCommand = (FindByContactCommand) other; + return this.getPredicate().equals(otherFindCommand.getPredicate()); + } +} diff --git a/src/main/java/seedu/address/logic/commands/FindByNameCommand.java b/src/main/java/seedu/address/logic/commands/FindByNameCommand.java index 5f3593b2e10..8503617cba7 100644 --- a/src/main/java/seedu/address/logic/commands/FindByNameCommand.java +++ b/src/main/java/seedu/address/logic/commands/FindByNameCommand.java @@ -7,6 +7,12 @@ * Keyword matching is case-insensitive. */ public class FindByNameCommand extends AbstractFindCommand { + public static final String COMMAND_WORD = "find /n"; + + 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 indices.\n" + + "Parameters: KEYWORD [MORE_KEYWORDS]...\n" + + "Example: " + COMMAND_WORD + " alice bob charlie"; public FindByNameCommand(NameContainsKeywordsPredicate predicate) { super(predicate); } diff --git a/src/main/java/seedu/address/logic/parser/FindCommandParser.java b/src/main/java/seedu/address/logic/parser/FindCommandParser.java index 9205b470b90..d88839e480a 100644 --- a/src/main/java/seedu/address/logic/parser/FindCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/FindCommandParser.java @@ -7,9 +7,10 @@ import java.util.regex.Pattern; import seedu.address.logic.commands.AbstractFindCommand; +import seedu.address.logic.commands.FindByContactCommand; import seedu.address.logic.commands.FindByNameCommand; -import seedu.address.logic.commands.FindCommand; import seedu.address.logic.parser.exceptions.ParseException; +import seedu.address.model.person.ContactContainsKeywordsPredicate; import seedu.address.model.person.NameContainsKeywordsPredicate; /** @@ -32,7 +33,7 @@ public AbstractFindCommand parse(String args) throws ParseException { // will throw exception if no args/command format not correct if (trimmedArgs.isEmpty() || !m.matches()) { throw new ParseException( - String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE)); + String.format(MESSAGE_INVALID_COMMAND_FORMAT, AbstractFindCommand.MESSAGE_USAGE)); } // extract tag and search argument @@ -40,11 +41,14 @@ public AbstractFindCommand parse(String args) throws ParseException { String searchTerms = m.group("arguments"); String[] searchTermArray = searchTerms.split("\\s+"); - // return approppriate FindCommand class depending on tag + // return appropriate FindCommand class depending on tag switch (tag) { case "/n": return new FindByNameCommand( new NameContainsKeywordsPredicate(Arrays.asList(searchTermArray))); + case "/c": + return new FindByContactCommand( + new ContactContainsKeywordsPredicate(Arrays.asList(searchTermArray))); default: return null; // temporary value, this should not occur due to regex } diff --git a/src/test/java/seedu/address/logic/commands/FindByContactCommandTest.java b/src/test/java/seedu/address/logic/commands/FindByContactCommandTest.java new file mode 100644 index 00000000000..e0271ef7ac5 --- /dev/null +++ b/src/test/java/seedu/address/logic/commands/FindByContactCommandTest.java @@ -0,0 +1,90 @@ +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.Messages.MESSAGE_PERSONS_LISTED_OVERVIEW; +import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; +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.ContactContainsKeywordsPredicate; +import seedu.address.model.person.NameContainsKeywordsPredicate; + +/** + * Contains integration tests (interaction with the Model) for {@code FindByContactCommand}. + */ +public class FindByContactCommandTest { + private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + private Model expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + + @Test + public void equals() { + ContactContainsKeywordsPredicate firstPredicate = + new ContactContainsKeywordsPredicate(Collections.singletonList("first")); + ContactContainsKeywordsPredicate secondPredicate = + new ContactContainsKeywordsPredicate(Collections.singletonList("second")); + + FindByContactCommand findFirstCommand = new FindByContactCommand(firstPredicate); + FindByContactCommand findSecondCommand = new FindByContactCommand(secondPredicate); + + // same object -> returns true + assertTrue(findFirstCommand.equals(findFirstCommand)); + + // same values -> returns true + FindByContactCommand findFirstCommandCopy = new FindByContactCommand(firstPredicate); + assertTrue(findFirstCommand.equals(findFirstCommandCopy)); + + // different types -> returns false + assertFalse(findFirstCommand.equals(1)); + + // null -> returns false + assertFalse(findFirstCommand.equals(null)); + + // different person -> returns false + assertFalse(findFirstCommand.equals(findSecondCommand)); + } + + @Test + public void execute_zeroKeywords_noPersonFound() { + String expectedMessage = String.format(MESSAGE_PERSONS_LISTED_OVERVIEW, 0); + ContactContainsKeywordsPredicate predicate = preparePredicate(" "); + FindByContactCommand command = new FindByContactCommand(predicate); + expectedModel.updateFilteredPersonList(predicate); + assertCommandSuccess(command, model, expectedMessage, expectedModel); + assertEquals(Collections.emptyList(), model.getFilteredPersonList()); + } + + // Commented out because expectedModel does not contain contact numbers + // @Test + // public void execute_multipleKeywords_multiplePersonsFound() { + // String expectedMessage = String.format(MESSAGE_PERSONS_LISTED_OVERVIEW, 0); + // ContactContainsKeywordsPredicate predicate = preparePredicate("999"); + // FindByContactCommand command = new FindByContactCommand(predicate); + // expectedModel.updateFilteredPersonList(predicate); + // assertCommandSuccess(command, model, expectedMessage, expectedModel); + // assertEquals(Arrays.asList(CARL, ELLE, FIONA), model.getFilteredPersonList()); + // } + + @Test + public void toStringMethod() { + NameContainsKeywordsPredicate predicate = new NameContainsKeywordsPredicate(Arrays.asList("keyword")); + FindByNameCommand findCommand = new FindByNameCommand(predicate); + String expected = FindByNameCommand.class.getCanonicalName() + "{predicate=" + predicate + "}"; + assertEquals(expected, findCommand.toString()); + } + + /** + * Parses {@code userInput} into a {@code NameContainsKeywordsPredicate}. + */ + private ContactContainsKeywordsPredicate preparePredicate(String userInput) { + return new ContactContainsKeywordsPredicate(Arrays.asList(userInput.split("\\s+"))); + } +} diff --git a/src/test/java/seedu/address/logic/commands/FindByNameCommandTest.java b/src/test/java/seedu/address/logic/commands/FindByNameCommandTest.java index 62e37b55f06..5cc9f6befaf 100644 --- a/src/test/java/seedu/address/logic/commands/FindByNameCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/FindByNameCommandTest.java @@ -21,7 +21,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 FindByNameCommand}. */ public class FindByNameCommandTest { private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); diff --git a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java b/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java index 08ae9a62fab..c13e70bb4d6 100644 --- a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java +++ b/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java @@ -19,10 +19,12 @@ import seedu.address.logic.commands.EditCommand; import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; import seedu.address.logic.commands.ExitCommand; +import seedu.address.logic.commands.FindByContactCommand; import seedu.address.logic.commands.FindByNameCommand; import seedu.address.logic.commands.HelpCommand; import seedu.address.logic.commands.ListCommand; import seedu.address.logic.parser.exceptions.ParseException; +import seedu.address.model.person.ContactContainsKeywordsPredicate; import seedu.address.model.person.NameContainsKeywordsPredicate; import seedu.address.model.person.Person; import seedu.address.testutil.EditPersonDescriptorBuilder; @@ -80,11 +82,20 @@ public void parseCommand_exit() throws Exception { public void parseCommand_findByName() throws Exception { List keywords = Arrays.asList("foo", "bar", "baz"); FindByNameCommand command = (FindByNameCommand) parser.parseCommand( - FindByNameCommand.COMMAND_WORD + " /n " + FindByNameCommand.COMMAND_WORD + " " + keywords.stream().collect(Collectors.joining(" "))); assertEquals(new FindByNameCommand(new NameContainsKeywordsPredicate(keywords)), command); } + @Test + public void parseCommand_findByContact() throws Exception { + List keywords = Arrays.asList("995", "91234567", "132"); + FindByContactCommand command = (FindByContactCommand) parser.parseCommand( + FindByContactCommand.COMMAND_WORD + " " + + keywords.stream().collect(Collectors.joining(" "))); + assertEquals(new FindByContactCommand(new ContactContainsKeywordsPredicate(keywords)), command); + } + @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 35b0de1c36b..7975408a57e 100644 --- a/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java @@ -8,8 +8,10 @@ import org.junit.jupiter.api.Test; +import seedu.address.logic.commands.AbstractFindCommand; +import seedu.address.logic.commands.FindByContactCommand; import seedu.address.logic.commands.FindByNameCommand; -import seedu.address.logic.commands.FindCommand; +import seedu.address.model.person.ContactContainsKeywordsPredicate; import seedu.address.model.person.NameContainsKeywordsPredicate; public class FindCommandParserTest { @@ -18,7 +20,8 @@ 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, + AbstractFindCommand.MESSAGE_USAGE)); } @Test @@ -33,4 +36,17 @@ public void parse_validArgs_returnsFindByNameCommand() { assertParseSuccess(parser, "/n \n Alice \n \t Bob \t", expectedFindCommand); } + @Test + public void parse_validArgs_returnsFindByContactCommand() { + FindByContactCommand expectedFindCommand = + new FindByContactCommand(new ContactContainsKeywordsPredicate( + Arrays.asList("91234567", "995"))); + + // no leading and trailing whitespaces + assertParseSuccess(parser, "/c 91234567 995", expectedFindCommand); + + // multiple whitespaces between keywords + assertParseSuccess(parser, "/c \n 91234567 \n \t 995 \t", expectedFindCommand); + } + }