Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create new findPhone feature #63

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions src/main/java/seedu/address/logic/commands/FindPhoneCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package seedu.address.logic.commands;

import static java.util.Objects.requireNonNull;

import seedu.address.commons.util.ToStringBuilder;
import seedu.address.logic.Messages;
import seedu.address.model.Model;
import seedu.address.model.person.PhoneBeginsWithKeywordPredicate;

/**
* Finds and lists all persons in address book whose phone number begins with the argument keywords.
* Keyword matching has to be all numbers.
*/
public class FindPhoneCommand extends Command {

public static final String COMMAND_WORD = "fp";

public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all persons whose phone number begins with "
+ "the specified keywords (integers only with no spacing) and displays them as a list with index numbers.\n"
+ "Parameters: integers \n"
+ "Example: " + COMMAND_WORD + " 91234567";

private final PhoneBeginsWithKeywordPredicate predicate;

public FindPhoneCommand(PhoneBeginsWithKeywordPredicate predicate) {
this.predicate = predicate;
}

@Override
public CommandResult execute(Model model) {
requireNonNull(model);
model.updateFilteredPersonList(predicate);
return new CommandResult(
String.format(Messages.MESSAGE_PERSONS_LISTED_OVERVIEW, model.getFilteredPersonList().size()));
}

@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();
}
}
4 changes: 4 additions & 0 deletions src/main/java/seedu/address/logic/parser/ClientHubParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import seedu.address.logic.commands.EditCommand;
import seedu.address.logic.commands.ExitCommand;
import seedu.address.logic.commands.FindCommand;
import seedu.address.logic.commands.FindPhoneCommand;
import seedu.address.logic.commands.HelpCommand;
import seedu.address.logic.commands.ListCommand;
import seedu.address.logic.parser.exceptions.ParseException;
Expand Down Expand Up @@ -77,6 +78,9 @@ public Command parseCommand(String userInput) throws ParseException {
case HelpCommand.COMMAND_WORD:
return new HelpCommand();

case FindPhoneCommand.COMMAND_WORD:
return new FindPhoneCommandParser().parse(arguments);

default:
logger.finer("This user input caused a ParseException: " + userInput);
throw new ParseException(MESSAGE_UNKNOWN_COMMAND);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package seedu.address.logic.parser;

import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT;

import seedu.address.logic.commands.FindPhoneCommand;
import seedu.address.logic.parser.exceptions.ParseException;
import seedu.address.model.person.PhoneBeginsWithKeywordPredicate;

/**
* Parses input arguments and creates a new FindPhoneCommand object
*/
public class FindPhoneCommandParser implements Parser<FindPhoneCommand> {

/**
* Parses the given {@code String} of arguments in the context of the FindCommand
* and returns a FindPhoneNumberCommand object for execution.
* @throws ParseException if the user input does not conform the expected format
*/
public FindPhoneCommand parse(String args) throws ParseException {
String trimmedArgs = args.trim();

if (trimmedArgs.isEmpty() || !trimmedArgs.matches("\\d+")) {
throw new ParseException(
String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindPhoneCommand.MESSAGE_USAGE));
}
Comment on lines +22 to +25

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice error handling for invalid arguments!


String[] phoneNumber = trimmedArgs.split("\\s+");

if (phoneNumber.length != 1) {
throw new ParseException(
String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindPhoneCommand.MESSAGE_USAGE));
}

return new FindPhoneCommand(new PhoneBeginsWithKeywordPredicate(phoneNumber[0]));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package seedu.address.model.person;

import java.util.function.Predicate;

import seedu.address.commons.util.ToStringBuilder;

/**
* Tests that a {@code Person}'s {@code Phone} matches any of the keywords given.
*/
public class PhoneBeginsWithKeywordPredicate implements Predicate<Person> {
private final String keyword;

public PhoneBeginsWithKeywordPredicate(String keyword) {
this.keyword = keyword;
}

@Override
public boolean test(Person person) {
if (keyword.isEmpty()) {
return false;
}
return person.getPhone().value.startsWith(keyword);
}

@Override
public boolean equals(Object other) {
if (other == this) {
return true;
}

// instanceof handles nulls
if (!(other instanceof PhoneBeginsWithKeywordPredicate)) {
return false;
}

PhoneBeginsWithKeywordPredicate otherPhoneBeginsWithKeywordPredicate = (PhoneBeginsWithKeywordPredicate) other;
return keyword.equals(otherPhoneBeginsWithKeywordPredicate.keyword);
}

@Override
public String toString() {
return new ToStringBuilder(this).add("keyword", keyword).toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
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.ELLE;
import static seedu.address.testutil.TypicalPersons.FIONA;
import static seedu.address.testutil.TypicalPersons.GEORGE;
import static seedu.address.testutil.TypicalPersons.getTypicalClientHub;

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.PhoneBeginsWithKeywordPredicate;

/**
* Contains integration tests (interaction with the Model) for {@code FindCommand}.
*/
public class FindPhoneCommandTest {
private Model model = new ModelManager(getTypicalClientHub(), new UserPrefs());
private Model expectedModel = new ModelManager(getTypicalClientHub(), new UserPrefs());

@Test
public void equals() {
PhoneBeginsWithKeywordPredicate firstPredicate =
new PhoneBeginsWithKeywordPredicate("9876");
PhoneBeginsWithKeywordPredicate secondPredicate =
new PhoneBeginsWithKeywordPredicate("9678");

FindPhoneCommand findPhoneFirstCommand = new FindPhoneCommand(firstPredicate);
FindPhoneCommand findPhoneSecondCommand = new FindPhoneCommand(secondPredicate);

// same object -> returns true
assertTrue(findPhoneFirstCommand.equals(findPhoneFirstCommand));

// same values -> returns true
FindPhoneCommand findPhoneFirstCommandCopy = new FindPhoneCommand(firstPredicate);
assertTrue(findPhoneFirstCommand.equals(findPhoneFirstCommandCopy));

// different types -> returns false
assertFalse(findPhoneFirstCommand.equals(1));

// null -> returns false
assertFalse(findPhoneFirstCommand.equals(null));

// different person -> returns false
assertFalse(findPhoneFirstCommand.equals(findPhoneSecondCommand));
}

@Test
public void execute_zeroKeywords_noPhoneFound() {
String expectedMessage = String.format(MESSAGE_PERSONS_LISTED_OVERVIEW, 0);
PhoneBeginsWithKeywordPredicate predicate = preparePredicate(" ");
FindPhoneCommand command = new FindPhoneCommand(predicate);
expectedModel.updateFilteredPersonList(predicate);
assertCommandSuccess(command, model, expectedMessage, expectedModel);
assertEquals(Collections.emptyList(), model.getFilteredPersonList());
}

@Test
public void execute_singleKeyword_multiplePersonsFound() {
String expectedMessage = String.format(MESSAGE_PERSONS_LISTED_OVERVIEW, 3);
PhoneBeginsWithKeywordPredicate predicate = preparePredicate("948");
FindPhoneCommand command = new FindPhoneCommand(predicate);
expectedModel.updateFilteredPersonList(predicate);
assertCommandSuccess(command, model, expectedMessage, expectedModel);
assertEquals(Arrays.asList(ELLE, FIONA, GEORGE), model.getFilteredPersonList());
}

@Test
public void toStringMethod() {
PhoneBeginsWithKeywordPredicate predicate = new PhoneBeginsWithKeywordPredicate("keyword");
FindPhoneCommand findPhoneCommand = new FindPhoneCommand(predicate);
String expected = FindPhoneCommand.class.getCanonicalName() + "{predicate=" + predicate + "}";
assertEquals(expected, findPhoneCommand.toString());
}

/**
* Parses {@code userInput} into a {@code NameContainsKeywordsPredicate}.
*/
private PhoneBeginsWithKeywordPredicate preparePredicate(String userInput) {
return new PhoneBeginsWithKeywordPredicate(userInput);
}
}
10 changes: 10 additions & 0 deletions src/test/java/seedu/address/logic/parser/ClientHubParserTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@
import seedu.address.logic.commands.EditCommand.EditPersonDescriptor;
import seedu.address.logic.commands.ExitCommand;
import seedu.address.logic.commands.FindCommand;
import seedu.address.logic.commands.FindPhoneCommand;
import seedu.address.logic.commands.HelpCommand;
import seedu.address.logic.commands.ListCommand;
import seedu.address.logic.parser.exceptions.ParseException;
import seedu.address.model.person.NameContainsKeywordsPredicate;
import seedu.address.model.person.Person;
import seedu.address.model.person.PhoneBeginsWithKeywordPredicate;
import seedu.address.testutil.EditPersonDescriptorBuilder;
import seedu.address.testutil.PersonBuilder;
import seedu.address.testutil.PersonUtil;
Expand Down Expand Up @@ -88,6 +90,14 @@ public void parseCommand_list() throws Exception {
assertTrue(parser.parseCommand(ListCommand.COMMAND_WORD + " 3") instanceof ListCommand);
}

@Test
public void parseCommand_findPhone() throws Exception {
String keyword = "9876";
FindPhoneCommand command = (FindPhoneCommand) parser.parseCommand(
FindPhoneCommand.COMMAND_WORD + " " + keyword);
assertEquals(new FindPhoneCommand(new PhoneBeginsWithKeywordPredicate(keyword)), command);
}

@Test
public void parseCommand_unrecognisedInput_throwsParseException() {
assertThrows(ParseException.class, String.format(MESSAGE_INVALID_COMMAND_FORMAT, HelpCommand.MESSAGE_USAGE), ()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
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 org.junit.jupiter.api.Test;

import seedu.address.logic.commands.FindPhoneCommand;
import seedu.address.model.person.PhoneBeginsWithKeywordPredicate;

public class FindPhoneCommandParserTest {

private FindPhoneCommandParser parser = new FindPhoneCommandParser();

@Test
public void parse_emptyArg_throwsParseException() {
assertParseFailure(parser, " ",
String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindPhoneCommand.MESSAGE_USAGE));
}

@Test
public void parse_validArgs_returnsFindCommand() {
// no leading and trailing whitespaces
FindPhoneCommand expectedFindCommand =
new FindPhoneCommand(new PhoneBeginsWithKeywordPredicate("9876"));
assertParseSuccess(parser, "9876", expectedFindCommand);
}

@Test
public void parse_invalidArgs_throwsParseException() {
// multiple inputs
assertParseFailure(parser, "9876 9678",
String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindPhoneCommand.MESSAGE_USAGE));


// not number
assertParseFailure(parser, "string",
String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindPhoneCommand.MESSAGE_USAGE));


// non-number in betweennumber
assertParseFailure(parser, "987n9678",
String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindPhoneCommand.MESSAGE_USAGE));
}

}
Loading
Loading