forked from nus-cs2103-AY1920S2/addressbook-level3
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
395 additions
and
6 deletions.
There are no files selected for viewing
46 changes: 46 additions & 0 deletions
46
src/main/java/seedu/address/logic/commands/FilterCommand.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package seedu.address.logic.commands; | ||
|
||
import static java.util.Objects.requireNonNull; | ||
import static seedu.address.logic.parser.CliSyntax.PREFIX_SPORT; | ||
import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; | ||
|
||
import seedu.address.commons.core.Messages; | ||
import seedu.address.model.Model; | ||
import seedu.address.model.client.TagAndSportContainsKeywordsPredicate; | ||
|
||
/** | ||
* @author tohkerwei | ||
* Filters and lists all clients in FitBiz whose tag or sports contains argument keywords for the respective parameters. | ||
* Keyword matching is case insensitive. | ||
*/ | ||
public class FilterCommand extends Command { | ||
|
||
public static final String COMMAND_WORD = "filter-c"; | ||
|
||
public static final String MESSAGE_USAGE = COMMAND_WORD + ": Filters and display all clients whose tags or sports " | ||
+ "contains any of the specified keywords for respective parameter (case-insensitive) \n" | ||
+ "Parameters: t/KEYWORD... s/KEYWORD...\n" | ||
+ "Example: " + COMMAND_WORD + " " + PREFIX_TAG + "normal" + " " + PREFIX_SPORT + "hockey"; | ||
|
||
private final TagAndSportContainsKeywordsPredicate predicate; | ||
|
||
public FilterCommand(TagAndSportContainsKeywordsPredicate predicate) { | ||
this.predicate = predicate; | ||
} | ||
|
||
@Override | ||
public CommandResult execute(Model model) { | ||
requireNonNull(model); | ||
model.updateFilteredClientList(predicate); | ||
return new CommandResult( | ||
String.format(Messages.MESSAGE_CLIENTS_LISTED_OVERVIEW, model.getFilteredClientList().size())); | ||
} | ||
|
||
@Override | ||
public boolean equals(Object other) { | ||
return other == this // short circuit if same object | ||
|| (other instanceof FilterCommand // instanceof handles nulls | ||
&& predicate.equals(((FilterCommand) other).predicate)); // state check | ||
} | ||
} | ||
|
89 changes: 89 additions & 0 deletions
89
src/main/java/seedu/address/logic/parser/FilterCommandParser.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
package seedu.address.logic.parser; | ||
|
||
import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; | ||
import static seedu.address.logic.parser.CliSyntax.PREFIX_SPORT; | ||
import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.List; | ||
import java.util.Set; | ||
|
||
import seedu.address.logic.commands.FilterCommand; | ||
import seedu.address.logic.parser.exceptions.ParseException; | ||
import seedu.address.model.client.Sport; | ||
import seedu.address.model.client.TagAndSportContainsKeywordsPredicate; | ||
import seedu.address.model.tag.Tag; | ||
|
||
/** | ||
* Parses input arguments and creates a new FilterCommand object | ||
*/ | ||
public class FilterCommandParser implements Parser<FilterCommand> { | ||
|
||
/** | ||
* @author tohkerwei | ||
* Parses the given {@code String} of arguments in the context of the FilterCommand | ||
* and returns a FilterCommand object for execution. | ||
* @throws ParseException if the user input does not conform the expected format | ||
*/ | ||
public FilterCommand parse(String args) throws ParseException { | ||
|
||
ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_TAG, PREFIX_SPORT); | ||
|
||
boolean hasTag = argMultimap.getValue(PREFIX_TAG).isPresent(); | ||
boolean hasSport = argMultimap.getValue(PREFIX_SPORT).isPresent(); | ||
|
||
if (!hasTag && !hasSport) { | ||
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, FilterCommand.MESSAGE_USAGE)); | ||
} | ||
|
||
List<String> tags = getTagsFromMap(argMultimap); | ||
List<String> sports = getSportsFromMap(argMultimap); | ||
|
||
return new FilterCommand(new TagAndSportContainsKeywordsPredicate(splitKeywords(tags), splitKeywords(sports))); | ||
} | ||
|
||
/** | ||
* Splits the tags input by " " | ||
* @param list List of tag input | ||
* @return List of tags | ||
*/ | ||
public List<String> splitKeywords(List<String> list) { | ||
List<String> keywords = new ArrayList<>(); | ||
if (!list.isEmpty()) { | ||
String[] keywordArray = list.get(0).split(" "); | ||
keywords.addAll(Arrays.asList(keywordArray)); | ||
} | ||
return keywords; | ||
} | ||
|
||
/** | ||
* Returns a list of string of tags | ||
* @param argMultimap map of input | ||
* @return List of strings of tags | ||
* @throws ParseException if there are no tags | ||
*/ | ||
public List<String> getTagsFromMap(ArgumentMultimap argMultimap) throws ParseException { | ||
Set<Tag> tagSet = ParserUtil.parseTags(argMultimap.getAllValues(PREFIX_TAG)); | ||
List<String> tags = new ArrayList<String>(); | ||
for (Tag tag : tagSet) { | ||
tags.add(tag.tagName); | ||
} | ||
return tags; | ||
} | ||
|
||
/** | ||
* Returns a list of strings of sports | ||
* @param argMultimap map of input | ||
* @return List of strings of sports | ||
* @throws ParseException if there are no sports | ||
*/ | ||
public List<String> getSportsFromMap(ArgumentMultimap argMultimap) throws ParseException { | ||
Set<Sport> sportSet = ParserUtil.parseSports(argMultimap.getAllValues(PREFIX_SPORT)); | ||
List<String> sports = new ArrayList<String>(); | ||
for (Sport sport : sportSet) { | ||
sports.add(sport.sportName); | ||
} | ||
return sports; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
91 changes: 91 additions & 0 deletions
91
src/main/java/seedu/address/model/client/TagAndSportContainsKeywordsPredicate.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
package seedu.address.model.client; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Set; | ||
import java.util.function.Predicate; | ||
|
||
import seedu.address.commons.util.StringUtil; | ||
import seedu.address.model.tag.Tag; | ||
|
||
/** | ||
* @author tohkerwei | ||
* Tests that a {@code Client}'s {@code Name} matches any of the keywords given. | ||
*/ | ||
public class TagAndSportContainsKeywordsPredicate implements Predicate<Client> { | ||
|
||
private final List<String> tagKeywords; | ||
private final List<String> sportKeywords; | ||
|
||
public TagAndSportContainsKeywordsPredicate(List<String> tagKeywords, List<String> sportKeywords) { | ||
|
||
this.tagKeywords = tagKeywords; | ||
this.sportKeywords = sportKeywords; | ||
} | ||
|
||
@Override | ||
public boolean test(Client client) { | ||
boolean hasTag; | ||
boolean hasSport; | ||
if (tagKeywords.isEmpty()) { | ||
hasTag = true; | ||
} else { | ||
hasTag = tagKeywords.stream() | ||
.allMatch(keyword -> StringUtil.containsWordIgnoreCase(setTagToString(client.getTags()), keyword)); | ||
} | ||
|
||
if (sportKeywords.isEmpty()) { | ||
hasSport = true; | ||
} else { | ||
hasSport = sportKeywords.stream() | ||
.allMatch(keyword -> StringUtil | ||
.containsWordIgnoreCase(setSportToString(client.getSports()), keyword)); | ||
} | ||
|
||
return hasTag && hasSport; | ||
} | ||
|
||
/** | ||
* Converts the tags of a client into a string | ||
* @param tagsSet set of tags of a client | ||
* @return string containing tags of a client | ||
*/ | ||
public String setTagToString(Set<Tag> tagsSet) { | ||
StringBuilder sb = new StringBuilder(); | ||
ArrayList<String> tagArray = new ArrayList<>(); | ||
for (Tag tag : tagsSet) { | ||
tagArray.add(tag.tagName); | ||
} | ||
for (int i = 0; i < tagsSet.size(); i++) { | ||
sb.append(tagArray.get(i)); | ||
sb.append(" "); | ||
} | ||
return sb.toString(); | ||
} | ||
|
||
/** | ||
* Converts the sports of a client into a string | ||
* @param sportSet set of sports of a client | ||
* @return string containing sports of a client | ||
*/ | ||
public String setSportToString(Set<Sport> sportSet) { | ||
StringBuilder sb = new StringBuilder(); | ||
ArrayList<String> sportArray = new ArrayList<>(); | ||
for (Sport sport : sportSet) { | ||
sportArray.add(sport.sportName); | ||
} | ||
for (int i = 0; i < sportSet.size(); i++) { | ||
sb.append(sportArray.get(i)); | ||
sb.append(" "); | ||
} | ||
return sb.toString(); | ||
} | ||
|
||
@Override | ||
public boolean equals(Object other) { | ||
return other == this // short circuit if same object | ||
|| (other instanceof TagAndSportContainsKeywordsPredicate // instanceof handles nulls | ||
&& tagKeywords.equals(((TagAndSportContainsKeywordsPredicate) other).tagKeywords) | ||
|| sportKeywords.equals(((TagAndSportContainsKeywordsPredicate) other).sportKeywords)); // state check | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
106 changes: 106 additions & 0 deletions
106
src/test/java/seedu/address/logic/commands/FilterCommandTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
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.commons.core.Messages.MESSAGE_CLIENTS_LISTED_OVERVIEW; | ||
import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; | ||
|
||
import static seedu.address.testutil.TypicalClients.getTypicalFitBiz; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.Collections; | ||
import java.util.List; | ||
|
||
import org.junit.jupiter.api.Test; | ||
|
||
import seedu.address.model.ClientInView; | ||
import seedu.address.model.Model; | ||
import seedu.address.model.ModelManager; | ||
import seedu.address.model.UserPrefs; | ||
import seedu.address.model.client.TagAndSportContainsKeywordsPredicate; | ||
|
||
/** | ||
* Contains integration tests (interaction with the Model) for {@code FilterCommand}. | ||
*/ | ||
public class FilterCommandTest { | ||
private Model model = new ModelManager(getTypicalFitBiz(), new UserPrefs(), new ClientInView()); | ||
private Model expectedModel = new ModelManager(getTypicalFitBiz(), new UserPrefs(), new ClientInView()); | ||
|
||
@Test | ||
public void equals() { | ||
TagAndSportContainsKeywordsPredicate firstPredicate = | ||
new TagAndSportContainsKeywordsPredicate(Collections.singletonList("firsttag"), | ||
Collections.singletonList("firstsport")); | ||
TagAndSportContainsKeywordsPredicate secondPredicate = | ||
new TagAndSportContainsKeywordsPredicate(Collections.singletonList("secondtag"), | ||
Collections.singletonList("secondsport")); | ||
|
||
FilterCommand filterFirstCommand = new FilterCommand(firstPredicate); | ||
FilterCommand filterSecondCommand = new FilterCommand(secondPredicate); | ||
|
||
// same object -> returns true | ||
assertTrue(filterFirstCommand.equals(filterFirstCommand)); | ||
|
||
// same values -> returns true | ||
FilterCommand filterFirstCommandCopy = new FilterCommand(firstPredicate); | ||
assertTrue(filterFirstCommand.equals(filterFirstCommandCopy)); | ||
|
||
// different types -> returns false | ||
assertFalse(filterFirstCommand.equals(1)); | ||
|
||
// null -> returns false | ||
assertFalse(filterFirstCommand.equals(null)); | ||
|
||
// different client -> returns false | ||
assertFalse(filterFirstCommand.equals(filterSecondCommand)); | ||
} | ||
|
||
@Test | ||
public void execute_validTagAndSport_clientFound() { | ||
String expectedMessage = String.format(MESSAGE_CLIENTS_LISTED_OVERVIEW, 1); | ||
TagAndSportContainsKeywordsPredicate predicate = preparePredicate("normal", | ||
"dance"); | ||
FilterCommand command = new FilterCommand(predicate); | ||
expectedModel.updateFilteredClientList(predicate); | ||
assertCommandSuccess(command, model, expectedMessage, expectedModel); | ||
} | ||
|
||
@Test | ||
public void execute_validTagNoSport_multipleClientsFound() { | ||
String expectedMessage = String.format(MESSAGE_CLIENTS_LISTED_OVERVIEW, 2); | ||
TagAndSportContainsKeywordsPredicate predicate = preparePredicate("normal", | ||
""); | ||
FilterCommand command = new FilterCommand(predicate); | ||
expectedModel.updateFilteredClientList(predicate); | ||
assertCommandSuccess(command, model, expectedMessage, expectedModel); | ||
} | ||
|
||
@Test | ||
public void execute_validSportNoTag_multipleClientsFound() { | ||
String expectedMessage = String.format(MESSAGE_CLIENTS_LISTED_OVERVIEW, 1); | ||
TagAndSportContainsKeywordsPredicate predicate = preparePredicate("", | ||
"dance"); | ||
FilterCommand command = new FilterCommand(predicate); | ||
expectedModel.updateFilteredClientList(predicate); | ||
assertCommandSuccess(command, model, expectedMessage, expectedModel); | ||
} | ||
|
||
/** | ||
* Parses {@code tagInput and @code sportInput} into a {@code TagAndSportContainsKeywordsPredicate}. | ||
*/ | ||
private TagAndSportContainsKeywordsPredicate preparePredicate(String tagInput, String sportInput) { | ||
List<String> tags = new ArrayList<>(); | ||
List<String> sports = new ArrayList<>(); | ||
if (!tagInput.equals("")) { | ||
tags = Arrays.asList(tagInput.split("\\s+")); | ||
} | ||
|
||
if (!sportInput.equals("")) { | ||
sports = Arrays.asList(sportInput.split("\\s+")); | ||
} | ||
return new TagAndSportContainsKeywordsPredicate(tags, sports); | ||
} | ||
|
||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.