@Test public void testQueryLanguageProviderWithProducts() throws IOException { String jsonRequest = getResource("commerce-products-omni-search-request2.json"); String json = getResource("magento-graphql-simple-products.json"); Type type = TypeToken.getParameterized(GraphqlResponse.class, Query.class, Error.class).getType(); GraphqlResponse<Query, Error> response = QueryDeserializer.getGson().fromJson(json, type); List<ProductInterface> products = response.getData().getProducts().getItems(); Mockito.when(graphqlDataService.searchProducts(any(), any(), any(), any(), any())).thenReturn(products); Iterator<Resource> it = queryLanguageProvider.findResources(ctx, jsonRequest, VIRTUAL_PRODUCT_QUERY_LANGUAGE); Mockito.verify(graphqlDataService).searchProducts(eq("gloves"), any(), eq(3), eq(2), any()); assertEquals(2, Iterators.size(it)); }
@Override public Iterator<Resource> findResources(ResolveContext<Object> ctx, String query, String language) { if (!VIRTUAL_PRODUCT_QUERY_LANGUAGE.equals(language)) { return null; } Map<String, Object> queryParameters = stringToMap(query); String fulltext = extractParameter(FULLTEXT_PARAMETER, queryParameters); Integer offset = queryParameters.containsKey(OFFSET_PARAMETER) ? Integer.valueOf(queryParameters.get(OFFSET_PARAMETER).toString()) : Integer.valueOf(0); Integer limit = queryParameters.containsKey(LIMIT_PARAMETER) ? Integer.valueOf(queryParameters.get(LIMIT_PARAMETER).toString()) : Integer.valueOf(20); String commerceType = extractParameter(COMMERCE_TYPE_PARAMETER, queryParameters); if (StringUtils.isBlank(commerceType)) { commerceType = "product"; } LOGGER.debug("Performing product search with '{}' (offset: {}, limit: {})", fulltext, offset, limit); Pair<Integer, Integer> pagination = toMagentoPageNumberAndSize(offset, limit); String categoryIdParam = extractParameter(CATEGORY_ID_PARAMETER, queryParameters); String categoryPathParam = extractParameter(CATEGORY_PATH_PARAMETER, queryParameters); if (StringUtils.isNotBlank(categoryPathParam) && !categoryPathParam.startsWith(resourceMapper.getRoot())) { return Collections.emptyIterator(); } Integer categoryId = null; if (StringUtils.isNotBlank(categoryIdParam)) { try { categoryId = Integer.parseInt(categoryIdParam); } catch (NumberFormatException x) { LOGGER.warn("Invalid root category id {}", categoryIdParam); } } ResourceResolver resolver = ctx.getResourceResolver(); if ("product".equals(commerceType)) { List<ProductInterface> products = graphqlDataService.searchProducts(fulltext, categoryId, pagination.getLeft(), pagination.getRight(), storeView); int start = offset - ((pagination.getLeft() - 1) * pagination.getRight()); int end = start + limit; if (start >= 0 && end <= products.size()) { products = products.subList(start, end); } LOGGER.debug("Returning {} products", products.size()); List<Resource> resources = new ArrayList<>(); String root = resourceMapper.getRoot() + "/"; for (ProductInterface product : products) { List<CategoryInterface> categories = product.getCategories(); String path = root + product.getSku(); if (categories != null && !categories.isEmpty()) { CategoryInterface category = categories.stream() .filter(c -> c.getUrlPath() != null && resourceMapper.resolveCategory(resolver, root + c.getUrlPath()) != null) .findFirst().orElse(null); if (category != null) { path = root + category.getUrlPath() + "/" + product.getSku(); } } resources.add(new ProductResource(resolver, path, product)); } return resources.iterator(); } else if ("category".equals(commerceType)) { List<Resource> resources = new ArrayList<>(); String root = resourceMapper.getRoot() + "/"; List<CategoryTree> categories = graphqlDataService.searchCategories(fulltext, categoryId, pagination.getLeft(), pagination.getRight(), storeView); int start = offset; int end = Math.min(categories.size(), offset + limit); if (start >= 0 && end <= categories.size()) { categories = categories.subList(start, end); } for (CategoryTree category : categories) { String path = root + category.getUrlPath(); resources.add(new CategoryResource(resolver, path, category)); } return resources.iterator(); } else { LOGGER.warn("Unknown commerce type: {}", commerceType); return Collections.emptyIterator(); } }
GraphqlQueryLanguageProvider implements QueryLanguageProvider<Object> { @Override public Iterator<Resource> findResources(ResolveContext<Object> ctx, String query, String language) { if (!VIRTUAL_PRODUCT_QUERY_LANGUAGE.equals(language)) { return null; } Map<String, Object> queryParameters = stringToMap(query); String fulltext = extractParameter(FULLTEXT_PARAMETER, queryParameters); Integer offset = queryParameters.containsKey(OFFSET_PARAMETER) ? Integer.valueOf(queryParameters.get(OFFSET_PARAMETER).toString()) : Integer.valueOf(0); Integer limit = queryParameters.containsKey(LIMIT_PARAMETER) ? Integer.valueOf(queryParameters.get(LIMIT_PARAMETER).toString()) : Integer.valueOf(20); String commerceType = extractParameter(COMMERCE_TYPE_PARAMETER, queryParameters); if (StringUtils.isBlank(commerceType)) { commerceType = "product"; } LOGGER.debug("Performing product search with '{}' (offset: {}, limit: {})", fulltext, offset, limit); Pair<Integer, Integer> pagination = toMagentoPageNumberAndSize(offset, limit); String categoryIdParam = extractParameter(CATEGORY_ID_PARAMETER, queryParameters); String categoryPathParam = extractParameter(CATEGORY_PATH_PARAMETER, queryParameters); if (StringUtils.isNotBlank(categoryPathParam) && !categoryPathParam.startsWith(resourceMapper.getRoot())) { return Collections.emptyIterator(); } Integer categoryId = null; if (StringUtils.isNotBlank(categoryIdParam)) { try { categoryId = Integer.parseInt(categoryIdParam); } catch (NumberFormatException x) { LOGGER.warn("Invalid root category id {}", categoryIdParam); } } ResourceResolver resolver = ctx.getResourceResolver(); if ("product".equals(commerceType)) { List<ProductInterface> products = graphqlDataService.searchProducts(fulltext, categoryId, pagination.getLeft(), pagination.getRight(), storeView); int start = offset - ((pagination.getLeft() - 1) * pagination.getRight()); int end = start + limit; if (start >= 0 && end <= products.size()) { products = products.subList(start, end); } LOGGER.debug("Returning {} products", products.size()); List<Resource> resources = new ArrayList<>(); String root = resourceMapper.getRoot() + "/"; for (ProductInterface product : products) { List<CategoryInterface> categories = product.getCategories(); String path = root + product.getSku(); if (categories != null && !categories.isEmpty()) { CategoryInterface category = categories.stream() .filter(c -> c.getUrlPath() != null && resourceMapper.resolveCategory(resolver, root + c.getUrlPath()) != null) .findFirst().orElse(null); if (category != null) { path = root + category.getUrlPath() + "/" + product.getSku(); } } resources.add(new ProductResource(resolver, path, product)); } return resources.iterator(); } else if ("category".equals(commerceType)) { List<Resource> resources = new ArrayList<>(); String root = resourceMapper.getRoot() + "/"; List<CategoryTree> categories = graphqlDataService.searchCategories(fulltext, categoryId, pagination.getLeft(), pagination.getRight(), storeView); int start = offset; int end = Math.min(categories.size(), offset + limit); if (start >= 0 && end <= categories.size()) { categories = categories.subList(start, end); } for (CategoryTree category : categories) { String path = root + category.getUrlPath(); resources.add(new CategoryResource(resolver, path, category)); } return resources.iterator(); } else { LOGGER.warn("Unknown commerce type: {}", commerceType); return Collections.emptyIterator(); } } }
GraphqlQueryLanguageProvider implements QueryLanguageProvider<Object> { @Override public Iterator<Resource> findResources(ResolveContext<Object> ctx, String query, String language) { if (!VIRTUAL_PRODUCT_QUERY_LANGUAGE.equals(language)) { return null; } Map<String, Object> queryParameters = stringToMap(query); String fulltext = extractParameter(FULLTEXT_PARAMETER, queryParameters); Integer offset = queryParameters.containsKey(OFFSET_PARAMETER) ? Integer.valueOf(queryParameters.get(OFFSET_PARAMETER).toString()) : Integer.valueOf(0); Integer limit = queryParameters.containsKey(LIMIT_PARAMETER) ? Integer.valueOf(queryParameters.get(LIMIT_PARAMETER).toString()) : Integer.valueOf(20); String commerceType = extractParameter(COMMERCE_TYPE_PARAMETER, queryParameters); if (StringUtils.isBlank(commerceType)) { commerceType = "product"; } LOGGER.debug("Performing product search with '{}' (offset: {}, limit: {})", fulltext, offset, limit); Pair<Integer, Integer> pagination = toMagentoPageNumberAndSize(offset, limit); String categoryIdParam = extractParameter(CATEGORY_ID_PARAMETER, queryParameters); String categoryPathParam = extractParameter(CATEGORY_PATH_PARAMETER, queryParameters); if (StringUtils.isNotBlank(categoryPathParam) && !categoryPathParam.startsWith(resourceMapper.getRoot())) { return Collections.emptyIterator(); } Integer categoryId = null; if (StringUtils.isNotBlank(categoryIdParam)) { try { categoryId = Integer.parseInt(categoryIdParam); } catch (NumberFormatException x) { LOGGER.warn("Invalid root category id {}", categoryIdParam); } } ResourceResolver resolver = ctx.getResourceResolver(); if ("product".equals(commerceType)) { List<ProductInterface> products = graphqlDataService.searchProducts(fulltext, categoryId, pagination.getLeft(), pagination.getRight(), storeView); int start = offset - ((pagination.getLeft() - 1) * pagination.getRight()); int end = start + limit; if (start >= 0 && end <= products.size()) { products = products.subList(start, end); } LOGGER.debug("Returning {} products", products.size()); List<Resource> resources = new ArrayList<>(); String root = resourceMapper.getRoot() + "/"; for (ProductInterface product : products) { List<CategoryInterface> categories = product.getCategories(); String path = root + product.getSku(); if (categories != null && !categories.isEmpty()) { CategoryInterface category = categories.stream() .filter(c -> c.getUrlPath() != null && resourceMapper.resolveCategory(resolver, root + c.getUrlPath()) != null) .findFirst().orElse(null); if (category != null) { path = root + category.getUrlPath() + "/" + product.getSku(); } } resources.add(new ProductResource(resolver, path, product)); } return resources.iterator(); } else if ("category".equals(commerceType)) { List<Resource> resources = new ArrayList<>(); String root = resourceMapper.getRoot() + "/"; List<CategoryTree> categories = graphqlDataService.searchCategories(fulltext, categoryId, pagination.getLeft(), pagination.getRight(), storeView); int start = offset; int end = Math.min(categories.size(), offset + limit); if (start >= 0 && end <= categories.size()) { categories = categories.subList(start, end); } for (CategoryTree category : categories) { String path = root + category.getUrlPath(); resources.add(new CategoryResource(resolver, path, category)); } return resources.iterator(); } else { LOGGER.warn("Unknown commerce type: {}", commerceType); return Collections.emptyIterator(); } } GraphqlQueryLanguageProvider(ResourceMapper resourceMapper, GraphqlDataService graphqlDataService, Map<String, String> properties); }
GraphqlQueryLanguageProvider implements QueryLanguageProvider<Object> { @Override public Iterator<Resource> findResources(ResolveContext<Object> ctx, String query, String language) { if (!VIRTUAL_PRODUCT_QUERY_LANGUAGE.equals(language)) { return null; } Map<String, Object> queryParameters = stringToMap(query); String fulltext = extractParameter(FULLTEXT_PARAMETER, queryParameters); Integer offset = queryParameters.containsKey(OFFSET_PARAMETER) ? Integer.valueOf(queryParameters.get(OFFSET_PARAMETER).toString()) : Integer.valueOf(0); Integer limit = queryParameters.containsKey(LIMIT_PARAMETER) ? Integer.valueOf(queryParameters.get(LIMIT_PARAMETER).toString()) : Integer.valueOf(20); String commerceType = extractParameter(COMMERCE_TYPE_PARAMETER, queryParameters); if (StringUtils.isBlank(commerceType)) { commerceType = "product"; } LOGGER.debug("Performing product search with '{}' (offset: {}, limit: {})", fulltext, offset, limit); Pair<Integer, Integer> pagination = toMagentoPageNumberAndSize(offset, limit); String categoryIdParam = extractParameter(CATEGORY_ID_PARAMETER, queryParameters); String categoryPathParam = extractParameter(CATEGORY_PATH_PARAMETER, queryParameters); if (StringUtils.isNotBlank(categoryPathParam) && !categoryPathParam.startsWith(resourceMapper.getRoot())) { return Collections.emptyIterator(); } Integer categoryId = null; if (StringUtils.isNotBlank(categoryIdParam)) { try { categoryId = Integer.parseInt(categoryIdParam); } catch (NumberFormatException x) { LOGGER.warn("Invalid root category id {}", categoryIdParam); } } ResourceResolver resolver = ctx.getResourceResolver(); if ("product".equals(commerceType)) { List<ProductInterface> products = graphqlDataService.searchProducts(fulltext, categoryId, pagination.getLeft(), pagination.getRight(), storeView); int start = offset - ((pagination.getLeft() - 1) * pagination.getRight()); int end = start + limit; if (start >= 0 && end <= products.size()) { products = products.subList(start, end); } LOGGER.debug("Returning {} products", products.size()); List<Resource> resources = new ArrayList<>(); String root = resourceMapper.getRoot() + "/"; for (ProductInterface product : products) { List<CategoryInterface> categories = product.getCategories(); String path = root + product.getSku(); if (categories != null && !categories.isEmpty()) { CategoryInterface category = categories.stream() .filter(c -> c.getUrlPath() != null && resourceMapper.resolveCategory(resolver, root + c.getUrlPath()) != null) .findFirst().orElse(null); if (category != null) { path = root + category.getUrlPath() + "/" + product.getSku(); } } resources.add(new ProductResource(resolver, path, product)); } return resources.iterator(); } else if ("category".equals(commerceType)) { List<Resource> resources = new ArrayList<>(); String root = resourceMapper.getRoot() + "/"; List<CategoryTree> categories = graphqlDataService.searchCategories(fulltext, categoryId, pagination.getLeft(), pagination.getRight(), storeView); int start = offset; int end = Math.min(categories.size(), offset + limit); if (start >= 0 && end <= categories.size()) { categories = categories.subList(start, end); } for (CategoryTree category : categories) { String path = root + category.getUrlPath(); resources.add(new CategoryResource(resolver, path, category)); } return resources.iterator(); } else { LOGGER.warn("Unknown commerce type: {}", commerceType); return Collections.emptyIterator(); } } GraphqlQueryLanguageProvider(ResourceMapper resourceMapper, GraphqlDataService graphqlDataService, Map<String, String> properties); @Override String[] getSupportedLanguages(ResolveContext<Object> paramResolveContext); @Override Iterator<Resource> findResources(ResolveContext<Object> ctx, String query, String language); @Override Iterator<ValueMap> queryResources(ResolveContext<Object> paramResolveContext, String query, String language); }
GraphqlQueryLanguageProvider implements QueryLanguageProvider<Object> { @Override public Iterator<Resource> findResources(ResolveContext<Object> ctx, String query, String language) { if (!VIRTUAL_PRODUCT_QUERY_LANGUAGE.equals(language)) { return null; } Map<String, Object> queryParameters = stringToMap(query); String fulltext = extractParameter(FULLTEXT_PARAMETER, queryParameters); Integer offset = queryParameters.containsKey(OFFSET_PARAMETER) ? Integer.valueOf(queryParameters.get(OFFSET_PARAMETER).toString()) : Integer.valueOf(0); Integer limit = queryParameters.containsKey(LIMIT_PARAMETER) ? Integer.valueOf(queryParameters.get(LIMIT_PARAMETER).toString()) : Integer.valueOf(20); String commerceType = extractParameter(COMMERCE_TYPE_PARAMETER, queryParameters); if (StringUtils.isBlank(commerceType)) { commerceType = "product"; } LOGGER.debug("Performing product search with '{}' (offset: {}, limit: {})", fulltext, offset, limit); Pair<Integer, Integer> pagination = toMagentoPageNumberAndSize(offset, limit); String categoryIdParam = extractParameter(CATEGORY_ID_PARAMETER, queryParameters); String categoryPathParam = extractParameter(CATEGORY_PATH_PARAMETER, queryParameters); if (StringUtils.isNotBlank(categoryPathParam) && !categoryPathParam.startsWith(resourceMapper.getRoot())) { return Collections.emptyIterator(); } Integer categoryId = null; if (StringUtils.isNotBlank(categoryIdParam)) { try { categoryId = Integer.parseInt(categoryIdParam); } catch (NumberFormatException x) { LOGGER.warn("Invalid root category id {}", categoryIdParam); } } ResourceResolver resolver = ctx.getResourceResolver(); if ("product".equals(commerceType)) { List<ProductInterface> products = graphqlDataService.searchProducts(fulltext, categoryId, pagination.getLeft(), pagination.getRight(), storeView); int start = offset - ((pagination.getLeft() - 1) * pagination.getRight()); int end = start + limit; if (start >= 0 && end <= products.size()) { products = products.subList(start, end); } LOGGER.debug("Returning {} products", products.size()); List<Resource> resources = new ArrayList<>(); String root = resourceMapper.getRoot() + "/"; for (ProductInterface product : products) { List<CategoryInterface> categories = product.getCategories(); String path = root + product.getSku(); if (categories != null && !categories.isEmpty()) { CategoryInterface category = categories.stream() .filter(c -> c.getUrlPath() != null && resourceMapper.resolveCategory(resolver, root + c.getUrlPath()) != null) .findFirst().orElse(null); if (category != null) { path = root + category.getUrlPath() + "/" + product.getSku(); } } resources.add(new ProductResource(resolver, path, product)); } return resources.iterator(); } else if ("category".equals(commerceType)) { List<Resource> resources = new ArrayList<>(); String root = resourceMapper.getRoot() + "/"; List<CategoryTree> categories = graphqlDataService.searchCategories(fulltext, categoryId, pagination.getLeft(), pagination.getRight(), storeView); int start = offset; int end = Math.min(categories.size(), offset + limit); if (start >= 0 && end <= categories.size()) { categories = categories.subList(start, end); } for (CategoryTree category : categories) { String path = root + category.getUrlPath(); resources.add(new CategoryResource(resolver, path, category)); } return resources.iterator(); } else { LOGGER.warn("Unknown commerce type: {}", commerceType); return Collections.emptyIterator(); } } GraphqlQueryLanguageProvider(ResourceMapper resourceMapper, GraphqlDataService graphqlDataService, Map<String, String> properties); @Override String[] getSupportedLanguages(ResolveContext<Object> paramResolveContext); @Override Iterator<Resource> findResources(ResolveContext<Object> ctx, String query, String language); @Override Iterator<ValueMap> queryResources(ResolveContext<Object> paramResolveContext, String query, String language); static final String CATEGORY_ID_PARAMETER; static final String CATEGORY_PATH_PARAMETER; }