Skip to content

Commit

Permalink
Merge pull request #355 from yooplo
Browse files Browse the repository at this point in the history
Add SuperFindCommand Test cases
  • Loading branch information
yooplo authored Nov 9, 2024
2 parents 572a8eb + 06cbe3e commit 142007d
Show file tree
Hide file tree
Showing 8 changed files with 466 additions and 48 deletions.
59 changes: 51 additions & 8 deletions src/main/java/seedu/address/logic/commands/SuperFindCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,23 @@
import seedu.address.model.person.ContainsKeywordsPredicate;

/**
* Abstract Find command to house the other find command classes.
* Represents a command for finding persons in the CampusConnect based on specified keywords.
* <p>
* This command can filter persons according to their names, phone numbers, emails, or tags,
* allowing users to search through the address book efficiently. It consolidates the functionality
* of various find commands under a single command class, enabling complex search queries with
* multiple keywords prefixed by their respective categories.
* </p>
*
* <p>
* The command utilizes a {@code ContainsKeywordsPredicate} to determine which persons match the
* specified criteria. If no matching persons are found, a message is returned indicating the
* failure to find any persons that match the search.
* </p>
*
* <p>
* This command follows the command pattern and extends the {@code Command} class.
* </p>
*/
public class SuperFindCommand extends Command {

Expand All @@ -28,20 +44,37 @@ public class SuperFindCommand extends Command {

private final ContainsKeywordsPredicate predicate;

/**
* Constructs a {@code SuperFindCommand} with the specified predicate.
*
* @param predicate The predicate to filter the list of persons.
*/
public SuperFindCommand(ContainsKeywordsPredicate predicate) {
this.predicate = predicate;
this.predicate = requireNonNull(predicate, "Predicate cannot be null");
}

/**
* Retrieves the predicate for this command.
*
* @return The predicate used to filter persons.
*/
protected ContainsKeywordsPredicate getPredicate() {
return this.predicate;
}

/**
* Executes the command, filtering the list of persons based on the predicate.
*
* @param model The model to operate on.
* @return The result of the command execution.
*/
@Override
public CommandResult execute(Model model) {
requireNonNull(model);
requireNonNull(model, "Model cannot be null");

model.updateFilteredPersonList(this.predicate);

// if the result find list is empty
// If the resulting filtered list is empty
if (model.getFilteredPersonList().isEmpty()) {
return new CommandResult(MESSAGE_NO_PERSONS_FOUND);
}
Expand All @@ -50,21 +83,31 @@ public CommandResult execute(Model model) {
String.format(Messages.MESSAGE_PERSONS_LISTED_OVERVIEW, model.getFilteredPersonList().size()));
}

/**
* Checks if this command is equal to another object.
*
* @param other The object to compare with this command.
* @return True if the other object is the same type and has the same predicate; false otherwise.
*/
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
return true; // Check for reference equality
}

if (!(other instanceof SuperFindCommand)) {
return false;
return false; // Ensure the other object is of the same type
}

SuperFindCommand otherCommand = (SuperFindCommand) other;
return this.predicate.equals(otherCommand.predicate);
return this.predicate.equals(otherCommand.predicate); // Compare predicates
}


/**
* Returns a string representation of this command.
*
* @return A string representation of the command state.
*/
@Override
public String toString() {
return new ToStringBuilder(this)
Expand Down
60 changes: 49 additions & 11 deletions src/main/java/seedu/address/logic/parser/FindCommandParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,36 @@
import seedu.address.model.person.TagContainsKeywordsPredicate;

/**
* Parses input arguments and creates a new FindCommand object
* Parses input arguments for the find command and constructs a new {@code SuperFindCommand} object.
* <p>
* This class processes user input to extract keywords associated with different attributes of a person,
* such as names, phone numbers, emails, and tags. It tokenizes the input arguments based on predefined
* prefixes and builds a list of predicates used to filter persons in the address book.
* </p>
*
* <p>
* The parser creates a {@code CombinedContainsKeywordsPredicate} that combines all individual predicates, allowing
* for complex search queries. If no valid predicates are constructed from the input, a {@code ParseException}
* is thrown to indicate an invalid command format.
* </p>
*
* <p>
* This class follows the parser pattern used in the logic layer of the application and is responsible for ensuring
* that input is validated and correctly interpreted before creating command objects.
* </p>
*/
public class FindCommandParser implements Parser<SuperFindCommand> {
/**
* Parses the given arguments for find command and returns a {@code SuperFindCommand}.
*
* @param args The input arguments for the command.
* @throws ParseException if the arguments format is invalid.
*/
@Override
public SuperFindCommand parse(String args) throws ParseException {
requireNonNull(args);
ArgumentMultimap argMultimap = tokenizeArguments(args);
requireNonNull(args, "Arguments cannot be null.");

ArgumentMultimap argMultimap = tokenizeArguments(args);
List<Predicate<Person>> predicates = buildPredicates(argMultimap);

if (predicates.isEmpty()) {
Expand All @@ -40,10 +62,22 @@ public SuperFindCommand parse(String args) throws ParseException {
return new SuperFindCommand(combinedPredicate);
}

/**
* Tokenizes the input arguments into an {@code ArgumentMultimap}.
*
* @param args The input arguments.
* @return The tokenized arguments.
*/
private ArgumentMultimap tokenizeArguments(String args) {
return ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_TAG);
}

/**
* Builds a list of predicates based on the tokenized input arguments.
*
* @param argMultimap The tokenized input arguments.
* @return A list of predicates for filtering persons.
*/
private List<Predicate<Person>> buildPredicates(ArgumentMultimap argMultimap) {
List<Predicate<Person>> predicates = new ArrayList<>();
buildNamePredicates(argMultimap, predicates);
Expand All @@ -54,22 +88,26 @@ private List<Predicate<Person>> buildPredicates(ArgumentMultimap argMultimap) {
}

private void buildNamePredicates(ArgumentMultimap argMultimap, List<Predicate<Person>> predicates) {
argMultimap.getValue(PREFIX_NAME).ifPresent(values ->
predicates.add(new NameContainsKeywordsPredicate(argMultimap.getAllValues(PREFIX_NAME))));
argMultimap.getValue(PREFIX_NAME)
.ifPresent(values -> predicates.add(
new NameContainsKeywordsPredicate(argMultimap.getAllValues(PREFIX_NAME))));
}

private void buildPhonePredicates(ArgumentMultimap argMultimap, List<Predicate<Person>> predicates) {
argMultimap.getValue(PREFIX_PHONE).ifPresent(values ->
predicates.add(new PhoneContainsKeywordsPredicate(argMultimap.getAllValues(PREFIX_PHONE))));
argMultimap.getValue(PREFIX_PHONE)
.ifPresent(values -> predicates.add(
new PhoneContainsKeywordsPredicate(argMultimap.getAllValues(PREFIX_PHONE))));
}

private void buildEmailPredicates(ArgumentMultimap argMultimap, List<Predicate<Person>> predicates) {
argMultimap.getValue(PREFIX_EMAIL).ifPresent(values ->
predicates.add(new EmailContainsKeywordsPredicate(argMultimap.getAllValues(PREFIX_EMAIL))));
argMultimap.getValue(PREFIX_EMAIL)
.ifPresent(values -> predicates.add(
new EmailContainsKeywordsPredicate(argMultimap.getAllValues(PREFIX_EMAIL))));
}

private void buildTagPredicates(ArgumentMultimap argMultimap, List<Predicate<Person>> predicates) {
argMultimap.getValue(PREFIX_TAG).ifPresent(values ->
predicates.add(new TagContainsKeywordsPredicate(argMultimap.getAllValues(PREFIX_TAG))));
argMultimap.getValue(PREFIX_TAG)
.ifPresent(values -> predicates.add(
new TagContainsKeywordsPredicate(argMultimap.getAllValues(PREFIX_TAG))));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,61 @@
import seedu.address.commons.util.ToStringBuilder;

/**
* Tests that a {@code Person}'s {@code Name} matches any of the keywords given.
* Tests that a {@code Person}'s {@code Email} matches any of the keywords given.
*/
public class EmailContainsKeywordsPredicate extends ContainsKeywordsPredicate {

/**
* Constructs an {@code EmailContainsKeywordsPredicate} with the specified keywords.
*
* @param keywords List of keywords to match against a person's email.
*/
public EmailContainsKeywordsPredicate(List<String> keywords) {
super(keywords);
}

/**
* Tests if any of the keywords match the email address of the given person.
*
* @param person the {@code Person} to test.
* @return true if any keyword matches the person's email address, false otherwise.
*/
@Override
public boolean test(Person person) {
return super.getKeywords().stream()
.anyMatch(keyword -> person.getEmail().value.toLowerCase().contains(keyword.toLowerCase()));
}

/**
* Checks if this predicate is equal to another object.
*
* @param other the object to compare with this predicate.
* @return true if the other object is the same type and has the same keywords, false otherwise.
*/
@Override
public boolean equals(Object other) {
if (other == this) {
return true;
if (this == other) {
return true; // Check for reference equality
}

// instanceof handles nulls
// Check if the other object is an instance of EmailContainsKeywordsPredicate
if (!(other instanceof EmailContainsKeywordsPredicate)) {
return false;
}

EmailContainsKeywordsPredicate otherNameContainsKeywordsPredicate = (EmailContainsKeywordsPredicate) other;
return this.getKeywords().equals(otherNameContainsKeywordsPredicate.getKeywords());
EmailContainsKeywordsPredicate otherPredicate = (EmailContainsKeywordsPredicate) other;
return getKeywords().equals(otherPredicate.getKeywords());
}

/**
* Returns a string representation of this predicate.
*
* @return string representation of the object's state.
*/
@Override
public String toString() {
return new ToStringBuilder(this).add("keywords", this.getKeywords()).toString();
return new ToStringBuilder(this)
.add("keywords", getKeywords())
.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,33 +9,57 @@
*/
public class NameContainsKeywordsPredicate extends ContainsKeywordsPredicate {

/**
* Constructs a {@code NameContainsKeywordsPredicate} with the specified keywords.
*
* @param keywords List of keywords to match against a person's name.
*/
public NameContainsKeywordsPredicate(List<String> keywords) {
super(keywords);
}

/**
* Tests if any of the keywords match the name of the given person.
*
* @param person the {@code Person} whose name is to be tested.
* @return true if any keyword matches the person's name, false otherwise.
*/
@Override
public boolean test(Person person) {
return this.getKeywords().stream()
return getKeywords().stream()
.anyMatch(keyword -> person.getName().fullName.toLowerCase().contains(keyword.toLowerCase()));
}

/**
* Checks if this predicate is equal to another object.
*
* @param other the object to compare with this predicate.
* @return true if the other object is the same type and has the same keywords, false otherwise.
*/
@Override
public boolean equals(Object other) {
if (other == this) {
return true;
if (this == other) {
return true; // Check for reference equality
}

// instanceof handles nulls
// Check if the other object is an instance of NameContainsKeywordsPredicate
if (!(other instanceof NameContainsKeywordsPredicate)) {
return false;
}

NameContainsKeywordsPredicate otherNameContainsKeywordsPredicate = (NameContainsKeywordsPredicate) other;
return this.getKeywords().equals(otherNameContainsKeywordsPredicate.getKeywords());
NameContainsKeywordsPredicate otherPredicate = (NameContainsKeywordsPredicate) other;
return getKeywords().equals(otherPredicate.getKeywords());
}

/**
* Returns a string representation of this predicate.
*
* @return string representation of the object's state.
*/
@Override
public String toString() {
return new ToStringBuilder(this).add("keywords", this.getKeywords()).toString();
return new ToStringBuilder(this)
.add("keywords", getKeywords())
.toString();
}
}
Loading

0 comments on commit 142007d

Please sign in to comment.