diff --git a/src/main/java/seedu/address/logic/commands/FindCommand.java b/src/main/java/seedu/address/logic/commands/FindCommand.java index 72b9eddd3a7..f92deb74f63 100644 --- a/src/main/java/seedu/address/logic/commands/FindCommand.java +++ b/src/main/java/seedu/address/logic/commands/FindCommand.java @@ -2,27 +2,29 @@ import static java.util.Objects.requireNonNull; +import java.util.function.Predicate; + import seedu.address.commons.util.ToStringBuilder; import seedu.address.logic.Messages; import seedu.address.model.Model; -import seedu.address.model.person.NameContainsKeywordsPredicate; +import seedu.address.model.person.Person; /** - * Finds and lists all persons in address book whose name contains any of the argument keywords. - * Keyword matching is case insensitive. + * Finds and lists all persons in address book whose attribute satisfies the given predicate. */ -public class FindCommand extends Command { +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 + " alice bob charlie"; + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all persons with the specified attribute " + + "containing any of the specified keywords (case-insensitive)" + + "and displays them as a list with index numbers.\n" + + "Parameters: PREFIX/KEYWORD [PREFIX/MORE_KEYWORDS]...\n" + + "Example: " + COMMAND_WORD + " n/alice n/bob"; - private final NameContainsKeywordsPredicate predicate; + protected final Predicate predicate; - public FindCommand(NameContainsKeywordsPredicate predicate) { + public FindCommand(Predicate predicate) { 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 new file mode 100644 index 00000000000..13fbebb30a3 --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/FindNameCommand.java @@ -0,0 +1,19 @@ +package seedu.address.logic.commands; + +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. + */ +public class FindNameCommand extends FindCommand { + + 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: n/KEYWORD [n/MORE_KEYWORDS]...\n" + + "Example: " + COMMAND_WORD + " n/alice n/bob n/charlie"; + + public FindNameCommand(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 2867bde857b..49a56dad211 100644 --- a/src/main/java/seedu/address/logic/parser/FindCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/FindCommandParser.java @@ -1,33 +1,47 @@ package seedu.address.logic.parser; import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; -import java.util.Arrays; +import java.util.List; +import java.util.stream.Stream; 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; /** - * Parses input arguments and creates a new FindCommand object + * Parses input arguments and creates a new FindNameCommand 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. + * Parses the given {@code String} of arguments in the context of the FindNameCommand + * and returns a FindNameCommand object for execution. * @throws ParseException if the user input does not conform the expected format */ public FindCommand parse(String args) throws ParseException { - String trimmedArgs = args.trim(); - if (trimmedArgs.isEmpty()) { - throw new ParseException( - String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE)); + ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_NAME); + + if (!argMultimap.getPreamble().isEmpty()) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindNameCommand.MESSAGE_USAGE)); + } + + if (!arePrefixesPresent(argMultimap, PREFIX_NAME)) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindNameCommand.MESSAGE_USAGE)); } - String[] nameKeywords = trimmedArgs.split("\\s+"); + List nameKeywords = argMultimap.getAllValues(PREFIX_NAME); - return new FindCommand(new NameContainsKeywordsPredicate(Arrays.asList(nameKeywords))); + return new FindNameCommand(new NameContainsKeywordsPredicate(nameKeywords)); } + /** + * 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/test/java/seedu/address/logic/commands/FindCommandTest.java b/src/test/java/seedu/address/logic/commands/FindNameCommandTest.java similarity index 80% rename from src/test/java/seedu/address/logic/commands/FindCommandTest.java rename to src/test/java/seedu/address/logic/commands/FindNameCommandTest.java index b8b7dbba91a..cd0e40092fc 100644 --- a/src/test/java/seedu/address/logic/commands/FindCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/FindNameCommandTest.java @@ -21,9 +21,9 @@ 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 FindCommandTest { +public class FindNameCommandTest { private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); private Model expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs()); @@ -34,14 +34,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); + FindNameCommand findFirstCommandCopy = new FindNameCommand(firstPredicate); assertTrue(findFirstCommand.equals(findFirstCommandCopy)); // different types -> returns false @@ -58,7 +58,7 @@ public void equals() { public void execute_zeroKeywords_noPersonFound() { String expectedMessage = String.format(MESSAGE_PERSONS_LISTED_OVERVIEW, 0); 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()); @@ -68,20 +68,12 @@ public void execute_zeroKeywords_noPersonFound() { public void execute_multipleKeywords_multiplePersonsFound() { String expectedMessage = String.format(MESSAGE_PERSONS_LISTED_OVERVIEW, 3); NameContainsKeywordsPredicate predicate = preparePredicate("Kurz Elle Kunz"); - FindCommand command = new FindCommand(predicate); + FindNameCommand command = new FindNameCommand(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")); - FindCommand findCommand = new FindCommand(predicate); - String expected = FindCommand.class.getCanonicalName() + "{predicate=" + predicate + "}"; - assertEquals(expected, findCommand.toString()); - } - /** * Parses {@code userInput} into a {@code NameContainsKeywordsPredicate}. */ diff --git a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java b/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java index 5a1ab3dbc0c..9e4b89d6e6c 100644 --- a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java +++ b/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java @@ -20,6 +20,7 @@ import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; import seedu.address.logic.commands.ExitCommand; 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.parser.exceptions.ParseException; @@ -71,9 +72,10 @@ 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 + " " + + keywords.stream().map(k -> "n/" + k).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..22d19a1d4bd 100644 --- a/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java @@ -8,7 +8,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 +17,19 @@ 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, FindNameCommand.MESSAGE_USAGE)); } @Test - public void parse_validArgs_returnsFindCommand() { + public void parse_validArgs_returnsFindNameCommand() { // 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, " n/Alice n/Bob", expectedFindCommand); // multiple whitespaces between keywords - assertParseSuccess(parser, " \n Alice \n \t Bob \t", expectedFindCommand); + assertParseSuccess(parser, " \n n/Alice \n \t n/Bob \t", expectedFindCommand); } }