Skip to content

Commit

Permalink
Merge pull request nus-cs2103-AY2021S1#107 from zhengweii/find-wareho…
Browse files Browse the repository at this point in the history
…use-command

Find warehouse command
  • Loading branch information
tohyuting authored Oct 11, 2020
2 parents fb9b1c2 + 3c33317 commit 74575af
Show file tree
Hide file tree
Showing 25 changed files with 381 additions and 108 deletions.
2 changes: 1 addition & 1 deletion docs/UserGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ and efficient Graphical User Interface interaction.

--------------------------------------------------------------------------------------------------------------------

## Quick startf
## Quick start

1. Ensure you have Java `11` or above installed in your Computer.

Expand Down
58 changes: 45 additions & 13 deletions src/main/java/seedu/clinic/logic/commands/FindCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,73 @@

import static java.util.Objects.requireNonNull;

import java.util.Optional;

import seedu.clinic.commons.core.Messages;
import seedu.clinic.model.Model;
import seedu.clinic.model.attribute.NameContainsKeywordsPredicateForSupplier;
import seedu.clinic.model.supplier.SupplierProductsContainKeywordsPredicate;
import seedu.clinic.model.warehouse.WarehouseProductsContainKeywordsPredicate;

/**
* Finds and lists all suppliers/warehouses in the CLI-nic app whose name contains any of the argument keywords.
* Finds and lists all suppliers/warehouses in the CLI-nic app that sell/hold products matching any of the argument
* keywords.
* Keyword matching is case insensitive.
* Keyword only matches whole word e.g. band will match "band aid" but not "bandaid".
*/
public class FindCommand extends Command {

public static final String COMMAND_WORD = "find";

public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all suppliers 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 suppliers/warehouses that sell/hold products"
+ "matching the specified keywords (case-insensitive) and displays them as a list with index numbers.\n"
+ "Parameters: TYPE KEYWORD [MORE_KEYWORDS...]\n"
+ "Example: " + COMMAND_WORD + " supplier panadol"
+ "Example: " + COMMAND_WORD + " warehouse face mask";

private final Optional<SupplierProductsContainKeywordsPredicate> supplierPredicate;
private final Optional<WarehouseProductsContainKeywordsPredicate> warehousePredicate;

private final NameContainsKeywordsPredicateForSupplier predicate;
/**
* Constructs a new FindCommand object.
*
* @param supplierPredicate takes in the predicate used to filter a supplier's products.
*/
public FindCommand(SupplierProductsContainKeywordsPredicate supplierPredicate) {
this.supplierPredicate = Optional.of(supplierPredicate);
this.warehousePredicate = Optional.empty();
}

public FindCommand(NameContainsKeywordsPredicateForSupplier predicate) {
this.predicate = predicate;
/**
* Constructs a new FindCommand object.
*
* @param warehousePredicate takes in the predicate used to filter a warehouse's products.
*/
public FindCommand(WarehouseProductsContainKeywordsPredicate warehousePredicate) {
this.warehousePredicate = Optional.of(warehousePredicate);
this.supplierPredicate = Optional.empty();
}

@Override
public CommandResult execute(Model model) {
requireNonNull(model);
model.updateFilteredSupplierList(predicate);
return new CommandResult(
String.format(Messages.MESSAGE_SUPPLIERS_LISTED_OVERVIEW, model.getFilteredSupplierList().size()));

if (supplierPredicate.isPresent()) {
model.updateFilteredSupplierList(supplierPredicate.get());
return new CommandResult(
String.format(Messages.MESSAGE_SUPPLIERS_LISTED_OVERVIEW, model.getFilteredSupplierList().size()));
} else {
model.updateFilteredWarehouseList(warehousePredicate.get());
return new CommandResult(
String.format(Messages.MESSAGE_WAREHOUSE_LISTED_OVERVIEW, model.getFilteredWarehouseList().size()));
}
}

@Override
public boolean equals(Object other) {
return other == this // short circuit if same object
|| (other instanceof FindCommand // instanceof handles nulls
&& predicate.equals(((FindCommand) other).predicate)); // state check
&& (supplierPredicate.isPresent()
? supplierPredicate.equals(((FindCommand) other).supplierPredicate)
: warehousePredicate.equals(((FindCommand) other).warehousePredicate)));
}
}
20 changes: 17 additions & 3 deletions src/main/java/seedu/clinic/logic/parser/FindCommandParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
import static seedu.clinic.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;

import java.util.Arrays;
import java.util.List;

import seedu.clinic.logic.commands.FindCommand;
import seedu.clinic.logic.parser.exceptions.ParseException;
import seedu.clinic.model.attribute.NameContainsKeywordsPredicateForSupplier;
import seedu.clinic.model.supplier.SupplierProductsContainKeywordsPredicate;
import seedu.clinic.model.warehouse.WarehouseProductsContainKeywordsPredicate;

/**
* Parses input arguments and creates a new FindCommand object
Expand All @@ -25,9 +27,21 @@ public FindCommand parse(String args) throws ParseException {
String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE));
}

String[] nameKeywords = trimmedArgs.split("\\s+");
String[] productNameKeywords = trimmedArgs.split("\\s+");
String type = productNameKeywords[0].toLowerCase();

return new FindCommand(new NameContainsKeywordsPredicateForSupplier(Arrays.asList(nameKeywords)));
// Ensures that the user enters the type and at least 1 keyword
if (!(type.equals("supplier") || type.equals("warehouse")) || productNameKeywords.length < 2) {
throw new ParseException(
String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE));
}

List<String> keywords = Arrays.asList(productNameKeywords);
if (type.equals("supplier")) {
return new FindCommand(new SupplierProductsContainKeywordsPredicate(keywords));
} else {
return new FindCommand(new WarehouseProductsContainKeywordsPredicate(keywords));
}
}

}
3 changes: 1 addition & 2 deletions src/main/java/seedu/clinic/model/attribute/Name.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@ public class Name {
public static final String MESSAGE_CONSTRAINTS =
"Names should only contain alphanumeric characters and spaces, and it should not be blank";

/*
/**
* The first character of the name must be alphanumeric.
* The .
*/
public static final String VALIDATION_REGEX = "[\\p{Alnum}][\\p{Print}]*";

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package seedu.clinic.model.supplier;

import java.util.List;
import java.util.function.Predicate;

import seedu.clinic.commons.util.StringUtil;
import seedu.clinic.model.product.Product;

/**
* Tests that any of the {@code Product} sold by {@code Supplier} matches any of the keywords given.
*/
public class SupplierProductsContainKeywordsPredicate implements Predicate<Supplier> {
private final List<String> keywords;

public SupplierProductsContainKeywordsPredicate(List<String> keywords) {
this.keywords = keywords;
}

@Override
public boolean test(Supplier supplier) {
Product[] products = supplier.getProducts().toArray(Product[]::new);
for (int i = 0; i < products.length; i++) {
String productName = products[i].getProductName().fullName;
boolean match = keywords.stream()
.anyMatch(keyword -> StringUtil.containsWordIgnoreCase(productName, keyword));

if (match) {
return true;
}
}

return false;
}

@Override
public boolean equals(Object other) {
return other == this // short circuit if same object
|| (other instanceof SupplierProductsContainKeywordsPredicate // instanceof handles nulls
&& keywords.equals(((SupplierProductsContainKeywordsPredicate) other).keywords)); // state check
}

}
30 changes: 14 additions & 16 deletions src/main/java/seedu/clinic/model/util/SampleDataUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,45 +26,45 @@ public static Supplier[] getSampleSuppliers() {
return new Supplier[] {
new Supplier(new Name("Alex Yeoh Ltd"), new Phone("87438807"), new Email("alexyeoh@example.com"),
new Remark("long term partner"),
getProductSet(Map.of("Panadol", new String[]{"fever"}))),
getProductSet(new HashSet<Product>(), Map.of("Panadol", new String[]{"fever"}))),
new Supplier(new Name("Bernice Yu Pte Ltd"), new Phone("99272758"), new Email("berniceyu@example.com"),
new Remark("long term partner"),
getProductSet(Map.of("Panadol", new String[]{"fever"}))),
getProductSet(new HashSet<Product>(), Map.of("Panadol", new String[]{"fever"}))),
new Supplier(new Name("Charlotte Oliveiro Ltd"), new Phone("93210283"), new Email("charlotte@example.com"),
new Remark("long term partner"),
getProductSet(Map.of("Panadol", new String[]{"fever"}))),
getProductSet(new HashSet<Product>(), Map.of("Panadol", new String[]{"fever"}))),
new Supplier(new Name("David Li Pte Ltd"), new Phone("91031282"), new Email("lidavid@example.com"),
new Remark("long term partner"),
getProductSet(Map.of("Panadol", new String[]{"fever"}))),
getProductSet(new HashSet<Product>(), Map.of("Panadol", new String[]{"fever"}))),
new Supplier(new Name("Irfan Ibrahim Pte Ltd"), new Phone("92492021"), new Email("irfan@example.com"),
new Remark("long term partner"),
getProductSet(Map.of("Panadol", new String[]{"fever"}))),
getProductSet(new HashSet<Product>(), Map.of("Panadol", new String[]{"fever"}))),
new Supplier(new Name("Roy Balakrishnan Pte Ltd"), new Phone("92624417"), new Email("royb@example.com"),
new Remark("long term partner"),
getProductSet(Map.of("Panadol", new String[]{"fever"}))),
getProductSet(new HashSet<Product>(), Map.of("Panadol", new String[]{"fever"}))),
};
}

public static Warehouse[] getSampleWarehouses() {
return new Warehouse[] {
new Warehouse(new Name("Alex Yeoh warehouse"), new Phone("87438807"),
new Address("21 Lower Kent Ridge Rd, Singapore 119077"), new Remark("long term partner"),
getProductSetForWarehouse(Map.of("Panadol", 10))),
getProductSetForWarehouse(new HashSet<Product>(), Map.of("Panadol", 10))),
new Warehouse(new Name("Bernice Yu warehouse"), new Phone("99272758"),
new Address("21 Lower Kent Ridge Rd, Singapore 119077"), new Remark("long term partner"),
getProductSetForWarehouse(Map.of("Panadol", 20))),
getProductSetForWarehouse(new HashSet<Product>(), Map.of("Panadol", 20))),
new Warehouse(new Name("Charlotte Oliveiro warehouse"), new Phone("93210283"),
new Address("21 Lower Kent Ridge Rd, Singapore 119077"), new Remark("long term partner"),
getProductSetForWarehouse(Map.of("Panadol", 30))),
getProductSetForWarehouse(new HashSet<Product>(), Map.of("Panadol", 30))),
new Warehouse(new Name("David Li warehouse"), new Phone("91031282"),
new Address("21 Lower Kent Ridge Rd, Singapore 119077"), new Remark("long term partner"),
getProductSetForWarehouse(Map.of("Panadol", 100))),
getProductSetForWarehouse(new HashSet<Product>(), Map.of("Panadol", 100))),
new Warehouse(new Name("Irfan Ibrahim warehouse"), new Phone("92492021"),
new Address("21 Lower Kent Ridge Rd, Singapore 119077"), new Remark("long term partner"),
getProductSetForWarehouse(Map.of("Panadol", 50))),
getProductSetForWarehouse(new HashSet<Product>(), Map.of("Panadol", 50))),
new Warehouse(new Name("Roy Balakrishnan warehouse"), new Phone("92624417"),
new Address("21 Lower Kent Ridge Rd, Singapore 119077"), new Remark("long term partner"),
getProductSetForWarehouse(Map.of("Panadol", 70))),
getProductSetForWarehouse(new HashSet<Product>(), Map.of("Panadol", 70))),
};
}

Expand Down Expand Up @@ -93,8 +93,7 @@ public static Set<Tag> getTagSet(String... strings) {
/**
* Returns a product set containing the hashmap of strings given.
*/
public static Set<Product> getProductSet(Map<String, String[]> productMap) {
Set<Product> productSet = new HashSet<>();
public static Set<Product> getProductSet(Set<Product> productSet, Map<String, String[]> productMap) {
for (String productName:productMap.keySet()) {
Set<Tag> productTags = getTagSet(productMap.get(productName));
Product product = new Product(new Name(productName), productTags);
Expand All @@ -106,8 +105,7 @@ public static Set<Product> getProductSet(Map<String, String[]> productMap) {
/**
* Returns a product set containing the hashmap of strings given.
*/
public static Set<Product> getProductSetForWarehouse(Map<String, Integer> productMap) {
Set<Product> productSet = new HashSet<>();
public static Set<Product> getProductSetForWarehouse(Set<Product> productSet, Map<String, Integer> productMap) {
for (String productName:productMap.keySet()) {
Product product = new Product(new Name(productName), productMap.get(productName));
productSet.add(product);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package seedu.clinic.model.warehouse;

import java.util.List;
import java.util.function.Predicate;

import seedu.clinic.commons.util.StringUtil;
import seedu.clinic.model.product.Product;

/**
* Tests that any of the {@code Product} stored in a {@code Warehouse} matches any of the keywords given.
*/
public class WarehouseProductsContainKeywordsPredicate implements Predicate<Warehouse> {
private final List<String> keywords;

public WarehouseProductsContainKeywordsPredicate(List<String> keywords) {
this.keywords = keywords;
}

@Override
public boolean test(Warehouse warehouse) {
Product[] products = warehouse.getProducts().toArray(Product[]::new);
for (int i = 0; i < products.length; i++) {
String productName = products[i].getProductName().fullName;
boolean match = keywords.stream()
.anyMatch(keyword -> StringUtil.containsWordIgnoreCase(productName, keyword));

if (match) {
return true;
}
}

return false;
}

@Override
public boolean equals(Object other) {
return other == this // short circuit if same object
|| (other instanceof WarehouseProductsContainKeywordsPredicate // instanceof handles nulls
&& keywords.equals(((WarehouseProductsContainKeywordsPredicate) other).keywords)); // state check
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"name": "Supplier with invalid name field: Ha!ns Mu@ster",
"phone": "9482424",
"email": "hans@example.com",
"remark": "Trusted company"
"remark": "Trusted seller"
} ],
"warehouse": [ ]
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
"name": "@ invalid name warehouse",
"phone": "9482424",
"address": "hans address",
"remark": "Trusted company"
"remark": "Biggest warehouse"
} ]
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"name" : "Alice Pauline Ltd",
"phone" : "98765432",
"address" : "johnd address",
"remark" : "trusted warehouse",
"remark" : "biggest warehouse",
"products": [ {
"name": "Panadol",
"quantity": 20
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,13 @@
"phone" : "95352563",
"email" : "heinz@example.com",
"remark" : "nearby",
"products" : [ ]
"products" : [{
"name": "Mask",
"tagged": ["black"]
}, {
"name": "Thermometer",
"tagged": ["digital"]
}]
}, {
"name" : "Daniel Meier Ltd",
"phone" : "87652533",
Expand All @@ -38,13 +44,28 @@
"phone" : "9482224",
"email" : "werner@example.com",
"remark" : "industry leader",
"products" : [ ]
"products" : [{
"name": "Mask",
"tagged": ["black"]
}, {
"name": "Medical Glove",
"tagged": ["rubber"]
}]
}, {
"name" : "Fiona Kunz Ltd",
"phone" : "9482427",
"email" : "lydia@example.com",
"remark" : "specialises in antibiotics",
"products" : [ ]
"products" : [{
"name": "Mask",
"tagged": ["black"]
}, {
"name": "Needle",
"tagged": ["1mm"]
}, {
"name": "Cough Syrup",
"tagged": ["cough"]
}]
}, {
"name" : "George Best Ltd",
"phone" : "9482442",
Expand Down
Loading

0 comments on commit 74575af

Please sign in to comment.