package productcatalog.services; import io.sphere.sdk.categories.Category; import io.sphere.sdk.client.PlayJavaSphereClient; import io.sphere.sdk.products.ProductProjection; import io.sphere.sdk.products.ProductVariant; import io.sphere.sdk.products.queries.ProductProjectionQuery; import io.sphere.sdk.products.search.ProductProjectionSearch; import io.sphere.sdk.queries.PagedQueryResult; import io.sphere.sdk.queries.PagedResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import play.libs.F; import javax.inject.Inject; import java.util.*; public class ProductProjectionServiceImpl implements ProductProjectionService { private static final Random RANDOM = new Random(); private static final Logger LOGGER = LoggerFactory.getLogger(ProductProjectionServiceImpl.class); private final PlayJavaSphereClient sphere; @Inject public ProductProjectionServiceImpl(final PlayJavaSphereClient sphere) { this.sphere = sphere; } public F.Promise<List<ProductProjection>> searchProducts(final int page, final int pageSize) { final int offset = (page - 1) * pageSize; return sphere.execute(ProductProjectionSearch.ofCurrent() .withOffset(offset) .withLimit(pageSize)) .map(PagedResult::getResults); } public F.Promise<Optional<ProductProjection>> searchProductBySlug(final Locale locale, final String slug) { final F.Promise<Optional<ProductProjection>> productOptionalPromise = sphere.execute(ProductProjectionQuery.ofCurrent().bySlug(locale, slug)) .map(PagedQueryResult::head); productOptionalPromise.onRedeem(productOptional -> { if (productOptional.isPresent()) { LOGGER.trace("Found product for slug {} in locale {} with ID {}.", slug, locale, productOptional.get().getId()); } else { LOGGER.trace("No product found for slug {} in locale {}.", slug, locale); } }); return productOptionalPromise; } public F.Promise<List<ProductProjection>> getSuggestions(final List<Category> categories, final int numSuggestions) { final ProductProjectionQuery productProjectionQuery = ProductProjectionQuery.ofCurrent() .withPredicates(p -> p.categories().isIn(categories)); return sphere.execute(productProjectionQuery) .map(PagedQueryResult::getResults) .map(results -> pickNRandom(results, numSuggestions)); } private boolean variantHasSku(final ProductVariant variant, final String sku) { return Optional.ofNullable(variant.getSku()).map(variantSku -> variantSku.equals(sku)).orElse(false); } private <T> List<T> pickNRandom(final List<T> elements, final int n) { return pickNRandom(RANDOM, elements, n); } private <T> List<T> pickNRandom(final Random random, final List<T> elements, final int n) { if(elements.size() < n) { return pickNRandom(elements, elements.size()); } final List<T> picked = new ArrayList<>(n); for(int i = 0; i < n; i++) { final int index = random.nextInt(elements.size()); picked.add(elements.get(index)); elements.remove(index); } return picked; } }