blob: 522219dff56ae18bd074a6e1f922909764027669 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.ofbiz.product.product;
import java.io.IOException;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.ofbiz.base.util.Debug;
import org.apache.ofbiz.base.util.UtilDateTime;
import org.apache.ofbiz.base.util.UtilGenerics;
import org.apache.ofbiz.base.util.UtilHttp;
import org.apache.ofbiz.base.util.UtilMisc;
import org.apache.ofbiz.base.util.UtilValidate;
import org.apache.ofbiz.entity.Delegator;
import org.apache.ofbiz.entity.GenericEntityException;
import org.apache.ofbiz.entity.GenericValue;
import org.apache.ofbiz.entity.condition.EntityCondition;
import org.apache.ofbiz.entity.condition.EntityOperator;
import org.apache.ofbiz.entity.model.DynamicViewEntity;
import org.apache.ofbiz.entity.model.ModelKeyMap;
import org.apache.ofbiz.entity.util.EntityListIterator;
import org.apache.ofbiz.entity.util.EntityQuery;
import org.apache.ofbiz.entity.util.EntityUtilProperties;
import org.apache.ofbiz.product.catalog.CatalogWorker;
import org.apache.ofbiz.product.category.CategoryWorker;
import org.apache.ofbiz.product.feature.ParametricSearch;
import org.apache.ofbiz.product.product.ProductSearch.CategoryConstraint;
import org.apache.ofbiz.product.product.ProductSearch.FeatureConstraint;
import org.apache.ofbiz.product.product.ProductSearch.KeywordConstraint;
import org.apache.ofbiz.product.product.ProductSearch.ProductSearchConstraint;
import org.apache.ofbiz.product.product.ProductSearch.ProductSearchContext;
import org.apache.ofbiz.product.product.ProductSearch.ResultSortOrder;
import org.apache.ofbiz.product.product.ProductSearch.SortKeywordRelevancy;
import org.apache.ofbiz.product.store.ProductStoreWorker;
import org.apache.ofbiz.webapp.control.RequestHandler;
import org.apache.ofbiz.webapp.stats.VisitHandler;
/**
* Utility class with methods to prepare and perform ProductSearch operations in the content of an HttpSession
*/
public class ProductSearchSession {
public static final String module = ProductSearchSession.class.getName();
@SuppressWarnings("serial")
public static class ProductSearchOptions implements java.io.Serializable {
protected List<ProductSearchConstraint> constraintList = null;
protected String topProductCategoryId = null;
protected ResultSortOrder resultSortOrder = null;
protected Integer viewIndex = null;
protected Integer viewSize = null;
protected boolean changed = false;
protected String paging = "Y";
protected Integer previousViewSize = null;
public ProductSearchOptions() { }
/** Basic copy constructor */
public ProductSearchOptions(ProductSearchOptions productSearchOptions) {
this.constraintList = new LinkedList<ProductSearch.ProductSearchConstraint>();
if (UtilValidate.isNotEmpty(productSearchOptions.constraintList)) {
this.constraintList.addAll(productSearchOptions.constraintList);
}
this.topProductCategoryId = productSearchOptions.topProductCategoryId;
this.resultSortOrder = productSearchOptions.resultSortOrder;
this.viewIndex = productSearchOptions.viewIndex;
this.viewSize = productSearchOptions.viewSize;
this.changed = productSearchOptions.changed;
this.paging = productSearchOptions.paging;
this.previousViewSize = productSearchOptions.previousViewSize;
}
public List<ProductSearchConstraint> getConstraintList() {
return this.constraintList;
}
public static List<ProductSearchConstraint> getConstraintList(HttpSession session) {
return getProductSearchOptions(session).constraintList;
}
public static void addConstraint(ProductSearchConstraint productSearchConstraint, HttpSession session) {
ProductSearchOptions productSearchOptions = getProductSearchOptions(session);
if (productSearchOptions.constraintList == null) {
productSearchOptions.constraintList = new LinkedList<ProductSearch.ProductSearchConstraint>();
}
if (!productSearchOptions.constraintList.contains(productSearchConstraint)) {
productSearchOptions.constraintList.add(productSearchConstraint);
productSearchOptions.changed = true;
}
}
public ResultSortOrder getResultSortOrder() {
if (this.resultSortOrder == null) {
this.resultSortOrder = new SortKeywordRelevancy();
this.changed = true;
}
return this.resultSortOrder;
}
public static ResultSortOrder getResultSortOrder(HttpServletRequest request) {
ProductSearchOptions productSearchOptions = getProductSearchOptions(request.getSession());
return productSearchOptions.getResultSortOrder();
}
public static void setResultSortOrder(ResultSortOrder resultSortOrder, HttpSession session) {
ProductSearchOptions productSearchOptions = getProductSearchOptions(session);
productSearchOptions.resultSortOrder = resultSortOrder;
productSearchOptions.changed = true;
}
public static void clearSearchOptions(HttpSession session) {
ProductSearchOptions productSearchOptions = getProductSearchOptions(session);
productSearchOptions.constraintList = null;
productSearchOptions.topProductCategoryId = null;
productSearchOptions.resultSortOrder = null;
}
public void clearViewInfo() {
this.viewIndex = null;
this.viewSize = null;
this.paging = "Y";
this.previousViewSize = null;
}
/**
* Get the view size
* @return returns the viewIndex.
*/
public Integer getViewIndex() {
return viewIndex;
}
/**
* Set the view index
* @param viewIndex the viewIndex to set.
*/
public void setViewIndex(Integer viewIndex) {
this.viewIndex = viewIndex;
}
/**
* Set the view index
* @param viewIndexStr the viewIndex to set.
*/
public void setViewIndex(String viewIndexStr) {
if (UtilValidate.isEmpty(viewIndexStr)) {
return;
}
try {
this.setViewIndex(Integer.valueOf(viewIndexStr));
} catch (Exception e) {
Debug.logError(e, "Error in formatting of VIEW_INDEX [" + viewIndexStr + "], setting to 20", module);
if (this.viewIndex == null) {
this.setViewIndex(Integer.valueOf(20));
}
}
}
/**
* Get the view size
* @return returns the view size.
*/
public Integer getViewSize() {
return viewSize;
}
/**
* Set the view size
* @param viewSize the view size to set.
*/
public void setViewSize(Integer viewSize) {
setPreviousViewSize(getViewSize());
this.viewSize = viewSize;
}
/**
* Set the view size
* @param viewSizeStr the view size to set.
*/
public void setViewSize(String viewSizeStr) {
if (UtilValidate.isEmpty(viewSizeStr)) {
return;
}
try {
this.setViewSize(Integer.valueOf(viewSizeStr));
} catch (Exception e) {
Debug.logError(e, "Error in formatting of VIEW_SIZE [" + viewSizeStr + "], setting to 20", module);
if (this.viewSize == null) {
this.setViewSize(Integer.valueOf(20));
}
}
}
/**
* Get the paging
* @return Returns the paging
*/
public String getPaging() {
return paging;
}
/**
* Set the paging
* @param paging the paging to set
*/
public void setPaging(String paging) {
if (paging == null) {
paging = "Y";
}
this.paging = paging;
}
/**
* Get the previous view size
* @return returns the previous view size
*/
public Integer getPreviousViewSize() {
return previousViewSize;
}
/**
* Set the previous view size
* @param previousViewSize the previousViewSize to set.
*/
public void setPreviousViewSize(Integer previousViewSize) {
if (previousViewSize == null) {
this.previousViewSize = Integer.valueOf(20);
} else {
this.previousViewSize = previousViewSize;
}
}
public String getTopProductCategoryId() {
return topProductCategoryId;
}
public static void setTopProductCategoryId(String topProductCategoryId, HttpSession session) {
ProductSearchOptions productSearchOptions = getProductSearchOptions(session);
productSearchOptions.setTopProductCategoryId(topProductCategoryId);
}
public void setTopProductCategoryId(String topProductCategoryId) {
if (this.topProductCategoryId != null && topProductCategoryId != null) {
if (!this.topProductCategoryId.equals(topProductCategoryId)) {
this.topProductCategoryId = topProductCategoryId;
this.changed = true;
}
} else {
if (this.topProductCategoryId != null || topProductCategoryId != null) {
this.topProductCategoryId = topProductCategoryId;
this.changed = true;
}
}
}
public List<String> searchGetConstraintStrings(boolean detailed, Delegator delegator, Locale locale) {
List<ProductSearchConstraint> productSearchConstraintList = this.getConstraintList();
List<String> constraintStrings = new LinkedList<String>();
if (productSearchConstraintList == null) {
return constraintStrings;
}
for (ProductSearchConstraint productSearchConstraint: productSearchConstraintList) {
if (productSearchConstraint == null) continue;
String constraintString = productSearchConstraint.prettyPrintConstraint(delegator, detailed, locale);
if (UtilValidate.isNotEmpty(constraintString)) {
constraintStrings.add(constraintString);
} else {
constraintStrings.add("Description not available");
}
}
return constraintStrings;
}
}
public static ProductSearchOptions getProductSearchOptions(HttpSession session) {
ProductSearchOptions productSearchOptions = (ProductSearchOptions) session.getAttribute("_PRODUCT_SEARCH_OPTIONS_CURRENT_");
if (productSearchOptions == null) {
productSearchOptions = new ProductSearchOptions();
session.setAttribute("_PRODUCT_SEARCH_OPTIONS_CURRENT_", productSearchOptions);
}
return productSearchOptions;
}
public static void checkSaveSearchOptionsHistory(HttpSession session) {
ProductSearchOptions productSearchOptions = getProductSearchOptions(session);
// if the options have changed since the last search, add it to the beginning of the search options history
if (productSearchOptions.changed) {
List<ProductSearchOptions> optionsHistoryList = getSearchOptionsHistoryList(session);
optionsHistoryList.add(0, new ProductSearchOptions(productSearchOptions));
productSearchOptions.changed = false;
}
}
public static List<ProductSearchOptions> getSearchOptionsHistoryList(HttpSession session) {
List<ProductSearchOptions> optionsHistoryList = UtilGenerics.checkList(session.getAttribute("_PRODUCT_SEARCH_OPTIONS_HISTORY_"));
if (optionsHistoryList == null) {
optionsHistoryList = new LinkedList<ProductSearchSession.ProductSearchOptions>();
session.setAttribute("_PRODUCT_SEARCH_OPTIONS_HISTORY_", optionsHistoryList);
}
return optionsHistoryList;
}
public static void clearSearchOptionsHistoryList(HttpSession session) {
session.removeAttribute("_PRODUCT_SEARCH_OPTIONS_HISTORY_");
}
public static void setCurrentSearchFromHistory(int index, boolean removeOld, HttpSession session) {
List<ProductSearchOptions> searchOptionsHistoryList = getSearchOptionsHistoryList(session);
if (index < searchOptionsHistoryList.size()) {
ProductSearchOptions productSearchOptions = searchOptionsHistoryList.get(index);
if (removeOld) {
searchOptionsHistoryList.remove(index);
}
if (productSearchOptions != null) {
session.setAttribute("_PRODUCT_SEARCH_OPTIONS_CURRENT_", new ProductSearchOptions(productSearchOptions));
}
} else {
throw new IllegalArgumentException("Could not set current search options to history index [" + index + "], only [" + searchOptionsHistoryList.size() + "] entries in the history list.");
}
}
public static String clearSearchOptionsHistoryList(HttpServletRequest request, HttpServletResponse response) {
HttpSession session = request.getSession();
clearSearchOptionsHistoryList(session);
return "success";
}
public static String setCurrentSearchFromHistory(HttpServletRequest request, HttpServletResponse response) {
HttpSession session = request.getSession();
String searchHistoryIndexStr = request.getParameter("searchHistoryIndex");
String removeOldStr = request.getParameter("removeOld");
if (UtilValidate.isEmpty(searchHistoryIndexStr)) {
request.setAttribute("_ERROR_MESSAGE_", "No search history index passed, cannot set current search to previous.");
return "error";
}
try {
int searchHistoryIndex = Integer.parseInt(searchHistoryIndexStr);
boolean removeOld = true;
if (UtilValidate.isNotEmpty(removeOldStr)) {
removeOld = !"false".equals(removeOldStr);
}
setCurrentSearchFromHistory(searchHistoryIndex, removeOld, session);
} catch (Exception e) {
request.setAttribute("_ERROR_MESSAGE_", e.toString());
return "error";
}
return "success";
}
/** A ControlServlet event method used to check to see if there is an override for any of the current keywords in the search */
public static final String checkDoKeywordOverride(HttpServletRequest request, HttpServletResponse response) {
HttpSession session = request.getSession();
Delegator delegator = (Delegator) request.getAttribute("delegator");
Map<String, Object> requestParams = UtilHttp.getParameterMap(request);
// get the current productStoreId
String productStoreId = ProductStoreWorker.getProductStoreId(request);
if (productStoreId != null) {
// get a Set of all keywords in the search, if there are any...
Set<String> keywords = new HashSet<String>();
List<ProductSearchConstraint> constraintList = ProductSearchOptions.getConstraintList(session);
if (constraintList != null) {
for (ProductSearchConstraint constraint: constraintList) {
if (constraint instanceof KeywordConstraint) {
KeywordConstraint keywordConstraint = (KeywordConstraint) constraint;
Set<String> keywordSet = keywordConstraint.makeFullKeywordSet(delegator);
if (keywordSet != null) keywords.addAll(keywordSet);
}
}
}
if (keywords.size() > 0) {
List<GenericValue> productStoreKeywordOvrdList = null;
try {
productStoreKeywordOvrdList = EntityQuery.use(delegator).from("ProductStoreKeywordOvrd").where("productStoreId", productStoreId).orderBy("-fromDate").cache(true).filterByDate().queryList();
} catch (GenericEntityException e) {
Debug.logError(e, "Error reading ProductStoreKeywordOvrd list, not doing keyword override", module);
}
if (UtilValidate.isNotEmpty(productStoreKeywordOvrdList)) {
for (GenericValue productStoreKeywordOvrd: productStoreKeywordOvrdList) {
String ovrdKeyword = productStoreKeywordOvrd.getString("keyword");
if (keywords.contains(ovrdKeyword)) {
String targetTypeEnumId = productStoreKeywordOvrd.getString("targetTypeEnumId");
String target = productStoreKeywordOvrd.getString("target");
ServletContext ctx = (ServletContext) request.getAttribute("servletContext");
RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");
if ("KOTT_PRODCAT".equals(targetTypeEnumId)) {
String requestName = "/category/~category_id=" + target;
target = rh.makeLink(request, response, requestName, false, false, false);
} else if ("KOTT_PRODUCT".equals(targetTypeEnumId)) {
String requestName = "/product/~product_id=" + target;
target = rh.makeLink(request, response, requestName, false, false, false);
} else if ("KOTT_OFBURL".equals(targetTypeEnumId)) {
target = rh.makeLink(request, response, target, false, false, false);
} else if ("KOTT_AURL".equals(targetTypeEnumId)) {
// do nothing, is absolute URL
} else {
Debug.logError("The targetTypeEnumId [] is not recognized, not doing keyword override", module);
// might as well see if there are any others...
continue;
}
try {
response.sendRedirect(target);
return "none";
} catch (IOException e) {
Debug.logError(e, "Could not send redirect to: " + target, module);
continue;
}
}
}
}
}
}
return "success";
}
public static ArrayList<String> searchDo(HttpSession session, Delegator delegator, String prodCatalogId) {
String visitId = VisitHandler.getVisitId(session);
ProductSearchOptions productSearchOptions = getProductSearchOptions(session);
List<ProductSearchConstraint> productSearchConstraintList = productSearchOptions.getConstraintList();
if (UtilValidate.isEmpty(productSearchConstraintList)) {
// no constraints, don't do a search...
return new ArrayList<String>();
}
ResultSortOrder resultSortOrder = productSearchOptions.getResultSortOrder();
// if the search options have changed since the last search, put at the beginning of the options history list
checkSaveSearchOptionsHistory(session);
return ProductSearch.searchProducts(productSearchConstraintList, resultSortOrder, delegator, visitId);
}
public static void searchClear(HttpSession session) {
ProductSearchOptions.clearSearchOptions(session);
}
public static List<String> searchGetConstraintStrings(boolean detailed, HttpSession session, Delegator delegator) {
Locale locale = UtilHttp.getLocale(session);
ProductSearchOptions productSearchOptions = getProductSearchOptions(session);
return productSearchOptions.searchGetConstraintStrings(detailed, delegator, locale);
}
public static String searchGetSortOrderString(boolean detailed, HttpServletRequest request) {
Locale locale = UtilHttp.getLocale(request);
ResultSortOrder resultSortOrder = ProductSearchOptions.getResultSortOrder(request);
if (resultSortOrder == null) return "";
return resultSortOrder.prettyPrintSortOrder(detailed, locale);
}
public static void searchSetSortOrder(ResultSortOrder resultSortOrder, HttpSession session) {
ProductSearchOptions.setResultSortOrder(resultSortOrder, session);
}
public static void searchAddFeatureIdConstraints(Collection<String> featureIds, Boolean exclude, HttpServletRequest request) {
HttpSession session = request.getSession();
if (UtilValidate.isEmpty(featureIds)) {
return;
}
for (String productFeatureId: featureIds) {
searchAddConstraint(new FeatureConstraint(productFeatureId, exclude), session);
}
}
public static void searchAddConstraint(ProductSearchConstraint productSearchConstraint, HttpSession session) {
ProductSearchOptions.addConstraint(productSearchConstraint, session);
}
public static void searchRemoveConstraint(int index, HttpSession session) {
List<ProductSearchConstraint> productSearchConstraintList = ProductSearchOptions.getConstraintList(session);
if (productSearchConstraintList == null) {
return;
} else if (index >= productSearchConstraintList.size()) {
return;
} else {
productSearchConstraintList.remove(index);
}
}
public static void processSearchParameters(Map<String, Object> parameters, HttpServletRequest request) {
Delegator delegator = (Delegator) request.getAttribute("delegator");
Boolean alreadyRun = (Boolean) request.getAttribute("processSearchParametersAlreadyRun");
if (Boolean.TRUE.equals(alreadyRun)) {
return;
} else {
request.setAttribute("processSearchParametersAlreadyRun", Boolean.TRUE);
}
HttpSession session = request.getSession();
boolean constraintsChanged = false;
GenericValue productStore = ProductStoreWorker.getProductStore(request);
// clear search? by default yes, but if the clearSearch parameter is N then don't
String clearSearchString = (String) parameters.get("clearSearch");
if (!"N".equals(clearSearchString)) {
searchClear(session);
constraintsChanged = true;
} else {
String removeConstraint = (String) parameters.get("removeConstraint");
if (UtilValidate.isNotEmpty(removeConstraint)) {
try {
searchRemoveConstraint(Integer.parseInt(removeConstraint), session);
constraintsChanged = true;
} catch (Exception e) {
Debug.logError(e, "Error removing constraint [" + removeConstraint + "]", module);
}
}
}
String prioritizeCategoryId = null;
if (UtilValidate.isNotEmpty(parameters.get("PRIORITIZE_CATEGORY_ID"))) {
prioritizeCategoryId = (String) parameters.get("PRIORITIZE_CATEGORY_ID");
} else if (UtilValidate.isNotEmpty(parameters.get("S_TPC"))) {
prioritizeCategoryId = (String) parameters.get("S_TPC");
}
if (UtilValidate.isNotEmpty(prioritizeCategoryId)) {
ProductSearchOptions.setTopProductCategoryId(prioritizeCategoryId, session);
constraintsChanged = true;
}
// if there is another category, add a constraint for it
if (UtilValidate.isNotEmpty(parameters.get("SEARCH_CATEGORY_ID"))) {
String searchCategoryId = (String) parameters.get("SEARCH_CATEGORY_ID");
String searchSubCategories = (String) parameters.get("SEARCH_SUB_CATEGORIES");
String searchCategoryExc = (String) parameters.get("SEARCH_CATEGORY_EXC");
Boolean exclude = UtilValidate.isEmpty(searchCategoryExc) ? null : Boolean.valueOf(!"N".equals(searchCategoryExc));
searchAddConstraint(new ProductSearch.CategoryConstraint(searchCategoryId, !"N".equals(searchSubCategories), exclude), session);
constraintsChanged = true;
}
for (int catNum = 1; catNum < 10; catNum++) {
if (UtilValidate.isNotEmpty(parameters.get("SEARCH_CATEGORY_ID" + catNum))) {
String searchCategoryId = (String) parameters.get("SEARCH_CATEGORY_ID" + catNum);
String searchSubCategories = (String) parameters.get("SEARCH_SUB_CATEGORIES" + catNum);
String searchCategoryExc = (String) parameters.get("SEARCH_CATEGORY_EXC" + catNum);
Boolean exclude = UtilValidate.isEmpty(searchCategoryExc) ? null : Boolean.valueOf(!"N".equals(searchCategoryExc));
searchAddConstraint(new ProductSearch.CategoryConstraint(searchCategoryId, !"N".equals(searchSubCategories), exclude), session);
constraintsChanged = true;
}
}
// a shorter variation for categories
for (int catNum = 1; catNum < 10; catNum++) {
if (UtilValidate.isNotEmpty(parameters.get("S_CAT" + catNum))) {
String searchCategoryId = (String) parameters.get("S_CAT" + catNum);
String searchSubCategories = (String) parameters.get("S_CSB" + catNum);
String searchCategoryExc = (String) parameters.get("S_CEX" + catNum);
Boolean exclude = UtilValidate.isEmpty(searchCategoryExc) ? null : Boolean.valueOf(!"N".equals(searchCategoryExc));
searchAddConstraint(new ProductSearch.CategoryConstraint(searchCategoryId, !"N".equals(searchSubCategories), exclude), session);
constraintsChanged = true;
}
}
// if there is any category selected try to use catalog and add a constraint for it
if (UtilValidate.isNotEmpty(parameters.get("SEARCH_CATALOG_ID"))) {
String searchCatalogId = (String) parameters.get("SEARCH_CATALOG_ID");
if (searchCatalogId != null && !searchCatalogId.equalsIgnoreCase("")) {
String topCategory = CatalogWorker.getCatalogTopCategoryId(request, searchCatalogId);
if (UtilValidate.isEmpty(topCategory)) {
topCategory = CatalogWorker.getCatalogTopEbayCategoryId(request, searchCatalogId);
}
List<GenericValue> categories = CategoryWorker.getRelatedCategoriesRet(request, "topLevelList", topCategory, true, false, true);
searchAddConstraint(new ProductSearch.CatalogConstraint(searchCatalogId, categories), session);
constraintsChanged = true;
}
}
// if keywords were specified, add a constraint for them
if (UtilValidate.isNotEmpty(parameters.get("SEARCH_STRING"))) {
String keywordString = (String) parameters.get("SEARCH_STRING");
String searchOperator = (String) parameters.get("SEARCH_OPERATOR");
// defaults to true/Y, ie anything but N is true/Y
boolean anyPrefixSuffix = !"N".equals(parameters.get("SEARCH_ANYPRESUF"));
searchAddConstraint(new ProductSearch.KeywordConstraint(keywordString, anyPrefixSuffix, anyPrefixSuffix, null, "AND".equals(searchOperator)), session);
constraintsChanged = true;
}
// if productName were specified, add a constraint for them
if (UtilValidate.isNotEmpty(parameters.get("SEARCH_PRODUCT_NAME"))) {
String productName = (String) parameters.get("SEARCH_PRODUCT_NAME");
searchAddConstraint(new ProductSearch.ProductFieldConstraint(productName, "productName"), session);
constraintsChanged = true;
}
// if internalName were specified, add a constraint for them
if (UtilValidate.isNotEmpty(parameters.get("SEARCH_INTERNAL_PROD_NAME"))) {
String internalName = (String) parameters.get("SEARCH_INTERNAL_PROD_NAME");
searchAddConstraint(new ProductSearch.ProductFieldConstraint(internalName, "internalName"), session);
constraintsChanged = true;
}
for (int kwNum = 1; kwNum < 10; kwNum++) {
if (UtilValidate.isNotEmpty(parameters.get("SEARCH_STRING" + kwNum))) {
String keywordString = (String) parameters.get("SEARCH_STRING" + kwNum);
String searchOperator = (String) parameters.get("SEARCH_OPERATOR" + kwNum);
// defaults to true/Y, ie anything but N is true/Y
boolean anyPrefixSuffix = !"N".equals(parameters.get("SEARCH_ANYPRESUF" + kwNum));
searchAddConstraint(new ProductSearch.KeywordConstraint(keywordString, anyPrefixSuffix, anyPrefixSuffix, null, "AND".equals(searchOperator)), session);
constraintsChanged = true;
}
}
for (String parameterName: parameters.keySet()) {
if (parameterName.startsWith("SEARCH_FEAT") && !parameterName.startsWith("SEARCH_FEAT_EXC")) {
String productFeatureId = (String) parameters.get(parameterName);
if (UtilValidate.isNotEmpty(productFeatureId)) {
String paramNameExt = parameterName.substring("SEARCH_FEAT".length());
String searchCategoryExc = (String) parameters.get("SEARCH_FEAT_EXC" + paramNameExt);
Boolean exclude = UtilValidate.isEmpty(searchCategoryExc) ? null : Boolean.valueOf(!"N".equals(searchCategoryExc));
//Debug.logInfo("parameterName=" + parameterName + ", paramNameExt=" + paramNameExt + ", searchCategoryExc=" + searchCategoryExc + ", exclude=" + exclude, module);
searchAddConstraint(new ProductSearch.FeatureConstraint(productFeatureId, exclude), session);
constraintsChanged = true;
}
}
// a shorter feature variation
if (parameterName.startsWith("S_PFI")) {
String productFeatureId = (String) parameters.get(parameterName);
if (UtilValidate.isNotEmpty(productFeatureId)) {
String paramNameExt = parameterName.substring("S_PFI".length());
String searchCategoryExc = (String) parameters.get("S_PFX" + paramNameExt);
Boolean exclude = UtilValidate.isEmpty(searchCategoryExc) ? null : Boolean.valueOf(!"N".equals(searchCategoryExc));
searchAddConstraint(new ProductSearch.FeatureConstraint(productFeatureId, exclude), session);
constraintsChanged = true;
}
}
//if product features category were selected add a constraint for each
if (parameterName.startsWith("SEARCH_PROD_FEAT_CAT") && !parameterName.startsWith("SEARCH_PROD_FEAT_CAT_EXC")) {
String productFeatureCategoryId = (String) parameters.get(parameterName);
if (UtilValidate.isNotEmpty(productFeatureCategoryId)) {
String paramNameExt = parameterName.substring("SEARCH_PROD_FEAT_CAT".length());
String searchProdFeatureCategoryExc = (String) parameters.get("SEARCH_PROD_FEAT_CAT_EXC" + paramNameExt);
Boolean exclude = UtilValidate.isEmpty(searchProdFeatureCategoryExc) ? null : Boolean.valueOf(!"N".equals(searchProdFeatureCategoryExc));
searchAddConstraint(new ProductSearch.FeatureCategoryConstraint(productFeatureCategoryId, exclude), session);
constraintsChanged = true;
}
}
// a shorter variation for feature category
if (parameterName.startsWith("S_FCI")) {
String productFeatureCategoryId = (String) parameters.get(parameterName);
if (UtilValidate.isNotEmpty(productFeatureCategoryId)) {
String paramNameExt = parameterName.substring("S_FCI".length());
String searchProdFeatureCategoryExc = (String) parameters.get("S_FCX" + paramNameExt);
Boolean exclude = UtilValidate.isEmpty(searchProdFeatureCategoryExc) ? null : Boolean.valueOf(!"N".equals(searchProdFeatureCategoryExc));
searchAddConstraint(new ProductSearch.FeatureCategoryConstraint(productFeatureCategoryId, exclude), session);
constraintsChanged = true;
}
}
//if product features group were selected add a constraint for each
if (parameterName.startsWith("SEARCH_PROD_FEAT_GRP") && !parameterName.startsWith("SEARCH_PROD_FEAT_GRP_EXC")) {
String productFeatureGroupId = (String) parameters.get(parameterName);
if (UtilValidate.isNotEmpty(productFeatureGroupId)) {
String paramNameExt = parameterName.substring("SEARCH_PROD_FEAT_GRP".length());
String searchProdFeatureGroupExc = (String) parameters.get("SEARCH_PROD_FEAT_GRP_EXC" + paramNameExt);
Boolean exclude = UtilValidate.isEmpty(searchProdFeatureGroupExc) ? null : Boolean.valueOf(!"N".equals(searchProdFeatureGroupExc));
searchAddConstraint(new ProductSearch.FeatureGroupConstraint(productFeatureGroupId, exclude), session);
constraintsChanged = true;
}
}
// a shorter variation for feature group
if (parameterName.startsWith("S_FGI")) {
String productFeatureGroupId = (String) parameters.get(parameterName);
if (UtilValidate.isNotEmpty(productFeatureGroupId)) {
String paramNameExt = parameterName.substring("S_FGI".length());
String searchProdFeatureGroupExc = (String) parameters.get("S_FGX" + paramNameExt);
Boolean exclude = UtilValidate.isEmpty(searchProdFeatureGroupExc) ? null : Boolean.valueOf(!"N".equals(searchProdFeatureGroupExc));
searchAddConstraint(new ProductSearch.FeatureGroupConstraint(productFeatureGroupId, exclude), session);
constraintsChanged = true;
}
}
}
// if features were selected add a constraint for each
Map<String, String> featureIdByType = ParametricSearch.makeFeatureIdByTypeMap(parameters);
if (featureIdByType.size() > 0) {
constraintsChanged = true;
searchAddFeatureIdConstraints(featureIdByType.values(), null, request);
}
// add a supplier to the search
if (UtilValidate.isNotEmpty(parameters.get("SEARCH_SUPPLIER_ID")) || UtilValidate.isNotEmpty(parameters.get("S_SUP"))) {
String supplierPartyId = (String) parameters.get("SEARCH_SUPPLIER_ID");
if (UtilValidate.isEmpty(supplierPartyId)) supplierPartyId = (String) parameters.get("S_SUP");
searchAddConstraint(new ProductSearch.SupplierConstraint(supplierPartyId), session);
constraintsChanged = true;
}
// add a list price range to the search
if (UtilValidate.isNotEmpty(parameters.get("LIST_PRICE_LOW")) || UtilValidate.isNotEmpty(parameters.get("LIST_PRICE_HIGH"))) {
BigDecimal listPriceLow = null;
BigDecimal listPriceHigh = null;
String listPriceCurrency = UtilHttp.getCurrencyUom(request);
if (UtilValidate.isNotEmpty(parameters.get("LIST_PRICE_LOW"))) {
try {
listPriceLow = new BigDecimal((String) parameters.get("LIST_PRICE_LOW"));
} catch (NumberFormatException e) {
Debug.logError("Error parsing LIST_PRICE_LOW parameter [" + (String) parameters.get("LIST_PRICE_LOW") + "]: " + e.toString(), module);
}
}
if (UtilValidate.isNotEmpty(parameters.get("LIST_PRICE_HIGH"))) {
try {
listPriceHigh = new BigDecimal((String) parameters.get("LIST_PRICE_HIGH"));
} catch (NumberFormatException e) {
Debug.logError("Error parsing LIST_PRICE_HIGH parameter [" + (String) parameters.get("LIST_PRICE_HIGH") + "]: " + e.toString(), module);
}
}
searchAddConstraint(new ProductSearch.ListPriceRangeConstraint(listPriceLow, listPriceHigh, listPriceCurrency), session);
constraintsChanged = true;
}
if (UtilValidate.isNotEmpty(parameters.get("LIST_PRICE_RANGE")) || UtilValidate.isNotEmpty(parameters.get("S_LPR"))) {
String listPriceRangeStr = (String) parameters.get("LIST_PRICE_RANGE");
if (UtilValidate.isEmpty(listPriceRangeStr)) listPriceRangeStr = (String) parameters.get("S_LPR");
int underscoreIndex = listPriceRangeStr.indexOf("_");
String listPriceLowStr;
String listPriceHighStr;
if (underscoreIndex >= 0) {
listPriceLowStr = listPriceRangeStr.substring(0, listPriceRangeStr.indexOf("_"));
listPriceHighStr = listPriceRangeStr.substring(listPriceRangeStr.indexOf("_") + 1);
} else {
// no underscore: assume it is a low range with no high range, ie the ending underscore was left off
listPriceLowStr = listPriceRangeStr;
listPriceHighStr = null;
}
BigDecimal listPriceLow = null;
BigDecimal listPriceHigh = null;
String listPriceCurrency = UtilHttp.getCurrencyUom(request);
if (UtilValidate.isNotEmpty(listPriceLowStr)) {
try {
listPriceLow = new BigDecimal(listPriceLowStr);
} catch (NumberFormatException e) {
Debug.logError("Error parsing low part of LIST_PRICE_RANGE parameter [" + listPriceLowStr + "]: " + e.toString(), module);
}
}
if (UtilValidate.isNotEmpty(listPriceHighStr)) {
try {
listPriceHigh = new BigDecimal(listPriceHighStr);
} catch (NumberFormatException e) {
Debug.logError("Error parsing high part of LIST_PRICE_RANGE parameter [" + listPriceHighStr + "]: " + e.toString(), module);
}
}
searchAddConstraint(new ProductSearch.ListPriceRangeConstraint(listPriceLow, listPriceHigh, listPriceCurrency), session);
constraintsChanged = true;
}
// check the ProductStore to see if we should add the ExcludeVariantsConstraint
if (productStore != null && !"N".equals(productStore.getString("prodSearchExcludeVariants"))) {
searchAddConstraint(new ProductSearch.ExcludeVariantsConstraint(), session);
// not consider this a change for now, shouldn't change often: constraintsChanged = true;
}
if ("true".equalsIgnoreCase((String) parameters.get("AVAILABILITY_FILTER"))) {
searchAddConstraint(new ProductSearch.AvailabilityDateConstraint(), session);
constraintsChanged = true;
}
if (UtilValidate.isNotEmpty(parameters.get("SEARCH_GOOD_IDENTIFICATION_TYPE")) ||
UtilValidate.isNotEmpty(parameters.get("SEARCH_GOOD_IDENTIFICATION_VALUE"))) {
String include = (String) parameters.get("SEARCH_GOOD_IDENTIFICATION_INCL");
if (UtilValidate.isEmpty(include)) {
include = "Y";
}
Boolean inc = Boolean.TRUE;
if ("N".equalsIgnoreCase(include)) {
inc = Boolean.FALSE;
}
searchAddConstraint(new ProductSearch.GoodIdentificationConstraint((String)parameters.get("SEARCH_GOOD_IDENTIFICATION_TYPE"),
(String) parameters.get("SEARCH_GOOD_IDENTIFICATION_VALUE"), inc), session);
constraintsChanged = true;
}
String prodCatalogId = CatalogWorker.getCurrentCatalogId(request);
String viewProductCategoryId = CatalogWorker.getCatalogViewAllowCategoryId(delegator, prodCatalogId);
if (UtilValidate.isNotEmpty(viewProductCategoryId)) {
ProductSearchConstraint viewAllowConstraint = new CategoryConstraint(viewProductCategoryId, true, null);
searchAddConstraint(viewAllowConstraint, session);
// not consider this a change for now, shouldn't change often: constraintsChanged = true;
}
// set the sort order
String sortOrder = (String) parameters.get("sortOrder");
if (UtilValidate.isEmpty(sortOrder)) sortOrder = (String) parameters.get("S_O");
String sortAscending = (String) parameters.get("sortAscending");
if (UtilValidate.isEmpty(sortAscending)) sortAscending = (String) parameters.get("S_A");
boolean ascending = !"N".equals(sortAscending);
if (sortOrder != null) {
if (sortOrder.equals("SortKeywordRelevancy") || sortOrder.equals("SKR")) {
searchSetSortOrder(new ProductSearch.SortKeywordRelevancy(), session);
} else if (sortOrder.startsWith("SortProductField:")) {
String fieldName = sortOrder.substring("SortProductField:".length());
searchSetSortOrder(new ProductSearch.SortProductField(fieldName, ascending), session);
} else if (sortOrder.startsWith("SPF:")) {
String fieldName = sortOrder.substring("SPF:".length());
searchSetSortOrder(new ProductSearch.SortProductField(fieldName, ascending), session);
} else if (sortOrder.startsWith("SortProductPrice:")) {
String priceTypeId = sortOrder.substring("SortProductPrice:".length());
searchSetSortOrder(new ProductSearch.SortProductPrice(priceTypeId, ascending), session);
} else if (sortOrder.startsWith("SPP:")) {
String priceTypeId = sortOrder.substring("SPP:".length());
searchSetSortOrder(new ProductSearch.SortProductPrice(priceTypeId, ascending), session);
} else if (sortOrder.startsWith("SortProductFeature:")) {
String featureId = sortOrder.substring("SortProductFeature:".length());
searchSetSortOrder(new ProductSearch.SortProductFeature(featureId, ascending), session);
} else if (sortOrder.startsWith("SPFT:")) {
String priceTypeId = sortOrder.substring("SPFT:".length());
searchSetSortOrder(new ProductSearch.SortProductPrice(priceTypeId, ascending), session);
}
}
ProductSearchOptions productSearchOptions = getProductSearchOptions(session);
if (constraintsChanged) {
// query changed, clear out the VIEW_INDEX & VIEW_SIZE
productSearchOptions.clearViewInfo();
}
productSearchOptions.setViewIndex((String) parameters.get("VIEW_INDEX"));
productSearchOptions.setViewSize((String) parameters.get("VIEW_SIZE"));
productSearchOptions.setPaging((String) parameters.get("PAGING"));
}
@SuppressWarnings("unchecked")
public static Map<String, Object> getProductSearchResult(HttpServletRequest request, Delegator delegator, String prodCatalogId) {
// ========== Create View Indexes
int viewIndex = 0;
int viewSize = 20;
int highIndex = 0;
int lowIndex = 0;
int listSize = 0;
String paging = "Y";
int previousViewSize = 20;
Map<String, Object> requestParams = UtilHttp.getCombinedMap(request);
List<String> keywordTypeIds = new LinkedList<String>();
if (requestParams.get("keywordTypeId") instanceof String) {
keywordTypeIds.add((String) requestParams.get("keywordTypeId"));
} else if (requestParams.get("keywordTypeId") instanceof List){
keywordTypeIds = (List<String>) requestParams.get("keywordTypeId");
}
String statusId = (String) requestParams.get("statusId");
HttpSession session = request.getSession();
ProductSearchOptions productSearchOptions = getProductSearchOptions(session);
String addOnTopProdCategoryId = productSearchOptions.getTopProductCategoryId();
Integer viewIndexInteger = productSearchOptions.getViewIndex();
if (viewIndexInteger != null) {
viewIndex = viewIndexInteger.intValue();
}
Integer viewSizeInteger = productSearchOptions.getViewSize();
if (viewSizeInteger != null) {
viewSize = viewSizeInteger.intValue();
}
Integer previousViewSizeInteger = productSearchOptions.getPreviousViewSize();
if (previousViewSizeInteger != null) {
previousViewSize = previousViewSizeInteger.intValue();
}
String pag = productSearchOptions.getPaging();
if (paging != null) {
paging = pag;
}
lowIndex = viewIndex * viewSize;
highIndex = (viewIndex + 1) * viewSize;
// ========== Do the actual search
List<String> productIds = new LinkedList<String>();
String visitId = VisitHandler.getVisitId(session);
List<ProductSearchConstraint> productSearchConstraintList = ProductSearchOptions.getConstraintList(session);
String noConditionFind = (String) requestParams.get("noConditionFind");
if (UtilValidate.isEmpty(noConditionFind)) {
noConditionFind = EntityUtilProperties.getPropertyValue("widget", "widget.defaultNoConditionFind", delegator);
}
// if noConditionFind to Y then find without conditions otherwise search according to constraints.
if ("Y".equals(noConditionFind) || UtilValidate.isNotEmpty(productSearchConstraintList)) {
// if the search options have changed since the last search, put at the beginning of the options history list
checkSaveSearchOptionsHistory(session);
int addOnTopTotalListSize = 0;
int addOnTopListSize = 0;
List<GenericValue> addOnTopProductCategoryMembers = new LinkedList<GenericValue>();
if (UtilValidate.isNotEmpty(addOnTopProdCategoryId)) {
// always include the members of the addOnTopProdCategoryId
Timestamp now = UtilDateTime.nowTimestamp();
List<EntityCondition> addOnTopProdCondList = new LinkedList<EntityCondition>();
addOnTopProdCondList.add(EntityCondition.makeCondition(EntityCondition.makeCondition("thruDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition("thruDate", EntityOperator.GREATER_THAN, now)));
addOnTopProdCondList.add(EntityCondition.makeCondition("fromDate", EntityOperator.LESS_THAN, now));
addOnTopProdCondList.add(EntityCondition.makeCondition("productCategoryId", EntityOperator.EQUALS, addOnTopProdCategoryId));
EntityListIterator pli = null;
try {
pli = EntityQuery.use(delegator).select(UtilMisc.toSet("productId", "sequenceNum"))
.from("ProductCategoryMember")
.where(addOnTopProdCondList)
.orderBy("sequenceNum")
.cursorScrollInsensitive()
.distinct()
.maxRows(highIndex)
.queryIterator();
addOnTopProductCategoryMembers = pli.getPartialList(lowIndex, viewSize);
addOnTopListSize = addOnTopProductCategoryMembers.size();
for (GenericValue alwaysAddProductCategoryMember: addOnTopProductCategoryMembers) {
productIds.add(alwaysAddProductCategoryMember.getString("productId"));
}
addOnTopTotalListSize = pli.getResultsSizeAfterPartialList();
listSize = listSize + addOnTopTotalListSize;
} catch (GenericEntityException e) {
Debug.logError(e, module);
} finally {
if (pli != null) {
try {
pli.close();
} catch (GenericEntityException e) {
Debug.logError(e, module);
}
}
}
}
// setup resultOffset and maxResults, noting that resultOffset is 1 based, not zero based as these numbers
int resultOffsetInt = lowIndex - addOnTopTotalListSize + 1;
if (resultOffsetInt < 1) {
resultOffsetInt = 1;
}
int maxResultsInt = viewSize - addOnTopListSize;
Integer resultOffset = Integer.valueOf(resultOffsetInt);
Integer maxResults = Integer.valueOf(maxResultsInt);
ResultSortOrder resultSortOrder = ProductSearchOptions.getResultSortOrder(request);
ProductSearchContext productSearchContext = new ProductSearchContext(delegator, visitId);
if (UtilValidate.isNotEmpty(productSearchConstraintList)) {
productSearchContext.addProductSearchConstraints(productSearchConstraintList);
}
productSearchContext.setResultSortOrder(resultSortOrder);
productSearchContext.setResultOffset(resultOffset);
productSearchContext.setMaxResults(maxResults);
if (UtilValidate.isNotEmpty(keywordTypeIds)) {
productSearchContext.keywordTypeIds = keywordTypeIds;
} else {
productSearchContext.keywordTypeIds = UtilMisc.toList("KWT_KEYWORD");
}
if (UtilValidate.isNotEmpty(statusId)) {
productSearchContext.statusId = statusId;
}
List<String> foundProductIds = productSearchContext.doSearch();
if (maxResultsInt > 0) {
productIds.addAll(foundProductIds);
}
Integer totalResults = productSearchContext.getTotalResults();
if (totalResults != null) {
listSize = listSize + totalResults.intValue();
}
}
if (listSize < highIndex) {
highIndex = listSize;
}
// ========== Setup other display info
List<String> searchConstraintStrings = searchGetConstraintStrings(false, session, delegator);
String searchSortOrderString = searchGetSortOrderString(false, request);
// ========== populate the result Map
Map<String, Object> result = new HashMap<String, Object>();
result.put("productIds", productIds);
result.put("viewIndex", Integer.valueOf(viewIndex));
result.put("viewSize", Integer.valueOf(viewSize));
result.put("listSize", Integer.valueOf(listSize));
result.put("lowIndex", Integer.valueOf(lowIndex));
result.put("highIndex", Integer.valueOf(highIndex));
result.put("paging", paging);
result.put("previousViewSize", previousViewSize);
result.put("searchConstraintStrings", searchConstraintStrings);
result.put("searchSortOrderString", searchSortOrderString);
result.put("noConditionFind", noConditionFind);
return result;
}
public static String makeSearchParametersString(HttpSession session) {
return makeSearchParametersString(getProductSearchOptions(session));
}
public static String makeSearchParametersString(ProductSearchOptions productSearchOptions) {
StringBuilder searchParamString = new StringBuilder();
List<ProductSearchConstraint> constraintList = productSearchOptions.getConstraintList();
if (UtilValidate.isEmpty(constraintList)) {
constraintList = new ArrayList<ProductSearchConstraint>();
}
int categoriesCount = 0;
int featuresCount = 0;
int featureCategoriesCount = 0;
int featureGroupsCount = 0;
int keywordsCount = 0;
boolean isNotFirst = false;
for (ProductSearchConstraint psc: constraintList) {
if (psc instanceof ProductSearch.CategoryConstraint) {
ProductSearch.CategoryConstraint cc = (ProductSearch.CategoryConstraint) psc;
categoriesCount++;
if (isNotFirst) {
searchParamString.append("&amp;");
} else {
isNotFirst = true;
}
searchParamString.append("S_CAT");
searchParamString.append(categoriesCount);
searchParamString.append("=");
searchParamString.append(cc.productCategoryId);
searchParamString.append("&amp;S_CSB");
searchParamString.append(categoriesCount);
searchParamString.append("=");
searchParamString.append(cc.includeSubCategories ? "Y" : "N");
if (cc.exclude != null) {
searchParamString.append("&amp;S_CEX");
searchParamString.append(categoriesCount);
searchParamString.append("=");
searchParamString.append(cc.exclude.booleanValue() ? "Y" : "N");
}
} else if (psc instanceof ProductSearch.FeatureConstraint) {
ProductSearch.FeatureConstraint fc = (ProductSearch.FeatureConstraint) psc;
featuresCount++;
if (isNotFirst) {
searchParamString.append("&amp;");
} else {
isNotFirst = true;
}
searchParamString.append("S_PFI");
searchParamString.append(featuresCount);
searchParamString.append("=");
searchParamString.append(fc.productFeatureId);
if (fc.exclude != null) {
searchParamString.append("&amp;S_PFX");
searchParamString.append(featuresCount);
searchParamString.append("=");
searchParamString.append(fc.exclude.booleanValue() ? "Y" : "N");
}
} else if (psc instanceof ProductSearch.FeatureCategoryConstraint) {
ProductSearch.FeatureCategoryConstraint pfcc = (ProductSearch.FeatureCategoryConstraint) psc;
featureCategoriesCount++;
if (isNotFirst) {
searchParamString.append("&amp;");
} else {
isNotFirst = true;
}
searchParamString.append("S_FCI");
searchParamString.append(featureCategoriesCount);
searchParamString.append("=");
searchParamString.append(pfcc.productFeatureCategoryId);
if (pfcc.exclude != null) {
searchParamString.append("&amp;S_FCX");
searchParamString.append(featureCategoriesCount);
searchParamString.append("=");
searchParamString.append(pfcc.exclude.booleanValue() ? "Y" : "N");
}
} else if (psc instanceof ProductSearch.FeatureGroupConstraint) {
ProductSearch.FeatureGroupConstraint pfgc = (ProductSearch.FeatureGroupConstraint) psc;
featureGroupsCount++;
if (isNotFirst) {
searchParamString.append("&amp;");
} else {
isNotFirst = true;
}
searchParamString.append("S_FGI");
searchParamString.append(featureGroupsCount);
searchParamString.append("=");
searchParamString.append(pfgc.productFeatureGroupId);
if (pfgc.exclude != null) {
searchParamString.append("&amp;S_FGX");
searchParamString.append(featureGroupsCount);
searchParamString.append("=");
searchParamString.append(pfgc.exclude.booleanValue() ? "Y" : "N");
}
} else if (psc instanceof ProductSearch.KeywordConstraint) {
ProductSearch.KeywordConstraint kc = (ProductSearch.KeywordConstraint) psc;
keywordsCount++;
if (isNotFirst) {
searchParamString.append("&amp;");
} else {
isNotFirst = true;
}
searchParamString.append("SEARCH_STRING");
searchParamString.append(keywordsCount);
searchParamString.append("=");
searchParamString.append(UtilHttp.encodeBlanks(kc.keywordsString));
searchParamString.append("&amp;SEARCH_OPERATOR");
searchParamString.append(keywordsCount);
searchParamString.append("=");
searchParamString.append(kc.isAnd ? "AND" : "OR");
searchParamString.append("&amp;SEARCH_ANYPRESUF");
searchParamString.append(keywordsCount);
searchParamString.append("=");
searchParamString.append(kc.anyPrefix | kc.anySuffix ? "Y" : "N");
} else if (psc instanceof ProductSearch.ListPriceRangeConstraint) {
ProductSearch.ListPriceRangeConstraint lprc = (ProductSearch.ListPriceRangeConstraint) psc;
if (lprc.lowPrice != null || lprc.highPrice != null) {
if (isNotFirst) {
searchParamString.append("&amp;");
} else {
isNotFirst = true;
}
searchParamString.append("S_LPR");
searchParamString.append("=");
if (lprc.lowPrice != null) searchParamString.append(lprc.lowPrice);
searchParamString.append("_");
if (lprc.highPrice != null) searchParamString.append(lprc.highPrice);
}
} else if (psc instanceof ProductSearch.SupplierConstraint) {
ProductSearch.SupplierConstraint suppc = (ProductSearch.SupplierConstraint) psc;
if (suppc.supplierPartyId != null) {
if (isNotFirst) {
searchParamString.append("&amp;");
} else {
isNotFirst = true;
}
searchParamString.append("S_SUP");
searchParamString.append("=");
searchParamString.append(suppc.supplierPartyId);
}
}
}
String topProductCategoryId = productSearchOptions.getTopProductCategoryId();
if (topProductCategoryId != null) {
searchParamString.append("&amp;S_TPC");
searchParamString.append("=");
searchParamString.append(topProductCategoryId);
}
ResultSortOrder resultSortOrder = productSearchOptions.getResultSortOrder();
if (resultSortOrder != null) {
if (resultSortOrder instanceof ProductSearch.SortKeywordRelevancy) {
searchParamString.append("&amp;S_O=SKR");
} else if (resultSortOrder instanceof ProductSearch.SortProductField) {
ProductSearch.SortProductField spf = (ProductSearch.SortProductField) resultSortOrder;
searchParamString.append("&amp;S_O=SPF:");
searchParamString.append(spf.fieldName);
} else if (resultSortOrder instanceof ProductSearch.SortProductPrice) {
ProductSearch.SortProductPrice spp = (ProductSearch.SortProductPrice) resultSortOrder;
searchParamString.append("&amp;S_O=SPP:");
searchParamString.append(spp.productPriceTypeId);
} else if (resultSortOrder instanceof ProductSearch.SortProductFeature) {
ProductSearch.SortProductFeature spf = (ProductSearch.SortProductFeature) resultSortOrder;
searchParamString.append("&amp;S_O=SPFT:");
searchParamString.append(spf.productFeatureTypeId);
}
searchParamString.append("&amp;S_A=");
searchParamString.append(resultSortOrder.isAscending() ? "Y" : "N");
}
return searchParamString.toString();
}
/**
* This method returns a list of productId counts grouped by productFeatureId's of input productFeatureTypeId,
* the constraint being applied on current ProductSearchConstraint list in session.
* @param productFeatureTypeId The productFeatureTypeId, productFeatureId's of which should be considered.
* @param session Current session.
* @param delegator The delegator object.
* @return List of Maps containing productFeatureId, productFeatureTypeId, description, featureCount.
*/
public static List<Map<String, String>> listCountByFeatureForType(String productFeatureTypeId, HttpSession session, Delegator delegator) {
String visitId = VisitHandler.getVisitId(session);
ProductSearchContext productSearchContext = new ProductSearchContext(delegator, visitId);
List<ProductSearchConstraint> productSearchConstraintList = ProductSearchOptions.getConstraintList(session);
if (UtilValidate.isNotEmpty(productSearchConstraintList)) {
productSearchContext.addProductSearchConstraints(productSearchConstraintList);
}
productSearchContext.finishKeywordConstraints();
productSearchContext.finishCategoryAndFeatureConstraints();
DynamicViewEntity dynamicViewEntity = productSearchContext.dynamicViewEntity;
List<EntityCondition> entityConditionList = productSearchContext.entityConditionList;
dynamicViewEntity.addMemberEntity("PFAC", "ProductFeatureAppl");
dynamicViewEntity.addAlias("PFAC", "pfacProductFeatureId", "productFeatureId", null, null, Boolean.TRUE, null);
dynamicViewEntity.addAlias("PFAC", "pfacFromDate", "fromDate", null, null, null, null);
dynamicViewEntity.addAlias("PFAC", "pfacThruDate", "thruDate", null, null, null, null);
dynamicViewEntity.addAlias("PFAC", "featureCount", "productId", null, null, null, "count-distinct");
dynamicViewEntity.addViewLink("PROD", "PFAC", Boolean.FALSE, ModelKeyMap.makeKeyMapList("productId"));
entityConditionList.add(EntityCondition.makeCondition(EntityCondition.makeCondition("pfacThruDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition("pfacThruDate", EntityOperator.GREATER_THAN, UtilDateTime.nowTimestamp())));
entityConditionList.add(EntityCondition.makeCondition("pfacFromDate", EntityOperator.LESS_THAN, UtilDateTime.nowTimestamp()));
dynamicViewEntity.addMemberEntity("PFC", "ProductFeature");
dynamicViewEntity.addAlias("PFC", "pfcProductFeatureTypeId", "productFeatureTypeId", null, null, Boolean.TRUE, null);
dynamicViewEntity.addAlias("PFC", "pfcDescription", "description", null, null, Boolean.TRUE, null);
dynamicViewEntity.addViewLink("PFAC", "PFC", Boolean.FALSE, ModelKeyMap.makeKeyMapList("productFeatureId"));
entityConditionList.add(EntityCondition.makeCondition("pfcProductFeatureTypeId", EntityOperator.EQUALS, productFeatureTypeId));
List<Map<String, String>> featureCountList = null;
try (EntityListIterator eli = EntityQuery.use(delegator)
.select(UtilMisc.toSet("pfacProductFeatureId", "featureCount", "pfcDescription", "pfcProductFeatureTypeId"))
.from(dynamicViewEntity)
.where(entityConditionList)
.orderBy(productSearchContext.orderByList)
.cursorScrollInsensitive()
.queryIterator()) {
featureCountList = new LinkedList<Map<String,String>>();
GenericValue searchResult = null;
while ((searchResult = eli.next()) != null) {
featureCountList.add(UtilMisc.<String, String>toMap("productFeatureId", (String) searchResult.get("pfacProductFeatureId"), "productFeatureTypeId", (String) searchResult.get("pfcProductFeatureTypeId"), "description", (String) searchResult.get("pfcDescription"), "featureCount", Long.toString((Long) searchResult.get("featureCount"))));
}
} catch (GenericEntityException e) {
Debug.logError(e, "Error in product search", module);
return null;
}
return featureCountList;
}
public static int getCategoryCostraintIndex(HttpSession session) {
int index = 0;
List<ProductSearchConstraint> productSearchConstraintList = ProductSearchOptions.getConstraintList(session);
for (ProductSearchConstraint constraint: productSearchConstraintList) {
if (constraint instanceof CategoryConstraint) {
index++;
}
}
return index;
}
/**
* This method returns count of products within a given price range, the constraint being
* applied on current ProductSearchConstraint list in session.
* @param priceLow The low price.
* @param priceHigh The high price.
* @param session Current session.
* @param delegator The delegator object.
* @return The long value of count of products.
*/
public static long getCountForListPriceRange(BigDecimal priceLow, BigDecimal priceHigh, HttpSession session, Delegator delegator) {
String visitId = VisitHandler.getVisitId(session);
ProductSearchContext productSearchContext = new ProductSearchContext(delegator, visitId);
List<ProductSearchConstraint> productSearchConstraintList = ProductSearchOptions.getConstraintList(session);
if (UtilValidate.isNotEmpty(productSearchConstraintList)) {
productSearchContext.addProductSearchConstraints(productSearchConstraintList);
}
productSearchContext.finishKeywordConstraints();
productSearchContext.finishCategoryAndFeatureConstraints();
DynamicViewEntity dynamicViewEntity = productSearchContext.dynamicViewEntity;
List<EntityCondition> entityConditionList = productSearchContext.entityConditionList;
List<String> fieldsToSelect = new LinkedList<String>();
dynamicViewEntity.addMemberEntity("PPC", "ProductPrice");
dynamicViewEntity.addAlias("PPC", "ppcProductPriceTypeId", "productPriceTypeId", null, null, null, null);
dynamicViewEntity.addAlias("PPC", "ppcFromDate", "fromDate", null, null, null, null);
dynamicViewEntity.addAlias("PPC", "ppcThruDate", "thruDate", null, null, null, null);
dynamicViewEntity.addAlias("PPC", "ppcPrice", "price", null, null, null, null);
dynamicViewEntity.addAlias("PPC", "priceRangeCount", "productId", null, null, null, "count-distinct");
dynamicViewEntity.addViewLink("PROD", "PPC", Boolean.FALSE, ModelKeyMap.makeKeyMapList("productId"));
fieldsToSelect.add("priceRangeCount");
entityConditionList.add(EntityCondition.makeCondition(EntityCondition.makeCondition("ppcThruDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition("ppcThruDate", EntityOperator.GREATER_THAN, UtilDateTime.nowTimestamp())));
entityConditionList.add(EntityCondition.makeCondition("ppcFromDate", EntityOperator.LESS_THAN, UtilDateTime.nowTimestamp()));
entityConditionList.add(EntityCondition.makeCondition("ppcPrice", EntityOperator.GREATER_THAN_EQUAL_TO, priceLow));
entityConditionList.add(EntityCondition.makeCondition("ppcPrice", EntityOperator.LESS_THAN_EQUAL_TO, priceHigh));
entityConditionList.add(EntityCondition.makeCondition("ppcProductPriceTypeId", EntityOperator.EQUALS, "LIST_PRICE"));
Long priceRangeCount = Long.valueOf(0);
try (EntityListIterator eli = EntityQuery.use(delegator)
.select(UtilMisc.toSet(fieldsToSelect))
.from(dynamicViewEntity)
.where(entityConditionList)
.orderBy(productSearchContext.orderByList)
.cursorScrollInsensitive()
.queryIterator()) {
GenericValue searchResult = null;
while ((searchResult = eli.next()) != null) {
priceRangeCount = searchResult.getLong("priceRangeCount");
}
} catch (GenericEntityException e) {
Debug.logError(e, "Error in product search", module);
}
return priceRangeCount;
}
/**
* This method returns count of products in a given category (including all sub categories), the constraint being
* applied on current ProductSearchConstraint list in session.
* @param productCategoryId productCategoryId for which the count should be returned.
* @param session Current session.
* @param delegator The delegator object.
* @return The long value of count of products.
*/
public static long getCountForProductCategory(String productCategoryId, HttpSession session, Delegator delegator) {
String visitId = VisitHandler.getVisitId(session);
ProductSearchContext productSearchContext = new ProductSearchContext(delegator, visitId);
List<ProductSearchConstraint> productSearchConstraintList = ProductSearchOptions.getConstraintList(session);
if (UtilValidate.isNotEmpty(productSearchConstraintList)) {
productSearchContext.addProductSearchConstraints(productSearchConstraintList);
}
productSearchContext.finishKeywordConstraints();
productSearchContext.finishCategoryAndFeatureConstraints();
DynamicViewEntity dynamicViewEntity = productSearchContext.dynamicViewEntity;
List<EntityCondition> entityConditionList = productSearchContext.entityConditionList;
List<String> fieldsToSelect = new LinkedList<String>();
dynamicViewEntity.addMemberEntity("PCMC", "ProductCategoryMember");
dynamicViewEntity.addAlias("PCMC", "pcmcProductCategoryId", "productCategoryId", null, null, null, null);
dynamicViewEntity.addAlias("PCMC", "pcmcFromDate", "fromDate", null, null, null, null);
dynamicViewEntity.addAlias("PCMC", "pcmcThruDate", "thruDate", null, null, null, null);
dynamicViewEntity.addAlias("PCMC", "categoryCount", "productId", null, null, null, "count-distinct");
dynamicViewEntity.addViewLink("PROD", "PCMC", Boolean.FALSE, ModelKeyMap.makeKeyMapList("productId"));
fieldsToSelect.add("categoryCount");
entityConditionList.add(EntityCondition.makeCondition(EntityCondition.makeCondition("pcmcThruDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition("pcmcThruDate", EntityOperator.GREATER_THAN, productSearchContext.nowTimestamp)));
entityConditionList.add(EntityCondition.makeCondition("pcmcFromDate", EntityOperator.LESS_THAN, productSearchContext.nowTimestamp));
Set<String> productCategoryIdSet = new HashSet<String>();
ProductSearch.getAllSubCategoryIds(productCategoryId, productCategoryIdSet, delegator, productSearchContext.nowTimestamp);
entityConditionList.add(EntityCondition.makeCondition("pcmcProductCategoryId", EntityOperator.IN, productCategoryIdSet));
Long categoryCount = Long.valueOf(0);
try (EntityListIterator eli = EntityQuery.use(delegator)
.select(UtilMisc.toSet(fieldsToSelect))
.from(dynamicViewEntity)
.where(entityConditionList)
.orderBy(productSearchContext.orderByList)
.cursorScrollInsensitive()
.queryIterator()) {
GenericValue searchResult = null;
while ((searchResult = eli.next()) != null) {
categoryCount = searchResult.getLong("categoryCount");
}
} catch (GenericEntityException e) {
Debug.logError(e, "Error in product search", module);
}
return categoryCount;
}
}