| /* |
| * 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.ofbiz.product.product; |
| |
| import java.math.BigDecimal; |
| import java.sql.Timestamp; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.TreeSet; |
| |
| import javolution.util.FastList; |
| import javolution.util.FastSet; |
| |
| import org.ofbiz.base.util.Debug; |
| import org.ofbiz.base.util.UtilDateTime; |
| import org.ofbiz.base.util.UtilMisc; |
| import org.ofbiz.base.util.UtilProperties; |
| import org.ofbiz.base.util.UtilValidate; |
| import org.ofbiz.common.KeywordSearchUtil; |
| import org.ofbiz.entity.Delegator; |
| import org.ofbiz.entity.GenericEntityException; |
| import org.ofbiz.entity.GenericValue; |
| import org.ofbiz.entity.condition.EntityComparisonOperator; |
| import org.ofbiz.entity.condition.EntityCondition; |
| import org.ofbiz.entity.condition.EntityConditionParam; |
| import org.ofbiz.entity.condition.EntityConditionSubSelect; |
| import org.ofbiz.entity.condition.EntityConditionValue; |
| import org.ofbiz.entity.condition.EntityOperator; |
| import org.ofbiz.entity.config.model.EntityConfig; |
| import org.ofbiz.entity.model.DynamicViewEntity; |
| import org.ofbiz.entity.model.ModelKeyMap; |
| import org.ofbiz.entity.model.ModelViewEntity.ComplexAlias; |
| import org.ofbiz.entity.model.ModelViewEntity.ComplexAliasField; |
| import org.ofbiz.entity.transaction.GenericTransactionException; |
| import org.ofbiz.entity.transaction.TransactionUtil; |
| import org.ofbiz.entity.util.EntityFindOptions; |
| import org.ofbiz.entity.util.EntityListIterator; |
| import org.ofbiz.entity.util.EntityQuery; |
| import org.ofbiz.entity.util.EntityUtil; |
| import org.ofbiz.party.party.PartyHelper; |
| import org.ofbiz.product.category.CategoryContentWrapper; |
| |
| |
| /** |
| * Utilities for product search based on various constraints including categories, features and keywords. |
| */ |
| public class ProductSearch { |
| |
| public static final String module = ProductSearch.class.getName(); |
| public static final String resource = "ProductUiLabels"; |
| public static final String resourceCommon = "CommonUiLabels"; |
| |
| public static ArrayList<String> parametricKeywordSearch(Map<?, String> featureIdByType, String keywordsString, Delegator delegator, String productCategoryId, String visitId, boolean anyPrefix, boolean anySuffix, boolean isAnd) { |
| Set<String> featureIdSet = FastSet.newInstance(); |
| if (featureIdByType != null) { |
| featureIdSet.addAll(featureIdByType.values()); |
| } |
| |
| return parametricKeywordSearch(featureIdSet, keywordsString, delegator, productCategoryId, true, visitId, anyPrefix, anySuffix, isAnd); |
| } |
| |
| public static ArrayList<String> parametricKeywordSearch(Set<String> featureIdSet, String keywordsString, Delegator delegator, String productCategoryId, boolean includeSubCategories, String visitId, boolean anyPrefix, boolean anySuffix, boolean isAnd) { |
| List<ProductSearchConstraint> productSearchConstraintList = FastList.newInstance(); |
| |
| if (UtilValidate.isNotEmpty(productCategoryId)) { |
| productSearchConstraintList.add(new CategoryConstraint(productCategoryId, includeSubCategories, null)); |
| } |
| |
| if (UtilValidate.isNotEmpty(keywordsString)) { |
| productSearchConstraintList.add(new KeywordConstraint(keywordsString, anyPrefix, anySuffix, null, isAnd)); |
| } |
| |
| if (UtilValidate.isNotEmpty(featureIdSet)) { |
| for (String productFeatureId: featureIdSet) { |
| productSearchConstraintList.add(new FeatureConstraint(productFeatureId, null)); |
| } |
| } |
| |
| return searchProducts(productSearchConstraintList, new SortKeywordRelevancy(), delegator, visitId); |
| } |
| |
| public static ArrayList<String> searchProducts(List<ProductSearchConstraint> productSearchConstraintList, ResultSortOrder resultSortOrder, Delegator delegator, String visitId) { |
| ProductSearchContext productSearchContext = new ProductSearchContext(delegator, visitId); |
| |
| productSearchContext.addProductSearchConstraints(productSearchConstraintList); |
| productSearchContext.setResultSortOrder(resultSortOrder); |
| |
| ArrayList<String> productIds = productSearchContext.doSearch(); |
| return productIds; |
| } |
| |
| public static void getAllSubCategoryIds(String productCategoryId, Set<String> productCategoryIdSet, Delegator delegator, Timestamp nowTimestamp) { |
| if (nowTimestamp == null) { |
| nowTimestamp = UtilDateTime.nowTimestamp(); |
| } |
| |
| // this will use the Delegator cache as much as possible, but not a dedicated cache because it would get stale to easily and is too much of a pain to maintain in development and production |
| |
| // first make sure the current category id is in the Set |
| productCategoryIdSet.add(productCategoryId); |
| |
| // now find all sub-categories, filtered by effective dates, and call this routine for them |
| try { |
| List<GenericValue> productCategoryRollupList = EntityQuery.use(delegator).from("ProductCategoryRollup").where("parentProductCategoryId", productCategoryId).cache(true).queryList(); |
| for (GenericValue productCategoryRollup: productCategoryRollupList) { |
| String subProductCategoryId = productCategoryRollup.getString("productCategoryId"); |
| if (productCategoryIdSet.contains(subProductCategoryId)) { |
| // if this category has already been traversed, no use doing it again; this will also avoid infinite loops |
| continue; |
| } |
| |
| // do the date filtering in the loop to avoid looping through the list twice |
| if (EntityUtil.isValueActive(productCategoryRollup, nowTimestamp)) { |
| getAllSubCategoryIds(subProductCategoryId, productCategoryIdSet, delegator, nowTimestamp); |
| } |
| } |
| } catch (GenericEntityException e) { |
| Debug.logError(e, "Error finding sub-categories for product search", module); |
| } |
| } |
| |
| public static class ProductSearchContext { |
| public int index = 1; |
| public List<EntityCondition> entityConditionList = FastList.newInstance(); |
| public List<String> orderByList = FastList.newInstance(); |
| public List<String> fieldsToSelect = UtilMisc.toList("mainProductId"); |
| public DynamicViewEntity dynamicViewEntity = new DynamicViewEntity(); |
| public boolean productIdGroupBy = false; |
| public boolean includedKeywordSearch = false; |
| public Timestamp nowTimestamp = UtilDateTime.nowTimestamp(); |
| public List<Set<String>> keywordFixedOrSetAndList = FastList.newInstance(); |
| public Set<String> orKeywordFixedSet = FastSet.newInstance(); |
| public Set<String> andKeywordFixedSet = FastSet.newInstance(); |
| public List<GenericValue> productSearchConstraintList = FastList.newInstance(); |
| public ResultSortOrder resultSortOrder = null; |
| public Integer resultOffset = null; |
| public Integer maxResults = null; |
| protected Delegator delegator = null; |
| protected String visitId = null; |
| protected Integer totalResults = null; |
| |
| public Set<String> includeCategoryIds = FastSet.newInstance(); |
| public Set<String> excludeCategoryIds = FastSet.newInstance(); |
| public Set<String> alwaysIncludeCategoryIds = FastSet.newInstance(); |
| |
| public List<Set<String>> includeCategoryIdOrSetAndList = FastList.newInstance(); |
| public List<Set<String>> alwaysIncludeCategoryIdOrSetAndList = FastList.newInstance(); |
| |
| public Set<String> includeFeatureIds = FastSet.newInstance(); |
| public Set<String> excludeFeatureIds = FastSet.newInstance(); |
| public Set<String> alwaysIncludeFeatureIds = FastSet.newInstance(); |
| |
| public List<Set<String>> includeFeatureIdOrSetAndList = FastList.newInstance(); |
| public List<Set<String>> alwaysIncludeFeatureIdOrSetAndList = FastList.newInstance(); |
| |
| public Set<String> includeFeatureCategoryIds = FastSet.newInstance(); |
| public Set<String> excludeFeatureCategoryIds = FastSet.newInstance(); |
| public Set<String> alwaysIncludeFeatureCategoryIds = FastSet.newInstance(); |
| |
| public Set<String> includeFeatureGroupIds = FastSet.newInstance(); |
| public Set<String> excludeFeatureGroupIds = FastSet.newInstance(); |
| public Set<String> alwaysIncludeFeatureGroupIds = FastSet.newInstance(); |
| |
| public List<String> keywordTypeIds = FastList.newInstance(); |
| public String statusId = null; |
| |
| public ProductSearchContext(Delegator delegator, String visitId) { |
| this.delegator = delegator; |
| this.visitId = visitId; |
| dynamicViewEntity.addMemberEntity("PROD", "Product"); |
| dynamicViewEntity.addMemberEntity("PRODCI", "ProductCalculatedInfo"); |
| dynamicViewEntity.addViewLink("PROD", "PRODCI", Boolean.TRUE, ModelKeyMap.makeKeyMapList("productId")); |
| } |
| |
| public Delegator getDelegator() { |
| return this.delegator; |
| } |
| |
| public void addProductSearchConstraints(List<ProductSearchConstraint> productSearchConstraintList) { |
| // Go through the constraints and add them in |
| for (ProductSearchConstraint constraint: productSearchConstraintList) { |
| constraint.addConstraint(this); |
| } |
| } |
| |
| public void setResultSortOrder(ResultSortOrder resultSortOrder) { |
| this.resultSortOrder = resultSortOrder; |
| } |
| |
| public void setResultOffset(Integer resultOffset) { |
| this.resultOffset = resultOffset; |
| } |
| |
| public void setMaxResults(Integer maxResults) { |
| this.maxResults = maxResults; |
| } |
| |
| public Integer getTotalResults() { |
| return this.totalResults; |
| } |
| |
| public ArrayList<String> doSearch() { |
| long startMillis = System.currentTimeMillis(); |
| |
| // do the query |
| EntityListIterator eli = this.doQuery(delegator); |
| ArrayList<String> productIds = this.makeProductIdList(eli); |
| if (eli != null) { |
| try { |
| eli.close(); |
| } catch (GenericEntityException e) { |
| Debug.logError(e, "Error closing ProductSearch EntityListIterator"); |
| } |
| } |
| |
| long endMillis = System.currentTimeMillis(); |
| double totalSeconds = ((double)endMillis - (double)startMillis)/1000.0; |
| |
| // store info about results in the database, attached to the user's visitId, if specified |
| this.saveSearchResultInfo(Long.valueOf(productIds.size()), Double.valueOf(totalSeconds)); |
| |
| return productIds; |
| } |
| |
| public void finishKeywordConstraints() { |
| if (orKeywordFixedSet.size() == 0 && andKeywordFixedSet.size() == 0 && keywordFixedOrSetAndList.size() == 0) { |
| return; |
| } |
| |
| // we know we have a keyword search to do, so keep track of that now... |
| this.includedKeywordSearch = true; |
| |
| // if there is anything in the orKeywordFixedSet add it to the keywordFixedOrSetAndList |
| if (orKeywordFixedSet.size() > 0) { |
| // put in keywordFixedOrSetAndList to process with other or lists where at least one is required |
| keywordFixedOrSetAndList.add(orKeywordFixedSet); |
| } |
| |
| // remove all or sets from the or set and list where the or set is size 1 and put them in the and list |
| Iterator<Set<String>> keywordFixedOrSetAndTestIter = keywordFixedOrSetAndList.iterator(); |
| while (keywordFixedOrSetAndTestIter.hasNext()) { |
| Set<String> keywordFixedOrSet = keywordFixedOrSetAndTestIter.next(); |
| if (keywordFixedOrSet.size() == 0) { |
| keywordFixedOrSetAndTestIter.remove(); |
| } else if (keywordFixedOrSet.size() == 1) { |
| // treat it as just another and |
| andKeywordFixedSet.add(keywordFixedOrSet.iterator().next()); |
| keywordFixedOrSetAndTestIter.remove(); |
| } |
| } |
| |
| boolean doingBothAndOr = (keywordFixedOrSetAndList.size() > 1) || (keywordFixedOrSetAndList.size() > 0 && andKeywordFixedSet.size() > 0); |
| |
| Debug.logInfo("Finished initial setup of keywords, doingBothAndOr=" + doingBothAndOr + ", andKeywordFixedSet=" + andKeywordFixedSet + "\n keywordFixedOrSetAndList=" + keywordFixedOrSetAndList, module); |
| |
| ComplexAlias relevancyComplexAlias = new ComplexAlias("+"); |
| if (andKeywordFixedSet.size() > 0) { |
| // add up the relevancyWeight fields from all keyword member entities for a total to sort by |
| |
| for (String keyword: andKeywordFixedSet) { |
| // make index based values and increment |
| String entityAlias = "PK" + index; |
| String prefix = "pk" + index; |
| index++; |
| |
| dynamicViewEntity.addMemberEntity(entityAlias, "ProductKeyword"); |
| dynamicViewEntity.addAlias(entityAlias, prefix + "Keyword", "keyword", null, null, null, null); |
| |
| // keyword type filter |
| if (UtilValidate.isNotEmpty(keywordTypeIds)) { |
| dynamicViewEntity.addAlias(entityAlias, "keywordTypeId"); |
| } |
| |
| // keyword status filter |
| if (UtilValidate.isNotEmpty(statusId)) { |
| dynamicViewEntity.addAlias(entityAlias, "statusId"); |
| } |
| |
| dynamicViewEntity.addViewLink("PROD", entityAlias, Boolean.FALSE, ModelKeyMap.makeKeyMapList("productId")); |
| entityConditionList.add(EntityCondition.makeCondition(prefix + "Keyword", EntityOperator.LIKE, keyword)); |
| |
| // keyword type filter |
| if (UtilValidate.isNotEmpty(keywordTypeIds)) { |
| List<EntityCondition> keywordTypeCons = FastList.newInstance(); |
| for (String keywordTypeId : keywordTypeIds) { |
| keywordTypeCons.add(EntityCondition.makeCondition("keywordTypeId", EntityOperator.EQUALS, keywordTypeId)); |
| } |
| entityConditionList.add(EntityCondition.makeCondition(keywordTypeCons, EntityOperator.OR)); |
| } |
| |
| // keyword status filter |
| if (UtilValidate.isNotEmpty(statusId)) { |
| entityConditionList.add(EntityCondition.makeCondition("statusId", EntityOperator.EQUALS, statusId)); |
| } |
| |
| //don't add an alias for this, will be part of a complex alias: dynamicViewEntity.addAlias(entityAlias, prefix + "RelevancyWeight", "relevancyWeight", null, null, null, null); |
| //needed when doingBothAndOr or will get an SQL error |
| if (doingBothAndOr) { |
| dynamicViewEntity.addAlias(entityAlias, prefix + "RelevancyWeight", "relevancyWeight", null, null, Boolean.TRUE, null); |
| } |
| relevancyComplexAlias.addComplexAliasMember(new ComplexAliasField(entityAlias, "relevancyWeight", null, null)); |
| } |
| |
| //TODO: find out why Oracle and other dbs don't like the query resulting from this and fix: productIdGroupBy = true; |
| |
| if (!doingBothAndOr) { |
| dynamicViewEntity.addAlias(null, "totalRelevancy", null, null, null, null, null, relevancyComplexAlias); |
| } |
| } |
| if (keywordFixedOrSetAndList.size() > 0) { |
| for (Set<String> keywordFixedOrSet: keywordFixedOrSetAndList) { |
| // make index based values and increment |
| String entityAlias = "PK" + index; |
| String prefix = "pk" + index; |
| index++; |
| |
| dynamicViewEntity.addMemberEntity(entityAlias, "ProductKeyword"); |
| dynamicViewEntity.addAlias(entityAlias, prefix + "Keyword", "keyword", null, null, null, null); |
| dynamicViewEntity.addViewLink("PROD", entityAlias, Boolean.FALSE, ModelKeyMap.makeKeyMapList("productId")); |
| List<EntityCondition> keywordOrList = FastList.newInstance(); |
| for (String keyword: keywordFixedOrSet) { |
| keywordOrList.add(EntityCondition.makeCondition(prefix + "Keyword", EntityOperator.LIKE, keyword)); |
| } |
| entityConditionList.add(EntityCondition.makeCondition(keywordOrList, EntityOperator.OR)); |
| |
| if (doingBothAndOr) { |
| relevancyComplexAlias.addComplexAliasMember(new ComplexAliasField(entityAlias, "relevancyWeight", null, "sum")); |
| } else { |
| dynamicViewEntity.addAlias(entityAlias, "totalRelevancy", "relevancyWeight", null, null, null, "sum"); |
| } |
| } |
| } |
| |
| if (doingBothAndOr) { |
| dynamicViewEntity.addAlias(null, "totalRelevancy", null, null, null, null, null, relevancyComplexAlias); |
| } |
| } |
| |
| public void finishCategoryAndFeatureConstraints() { |
| if (includeCategoryIds.size() == 0 && excludeCategoryIds.size() == 0 && alwaysIncludeCategoryIds.size() == 0 && |
| includeCategoryIdOrSetAndList.size() == 0 && alwaysIncludeCategoryIdOrSetAndList.size() == 0 && |
| includeFeatureIds.size() == 0 && excludeFeatureIds.size() == 0 && alwaysIncludeFeatureIds.size() == 0 && |
| includeFeatureIdOrSetAndList.size() == 0 && alwaysIncludeFeatureIdOrSetAndList.size() == 0 && |
| includeFeatureCategoryIds.size() == 0 && excludeFeatureCategoryIds.size() == 0 && alwaysIncludeFeatureCategoryIds.size() == 0 && |
| includeFeatureGroupIds.size() == 0 && excludeFeatureGroupIds.size() == 0 && alwaysIncludeFeatureGroupIds.size() == 0) { |
| return; |
| } |
| |
| // create new view members with logic: |
| // ((each Id = category includes AND Id IN feature includes) AND (Id NOT IN category excludes AND Id NOT IN feature excludes)) |
| // OR (each Id = category alwaysIncludes AND each Id = feature alwaysIncludes) |
| List<EntityCondition> incExcCondList = FastList.newInstance(); |
| EntityCondition incExcCond = null; |
| |
| List<EntityCondition> alwIncCondList = FastList.newInstance(); |
| EntityCondition alwIncCond = null; |
| |
| EntityCondition topCond = null; |
| |
| if (includeCategoryIds.size() > 0) { |
| for (String includeCategoryId: includeCategoryIds) { |
| String categoryPrefix = "pcm" + this.index; |
| String entityAlias = "PCM" + this.index; |
| this.index++; |
| |
| this.dynamicViewEntity.addMemberEntity(entityAlias, "ProductCategoryMember"); |
| this.dynamicViewEntity.addAlias(entityAlias, categoryPrefix + "ProductCategoryId", "productCategoryId", null, null, null, null); |
| this.dynamicViewEntity.addAlias(entityAlias, categoryPrefix + "FromDate", "fromDate", null, null, null, null); |
| this.dynamicViewEntity.addAlias(entityAlias, categoryPrefix + "ThruDate", "thruDate", null, null, null, null); |
| this.dynamicViewEntity.addViewLink("PROD", entityAlias, Boolean.FALSE, ModelKeyMap.makeKeyMapList("productId")); |
| incExcCondList.add(EntityCondition.makeCondition(EntityCondition.makeCondition(categoryPrefix + "ThruDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition(categoryPrefix + "ThruDate", EntityOperator.GREATER_THAN, this.nowTimestamp))); |
| incExcCondList.add(EntityCondition.makeCondition(categoryPrefix + "FromDate", EntityOperator.LESS_THAN, this.nowTimestamp)); |
| incExcCondList.add(EntityCondition.makeCondition(categoryPrefix + "ProductCategoryId", EntityOperator.EQUALS, includeCategoryId)); |
| } |
| } |
| if (includeFeatureIds.size() > 0) { |
| for (String includeFeatureId: includeFeatureIds) { |
| String featurePrefix = "pfa" + this.index; |
| String entityAlias = "PFA" + this.index; |
| this.index++; |
| |
| this.dynamicViewEntity.addMemberEntity(entityAlias, "ProductFeatureAppl"); |
| this.dynamicViewEntity.addAlias(entityAlias, featurePrefix + "ProductFeatureId", "productFeatureId", null, null, null, null); |
| this.dynamicViewEntity.addAlias(entityAlias, featurePrefix + "FromDate", "fromDate", null, null, null, null); |
| this.dynamicViewEntity.addAlias(entityAlias, featurePrefix + "ThruDate", "thruDate", null, null, null, null); |
| this.dynamicViewEntity.addViewLink("PROD", entityAlias, Boolean.FALSE, ModelKeyMap.makeKeyMapList("productId")); |
| incExcCondList.add(EntityCondition.makeCondition(EntityCondition.makeCondition(featurePrefix + "ThruDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition(featurePrefix + "ThruDate", EntityOperator.GREATER_THAN, this.nowTimestamp))); |
| incExcCondList.add(EntityCondition.makeCondition(featurePrefix + "FromDate", EntityOperator.LESS_THAN, this.nowTimestamp)); |
| incExcCondList.add(EntityCondition.makeCondition(featurePrefix + "ProductFeatureId", EntityOperator.EQUALS, includeFeatureId)); |
| } |
| } |
| if (includeFeatureCategoryIds.size() > 0) { |
| for (String includeFeatureCategoryId: includeFeatureCategoryIds) { |
| String featurePrefix = "pfa" + this.index; |
| String entityAlias = "PFA" + this.index; |
| String otherFeaturePrefix = "pfe" + this.index; |
| String otherEntityAlias = "PFE" + this.index; |
| this.index++; |
| |
| this.dynamicViewEntity.addMemberEntity(entityAlias, "ProductFeatureAppl"); |
| this.dynamicViewEntity.addMemberEntity(otherEntityAlias, "ProductFeature"); |
| this.dynamicViewEntity.addAlias(otherEntityAlias, otherFeaturePrefix + "ProductFeatureCategoryId", "productFeatureCategoryId", null, null, null, null); |
| this.dynamicViewEntity.addAlias(entityAlias, featurePrefix + "FromDate", "fromDate", null, null, null, null); |
| this.dynamicViewEntity.addAlias(entityAlias, featurePrefix + "ThruDate", "thruDate", null, null, null, null); |
| this.dynamicViewEntity.addViewLink("PROD", entityAlias, Boolean.FALSE, ModelKeyMap.makeKeyMapList("productId")); |
| this.dynamicViewEntity.addViewLink(entityAlias, otherEntityAlias, Boolean.FALSE, ModelKeyMap.makeKeyMapList("productFeatureId")); |
| incExcCondList.add(EntityCondition.makeCondition(EntityCondition.makeCondition(featurePrefix + "ThruDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition(featurePrefix + "ThruDate", EntityOperator.GREATER_THAN, this.nowTimestamp))); |
| incExcCondList.add(EntityCondition.makeCondition(featurePrefix + "FromDate", EntityOperator.LESS_THAN, this.nowTimestamp)); |
| incExcCondList.add(EntityCondition.makeCondition(otherFeaturePrefix + "ProductFeatureCategoryId", EntityOperator.EQUALS, includeFeatureCategoryId)); |
| } |
| } |
| if (includeFeatureGroupIds.size() > 0) { |
| for (String includeFeatureGroupId: includeFeatureGroupIds) { |
| String featurePrefix = "pfa" + this.index; |
| String entityAlias = "PFA" + this.index; |
| String otherFeaturePrefix = "pfga" + this.index; |
| String otherEntityAlias = "PFGA" + this.index; |
| this.index++; |
| |
| this.dynamicViewEntity.addMemberEntity(entityAlias, "ProductFeatureAppl"); |
| this.dynamicViewEntity.addMemberEntity(otherEntityAlias, "ProductFeatureGroupAppl"); |
| this.dynamicViewEntity.addAlias(otherEntityAlias, otherFeaturePrefix + "ProductFeatureGroupId", "productFeatureGroupId", null, null, null, null); |
| this.dynamicViewEntity.addAlias(entityAlias, featurePrefix + "FromDate", "fromDate", null, null, null, null); |
| this.dynamicViewEntity.addAlias(entityAlias, featurePrefix + "ThruDate", "thruDate", null, null, null, null); |
| this.dynamicViewEntity.addAlias(otherEntityAlias, otherFeaturePrefix + "FromDate", "fromDate", null, null, null, null); |
| this.dynamicViewEntity.addAlias(otherEntityAlias, otherFeaturePrefix + "ThruDate", "thruDate", null, null, null, null); |
| this.dynamicViewEntity.addViewLink("PROD", entityAlias, Boolean.FALSE, ModelKeyMap.makeKeyMapList("productId")); |
| this.dynamicViewEntity.addViewLink(entityAlias, otherEntityAlias, Boolean.FALSE, ModelKeyMap.makeKeyMapList("productFeatureId")); |
| incExcCondList.add(EntityCondition.makeCondition(EntityCondition.makeCondition(featurePrefix + "ThruDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition(featurePrefix + "ThruDate", EntityOperator.GREATER_THAN, this.nowTimestamp))); |
| incExcCondList.add(EntityCondition.makeCondition(featurePrefix + "FromDate", EntityOperator.LESS_THAN, this.nowTimestamp)); |
| incExcCondList.add(EntityCondition.makeCondition(EntityCondition.makeCondition(otherFeaturePrefix + "ThruDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition(otherFeaturePrefix + "ThruDate", EntityOperator.GREATER_THAN, this.nowTimestamp))); |
| incExcCondList.add(EntityCondition.makeCondition(otherFeaturePrefix + "FromDate", EntityOperator.LESS_THAN, this.nowTimestamp)); |
| incExcCondList.add(EntityCondition.makeCondition(otherFeaturePrefix + "ProductFeatureGroupId", EntityOperator.EQUALS, includeFeatureGroupId)); |
| } |
| } |
| |
| if (excludeCategoryIds.size() > 0) { |
| List<EntityCondition> idExcludeCondList = FastList.newInstance(); |
| idExcludeCondList.add(EntityCondition.makeCondition(EntityCondition.makeCondition("thruDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition("thruDate", EntityOperator.GREATER_THAN, this.nowTimestamp))); |
| idExcludeCondList.add(EntityCondition.makeCondition("fromDate", EntityOperator.LESS_THAN, this.nowTimestamp)); |
| idExcludeCondList.add(EntityCondition.makeCondition("productCategoryId", EntityOperator.IN, excludeCategoryIds)); |
| EntityConditionValue subSelCond = new EntityConditionSubSelect("ProductCategoryMember", "productId", EntityCondition.makeCondition(idExcludeCondList, EntityOperator.AND), true, delegator); |
| incExcCondList.add(EntityCondition.makeCondition("mainProductId", EntityOperator.NOT_EQUAL, subSelCond)); |
| } |
| if (excludeFeatureIds.size() > 0) { |
| List<EntityCondition> idExcludeCondList = FastList.newInstance(); |
| idExcludeCondList.add(EntityCondition.makeCondition(EntityCondition.makeCondition("thruDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition("thruDate", EntityOperator.GREATER_THAN, this.nowTimestamp))); |
| idExcludeCondList.add(EntityCondition.makeCondition("fromDate", EntityOperator.LESS_THAN, this.nowTimestamp)); |
| idExcludeCondList.add(EntityCondition.makeCondition("productFeatureId", EntityOperator.IN, excludeFeatureIds)); |
| EntityConditionValue subSelCond = new EntityConditionSubSelect("ProductFeatureAppl", "productId", EntityCondition.makeCondition(idExcludeCondList, EntityOperator.AND), true, delegator); |
| incExcCondList.add(EntityCondition.makeCondition("mainProductId", EntityOperator.NOT_EQUAL, subSelCond)); |
| } |
| if (excludeFeatureCategoryIds.size() > 0) { |
| List<EntityCondition> idExcludeCondList = FastList.newInstance(); |
| idExcludeCondList.add(EntityCondition.makeCondition(EntityCondition.makeCondition("thruDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition("thruDate", EntityOperator.GREATER_THAN, this.nowTimestamp))); |
| idExcludeCondList.add(EntityCondition.makeCondition("fromDate", EntityOperator.LESS_THAN, this.nowTimestamp)); |
| idExcludeCondList.add(EntityCondition.makeCondition("productFeatureCategoryId", EntityOperator.IN, excludeFeatureCategoryIds)); |
| EntityConditionValue subSelCond = new EntityConditionSubSelect("ProductFeatureAndAppl", "productId", EntityCondition.makeCondition(idExcludeCondList, EntityOperator.AND), true, delegator); |
| incExcCondList.add(EntityCondition.makeCondition("mainProductId", EntityOperator.NOT_EQUAL, subSelCond)); |
| } |
| if (excludeFeatureGroupIds.size() > 0) { |
| List<EntityCondition> idExcludeCondList = FastList.newInstance(); |
| idExcludeCondList.add(EntityCondition.makeCondition(EntityCondition.makeCondition("thruDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition("thruDate", EntityOperator.GREATER_THAN, this.nowTimestamp))); |
| idExcludeCondList.add(EntityCondition.makeCondition("fromDate", EntityOperator.LESS_THAN, this.nowTimestamp)); |
| idExcludeCondList.add(EntityCondition.makeCondition(EntityCondition.makeCondition("groupThruDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition("groupThruDate", EntityOperator.GREATER_THAN, this.nowTimestamp))); |
| idExcludeCondList.add(EntityCondition.makeCondition("groupFromDate", EntityOperator.LESS_THAN, this.nowTimestamp)); |
| idExcludeCondList.add(EntityCondition.makeCondition("productFeatureGroupId", EntityOperator.IN, excludeFeatureGroupIds)); |
| EntityConditionValue subSelCond = new EntityConditionSubSelect("ProdFeaGrpAppAndProdFeaApp", "productId", EntityCondition.makeCondition(idExcludeCondList, EntityOperator.AND), true, delegator); |
| incExcCondList.add(EntityCondition.makeCondition("mainProductId", EntityOperator.NOT_EQUAL, subSelCond)); |
| } |
| |
| if (alwaysIncludeCategoryIds.size() > 0) { |
| String categoryPrefix = "pcm" + this.index; |
| String entityAlias = "PCM" + this.index; |
| this.index++; |
| |
| this.dynamicViewEntity.addMemberEntity(entityAlias, "ProductCategoryMember"); |
| this.dynamicViewEntity.addAlias(entityAlias, categoryPrefix + "ProductCategoryId", "productCategoryId", null, null, null, null); |
| this.dynamicViewEntity.addAlias(entityAlias, categoryPrefix + "FromDate", "fromDate", null, null, null, null); |
| this.dynamicViewEntity.addAlias(entityAlias, categoryPrefix + "ThruDate", "thruDate", null, null, null, null); |
| this.dynamicViewEntity.addViewLink("PROD", entityAlias, Boolean.FALSE, ModelKeyMap.makeKeyMapList("productId")); |
| alwIncCondList.add(EntityCondition.makeCondition(EntityCondition.makeCondition(categoryPrefix + "ThruDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition(categoryPrefix + "ThruDate", EntityOperator.GREATER_THAN, this.nowTimestamp))); |
| alwIncCondList.add(EntityCondition.makeCondition(categoryPrefix + "FromDate", EntityOperator.LESS_THAN, this.nowTimestamp)); |
| alwIncCondList.add(EntityCondition.makeCondition(categoryPrefix + "ProductCategoryId", EntityOperator.IN, alwaysIncludeCategoryIds)); |
| } |
| if (alwaysIncludeFeatureIds.size() > 0) { |
| String featurePrefix = "pfa" + this.index; |
| String entityAlias = "PFA" + this.index; |
| this.index++; |
| |
| this.dynamicViewEntity.addMemberEntity(entityAlias, "ProductFeatureAppl"); |
| this.dynamicViewEntity.addAlias(entityAlias, featurePrefix + "ProductFeatureId", "productFeatureId", null, null, null, null); |
| this.dynamicViewEntity.addAlias(entityAlias, featurePrefix + "FromDate", "fromDate", null, null, null, null); |
| this.dynamicViewEntity.addAlias(entityAlias, featurePrefix + "ThruDate", "thruDate", null, null, null, null); |
| this.dynamicViewEntity.addViewLink("PROD", entityAlias, Boolean.FALSE, ModelKeyMap.makeKeyMapList("productId")); |
| alwIncCondList.add(EntityCondition.makeCondition(EntityCondition.makeCondition(featurePrefix + "ThruDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition(featurePrefix + "ThruDate", EntityOperator.GREATER_THAN, this.nowTimestamp))); |
| alwIncCondList.add(EntityCondition.makeCondition(featurePrefix + "FromDate", EntityOperator.LESS_THAN, this.nowTimestamp)); |
| alwIncCondList.add(EntityCondition.makeCondition(featurePrefix + "ProductFeatureId", EntityOperator.IN, alwaysIncludeFeatureIds)); |
| } |
| if (alwaysIncludeFeatureCategoryIds.size() > 0) { |
| for (String alwaysIncludeFeatureCategoryId: alwaysIncludeFeatureCategoryIds) { |
| String featurePrefix = "pfa" + this.index; |
| String entityAlias = "PFA" + this.index; |
| String otherFeaturePrefix = "pfe" + this.index; |
| String otherEntityAlias = "PFE" + this.index; |
| this.index++; |
| |
| this.dynamicViewEntity.addMemberEntity(entityAlias, "ProductFeatureAppl"); |
| this.dynamicViewEntity.addMemberEntity(otherEntityAlias, "ProductFeature"); |
| this.dynamicViewEntity.addAlias(otherEntityAlias, otherFeaturePrefix + "ProductFeatureCategoryId", "productFeatureCategoryId", null, null, null, null); |
| this.dynamicViewEntity.addAlias(entityAlias, featurePrefix + "FromDate", "fromDate", null, null, null, null); |
| this.dynamicViewEntity.addAlias(entityAlias, featurePrefix + "ThruDate", "thruDate", null, null, null, null); |
| this.dynamicViewEntity.addViewLink("PROD", entityAlias, Boolean.FALSE, ModelKeyMap.makeKeyMapList("productId")); |
| this.dynamicViewEntity.addViewLink(entityAlias, otherEntityAlias, Boolean.FALSE, ModelKeyMap.makeKeyMapList("productFeatureId")); |
| alwIncCondList.add(EntityCondition.makeCondition(EntityCondition.makeCondition(featurePrefix + "ThruDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition(featurePrefix + "ThruDate", EntityOperator.GREATER_THAN, this.nowTimestamp))); |
| alwIncCondList.add(EntityCondition.makeCondition(featurePrefix + "FromDate", EntityOperator.LESS_THAN, this.nowTimestamp)); |
| alwIncCondList.add(EntityCondition.makeCondition(otherFeaturePrefix + "ProductFeatureCategoryId", EntityOperator.EQUALS, alwaysIncludeFeatureCategoryId)); |
| } |
| } |
| if (alwaysIncludeFeatureGroupIds.size() > 0) { |
| for (String alwaysIncludeFeatureGroupId: alwaysIncludeFeatureGroupIds) { |
| String featurePrefix = "pfa" + this.index; |
| String entityAlias = "PFA" + this.index; |
| String otherFeaturePrefix = "pfga" + this.index; |
| String otherEntityAlias = "PFGA" + this.index; |
| this.index++; |
| |
| this.dynamicViewEntity.addMemberEntity(entityAlias, "ProductFeatureAppl"); |
| this.dynamicViewEntity.addMemberEntity(otherEntityAlias, "ProductFeatureGroupAppl"); |
| this.dynamicViewEntity.addAlias(otherEntityAlias, otherFeaturePrefix + "ProductFeatureGroupId", "productFeatureGroupId", null, null, null, null); |
| this.dynamicViewEntity.addAlias(entityAlias, featurePrefix + "FromDate", "fromDate", null, null, null, null); |
| this.dynamicViewEntity.addAlias(entityAlias, featurePrefix + "ThruDate", "thruDate", null, null, null, null); |
| this.dynamicViewEntity.addAlias(otherEntityAlias, otherFeaturePrefix + "FromDate", "fromDate", null, null, null, null); |
| this.dynamicViewEntity.addAlias(otherEntityAlias, otherFeaturePrefix + "ThruDate", "thruDate", null, null, null, null); |
| this.dynamicViewEntity.addViewLink("PROD", entityAlias, Boolean.FALSE, ModelKeyMap.makeKeyMapList("productId")); |
| this.dynamicViewEntity.addViewLink(entityAlias, otherEntityAlias, Boolean.FALSE, ModelKeyMap.makeKeyMapList("productFeatureId")); |
| alwIncCondList.add(EntityCondition.makeCondition(EntityCondition.makeCondition(featurePrefix + "ThruDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition(featurePrefix + "ThruDate", EntityOperator.GREATER_THAN, this.nowTimestamp))); |
| alwIncCondList.add(EntityCondition.makeCondition(featurePrefix + "FromDate", EntityOperator.LESS_THAN, this.nowTimestamp)); |
| alwIncCondList.add(EntityCondition.makeCondition(EntityCondition.makeCondition(otherFeaturePrefix + "ThruDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition(otherFeaturePrefix + "ThruDate", EntityOperator.GREATER_THAN, this.nowTimestamp))); |
| alwIncCondList.add(EntityCondition.makeCondition(otherFeaturePrefix + "FromDate", EntityOperator.LESS_THAN, this.nowTimestamp)); |
| alwIncCondList.add(EntityCondition.makeCondition(otherFeaturePrefix + "ProductFeatureGroupId", EntityOperator.EQUALS, alwaysIncludeFeatureGroupId)); |
| } |
| } |
| |
| // handle includeFeatureIdOrSetAndList and alwaysIncludeFeatureIdOrSetAndList |
| if (includeFeatureIdOrSetAndList.size() > 0) { |
| for (Set<String> includeFeatureIdOrSet: includeFeatureIdOrSetAndList) { |
| String featurePrefix = "pfa" + this.index; |
| String entityAlias = "PFA" + this.index; |
| this.index++; |
| |
| this.dynamicViewEntity.addMemberEntity(entityAlias, "ProductFeatureAppl"); |
| this.dynamicViewEntity.addAlias(entityAlias, featurePrefix + "ProductFeatureId", "productFeatureId", null, null, null, null); |
| this.dynamicViewEntity.addAlias(entityAlias, featurePrefix + "FromDate", "fromDate", null, null, null, null); |
| this.dynamicViewEntity.addAlias(entityAlias, featurePrefix + "ThruDate", "thruDate", null, null, null, null); |
| this.dynamicViewEntity.addViewLink("PROD", entityAlias, Boolean.FALSE, ModelKeyMap.makeKeyMapList("productId")); |
| incExcCondList.add(EntityCondition.makeCondition(EntityCondition.makeCondition(featurePrefix + "ThruDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition(featurePrefix + "ThruDate", EntityOperator.GREATER_THAN, this.nowTimestamp))); |
| incExcCondList.add(EntityCondition.makeCondition(featurePrefix + "FromDate", EntityOperator.LESS_THAN, this.nowTimestamp)); |
| incExcCondList.add(EntityCondition.makeCondition(featurePrefix + "ProductFeatureId", EntityOperator.IN, includeFeatureIdOrSet)); |
| } |
| } |
| if (alwaysIncludeFeatureIdOrSetAndList.size() > 0) { |
| for (Set<String> alwaysIncludeFeatureIdOrSet: alwaysIncludeFeatureIdOrSetAndList) { |
| String featurePrefix = "pfa" + this.index; |
| String entityAlias = "PFA" + this.index; |
| this.index++; |
| |
| this.dynamicViewEntity.addMemberEntity(entityAlias, "ProductFeatureAppl"); |
| this.dynamicViewEntity.addAlias(entityAlias, featurePrefix + "ProductFeatureId", "productFeatureId", null, null, null, null); |
| this.dynamicViewEntity.addAlias(entityAlias, featurePrefix + "FromDate", "fromDate", null, null, null, null); |
| this.dynamicViewEntity.addAlias(entityAlias, featurePrefix + "ThruDate", "thruDate", null, null, null, null); |
| this.dynamicViewEntity.addViewLink("PROD", entityAlias, Boolean.FALSE, ModelKeyMap.makeKeyMapList("productId")); |
| alwIncCondList.add(EntityCondition.makeCondition(EntityCondition.makeCondition(featurePrefix + "ThruDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition(featurePrefix + "ThruDate", EntityOperator.GREATER_THAN, this.nowTimestamp))); |
| alwIncCondList.add(EntityCondition.makeCondition(featurePrefix + "FromDate", EntityOperator.LESS_THAN, this.nowTimestamp)); |
| alwIncCondList.add(EntityCondition.makeCondition(featurePrefix + "ProductFeatureId", EntityOperator.IN, alwaysIncludeFeatureIdOrSet)); |
| } |
| } |
| |
| // handle includeCategoryIdOrSetAndList and alwaysIncludeCategoryIdOrSetAndList |
| if (includeCategoryIdOrSetAndList.size() > 0) { |
| for (Set<String> includeCategoryIdOrSet: includeCategoryIdOrSetAndList) { |
| String categoryPrefix = "pcm" + this.index; |
| String entityAlias = "PCM" + this.index; |
| this.index++; |
| |
| this.dynamicViewEntity.addMemberEntity(entityAlias, "ProductCategoryMember"); |
| this.dynamicViewEntity.addAlias(entityAlias, categoryPrefix + "ProductCategoryId", "productCategoryId", null, null, null, null); |
| this.dynamicViewEntity.addAlias(entityAlias, categoryPrefix + "FromDate", "fromDate", null, null, null, null); |
| this.dynamicViewEntity.addAlias(entityAlias, categoryPrefix + "ThruDate", "thruDate", null, null, null, null); |
| this.dynamicViewEntity.addViewLink("PROD", entityAlias, Boolean.FALSE, ModelKeyMap.makeKeyMapList("productId")); |
| incExcCondList.add(EntityCondition.makeCondition(EntityCondition.makeCondition(categoryPrefix + "ThruDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition(categoryPrefix + "ThruDate", EntityOperator.GREATER_THAN, this.nowTimestamp))); |
| incExcCondList.add(EntityCondition.makeCondition(categoryPrefix + "FromDate", EntityOperator.LESS_THAN, this.nowTimestamp)); |
| incExcCondList.add(EntityCondition.makeCondition(categoryPrefix + "ProductCategoryId", EntityOperator.IN, includeCategoryIdOrSet)); |
| } |
| } |
| if (alwaysIncludeCategoryIdOrSetAndList.size() > 0) { |
| for (Set<String> alwaysIncludeCategoryIdOrSet: alwaysIncludeCategoryIdOrSetAndList) { |
| String categoryPrefix = "pcm" + this.index; |
| String entityAlias = "PCM" + this.index; |
| this.index++; |
| |
| this.dynamicViewEntity.addMemberEntity(entityAlias, "ProductCategoryMember"); |
| this.dynamicViewEntity.addAlias(entityAlias, categoryPrefix + "ProductCategoryId", "productCategoryId", null, null, null, null); |
| this.dynamicViewEntity.addAlias(entityAlias, categoryPrefix + "FromDate", "fromDate", null, null, null, null); |
| this.dynamicViewEntity.addAlias(entityAlias, categoryPrefix + "ThruDate", "thruDate", null, null, null, null); |
| this.dynamicViewEntity.addViewLink("PROD", entityAlias, Boolean.FALSE, ModelKeyMap.makeKeyMapList("productId")); |
| alwIncCondList.add(EntityCondition.makeCondition(EntityCondition.makeCondition(categoryPrefix + "ThruDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition(categoryPrefix + "ThruDate", EntityOperator.GREATER_THAN, this.nowTimestamp))); |
| alwIncCondList.add(EntityCondition.makeCondition(categoryPrefix + "FromDate", EntityOperator.LESS_THAN, this.nowTimestamp)); |
| alwIncCondList.add(EntityCondition.makeCondition(categoryPrefix + "ProductCategoryId", EntityOperator.IN, alwaysIncludeCategoryIdOrSet)); |
| } |
| } |
| |
| if (incExcCondList.size() > 0) { |
| incExcCond = EntityCondition.makeCondition(incExcCondList, EntityOperator.AND); |
| } |
| if (alwIncCondList.size() > 0) { |
| alwIncCond = EntityCondition.makeCondition(alwIncCondList, EntityOperator.AND); |
| } |
| |
| if (incExcCond != null && alwIncCond != null) { |
| topCond = EntityCondition.makeCondition(incExcCond, EntityOperator.OR, alwIncCond); |
| } else if (incExcCond != null) { |
| topCond = incExcCond; |
| } else if (alwIncCond != null) { |
| topCond = alwIncCond; |
| } |
| |
| this.entityConditionList.add(topCond); |
| |
| Debug.logInfo("topCond=" + topCond.makeWhereString(null, FastList.<EntityConditionParam>newInstance(), EntityConfig.getDatasource(delegator.getEntityHelperName("Product"))), module); |
| } |
| |
| public EntityListIterator doQuery(Delegator delegator) { |
| // handle the now assembled or and and keyword fixed lists |
| this.finishKeywordConstraints(); |
| |
| this.finishCategoryAndFeatureConstraints(); |
| |
| if (resultSortOrder != null) { |
| resultSortOrder.setSortOrder(this); |
| } |
| |
| dynamicViewEntity.addAlias("PROD", "mainProductId", "productId", null, null, Boolean.valueOf(productIdGroupBy), null); |
| |
| EntityListIterator eli = null; |
| try { |
| int queryMaxResults = 0; |
| if (maxResults != null) { |
| queryMaxResults = maxResults; |
| if (resultOffset != null) { |
| queryMaxResults += resultOffset - 1; |
| } |
| } |
| eli = EntityQuery.use(delegator).select(UtilMisc.toSet(fieldsToSelect)) |
| .from(dynamicViewEntity).where(entityConditionList) |
| .orderBy(orderByList) |
| .distinct(true) |
| .maxRows(queryMaxResults) |
| .cursorScrollInsensitive() |
| .queryIterator(); |
| } catch (GenericEntityException e) { |
| Debug.logError(e, "Error in product search", module); |
| return null; |
| } |
| |
| return eli; |
| } |
| |
| public ArrayList<String> makeProductIdList(EntityListIterator eli) { |
| ArrayList<String> productIds = new ArrayList<String>(maxResults == null ? 100 : maxResults.intValue()); |
| if (eli == null) { |
| Debug.logWarning("The eli is null, returning zero results", module); |
| return productIds; |
| } |
| |
| try { |
| boolean hasResults = false; |
| Object initialResult = null; |
| |
| /* this method has been replaced by the following to address issue with SAP DB and possibly other DBs |
| if (resultOffset != null) { |
| Debug.logInfo("Before relative, current index=" + eli.currentIndex(), module); |
| hasResults = eli.relative(resultOffset.intValue()); |
| } else { |
| initialResult = eli.next(); |
| if (initialResult != null) { |
| hasResults = true; |
| } |
| } |
| */ |
| |
| initialResult = eli.next(); |
| if (initialResult != null) { |
| hasResults = true; |
| } |
| if (resultOffset != null && resultOffset.intValue() > 1) { |
| if (Debug.infoOn()) Debug.logInfo("Before relative, current index=" + eli.currentIndex(), module); |
| hasResults = eli.relative(resultOffset.intValue() - 1); |
| initialResult = null; |
| } |
| |
| // get the first as the current one |
| GenericValue searchResult = null; |
| if (hasResults) { |
| if (initialResult != null) { |
| searchResult = (GenericValue) initialResult; |
| } else { |
| searchResult = eli.currentGenericValue(); |
| } |
| } |
| |
| if (searchResult == null) { |
| // nothing to get... |
| int failTotal = 0; |
| if (this.resultOffset != null) { |
| failTotal = this.resultOffset.intValue() - 1; |
| } |
| this.totalResults = Integer.valueOf(failTotal); |
| return productIds; |
| } |
| |
| |
| // init numRetreived to one since we have already grabbed the initial one |
| int numRetreived = 1; |
| int duplicatesFound = 0; |
| |
| Set<String> productIdSet = FastSet.newInstance(); |
| |
| productIds.add(searchResult.getString("mainProductId")); |
| productIdSet.add(searchResult.getString("mainProductId")); |
| |
| while ((maxResults == null || numRetreived < maxResults.intValue()) && ((searchResult = eli.next()) != null)) { |
| String productId = searchResult.getString("mainProductId"); |
| if (!productIdSet.contains(productId)) { |
| productIds.add(productId); |
| productIdSet.add(productId); |
| numRetreived++; |
| } else { |
| duplicatesFound++; |
| } |
| |
| /* |
| StringBuilder lineMsg = new StringBuilder("Got search result line: "); |
| for (String fieldName: fieldsToSelect) { |
| lineMsg.append(fieldName); |
| lineMsg.append("="); |
| lineMsg.append(searchResult.get(fieldName)); |
| if (fieldsToSelectIter.hasNext()) { |
| lineMsg.append(", "); |
| } |
| } |
| Debug.logInfo(lineMsg.toString(), module); |
| */ |
| } |
| |
| if (searchResult != null) { |
| this.totalResults = eli.getResultsSizeAfterPartialList(); |
| } |
| if (this.totalResults == null || this.totalResults.intValue() == 0) { |
| int total = numRetreived; |
| if (this.resultOffset != null) { |
| total += (this.resultOffset.intValue() - 1); |
| } |
| this.totalResults = Integer.valueOf(total); |
| } |
| |
| Debug.logInfo("Got search values, numRetreived=" + numRetreived + ", totalResults=" + totalResults + ", maxResults=" + maxResults + ", resultOffset=" + resultOffset + ", duplicatesFound(in the current results)=" + duplicatesFound, module); |
| |
| } catch (GenericEntityException e) { |
| Debug.logError(e, "Error getting results from the product search query", module); |
| } |
| return productIds; |
| } |
| |
| public void saveSearchResultInfo(Long numResults, Double secondsTotal) { |
| // uses entities: ProductSearchResult and ProductSearchConstraint |
| |
| try { |
| // make sure this is in a transaction |
| boolean beganTransaction = TransactionUtil.begin(); |
| |
| try { |
| |
| GenericValue productSearchResult = delegator.makeValue("ProductSearchResult"); |
| String productSearchResultId = delegator.getNextSeqId("ProductSearchResult"); |
| |
| productSearchResult.set("productSearchResultId", productSearchResultId); |
| productSearchResult.set("visitId", this.visitId); |
| if (this.resultSortOrder != null) { |
| productSearchResult.set("orderByName", this.resultSortOrder.getOrderName()); |
| productSearchResult.set("isAscending", this.resultSortOrder.isAscending() ? "Y" : "N"); |
| } |
| productSearchResult.set("numResults", numResults); |
| productSearchResult.set("secondsTotal", secondsTotal); |
| productSearchResult.set("searchDate", nowTimestamp); |
| productSearchResult.create(); |
| |
| int seqId = 1; |
| for (GenericValue productSearchConstraint: productSearchConstraintList) { |
| productSearchConstraint.set("productSearchResultId", productSearchResultId); |
| productSearchConstraint.set("constraintSeqId", Integer.toString(seqId)); |
| productSearchConstraint.create(); |
| seqId++; |
| } |
| |
| TransactionUtil.commit(beganTransaction); |
| } catch (GenericEntityException e1) { |
| String errMsg = "Error saving product search result info/stats"; |
| Debug.logError(e1, errMsg, module); |
| TransactionUtil.rollback(beganTransaction, errMsg, e1); |
| } |
| } catch (GenericTransactionException e) { |
| Debug.logError(e, "Error saving product search result info/stats", module); |
| } |
| } |
| } |
| |
| // ====================================================================== |
| // Search Constraint Classes |
| // ====================================================================== |
| |
| @SuppressWarnings("serial") |
| public static abstract class ProductSearchConstraint implements java.io.Serializable { |
| public ProductSearchConstraint() { } |
| |
| public abstract void addConstraint(ProductSearchContext productSearchContext); |
| /** pretty print for log messages and even UI stuff */ |
| public abstract String prettyPrintConstraint(Delegator delegator, boolean detailed, Locale locale); |
| } |
| |
| |
| @SuppressWarnings("serial") |
| public static class CatalogConstraint extends ProductSearchConstraint { |
| public static final String constraintName = "Catalog"; |
| protected String prodCatalogId; |
| protected List<GenericValue> productCategories; |
| |
| public CatalogConstraint(String prodCatalogId, List<GenericValue> productCategories) { |
| this.prodCatalogId = prodCatalogId; |
| this.productCategories = productCategories; |
| } |
| |
| @Override |
| public void addConstraint(ProductSearchContext productSearchContext) { |
| List<String> productCategoryIds = FastList.newInstance(); |
| for (GenericValue category: productCategories) { |
| productCategoryIds.add(category.getString("productCategoryId")); |
| } |
| |
| // make index based values and increment |
| String entityAlias = "PCM" + productSearchContext.index; |
| String prefix = "pcm" + productSearchContext.index; |
| productSearchContext.index++; |
| |
| productSearchContext.dynamicViewEntity.addMemberEntity(entityAlias, "ProductCategoryMember"); |
| productSearchContext.dynamicViewEntity.addAlias(entityAlias, prefix + "ProductCategoryId", "productCategoryId", null, null, null, null); |
| productSearchContext.dynamicViewEntity.addAlias(entityAlias, prefix + "FromDate", "fromDate", null, null, null, null); |
| productSearchContext.dynamicViewEntity.addAlias(entityAlias, prefix + "ThruDate", "thruDate", null, null, null, null); |
| productSearchContext.dynamicViewEntity.addViewLink("PROD", entityAlias, Boolean.FALSE, ModelKeyMap.makeKeyMapList("productId")); |
| productSearchContext.entityConditionList.add(EntityCondition.makeCondition(prefix + "ProductCategoryId", EntityOperator.IN, productCategoryIds)); |
| productSearchContext.entityConditionList.add(EntityCondition.makeCondition(EntityCondition.makeCondition(prefix + "ThruDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition(prefix + "ThruDate", EntityOperator.GREATER_THAN, productSearchContext.nowTimestamp))); |
| productSearchContext.entityConditionList.add(EntityCondition.makeCondition(prefix + "FromDate", EntityOperator.LESS_THAN, productSearchContext.nowTimestamp)); |
| |
| // add in productSearchConstraint, don't worry about the productSearchResultId or constraintSeqId, those will be fill in later |
| productSearchContext.productSearchConstraintList.add(productSearchContext.getDelegator().makeValue("ProductSearchConstraint", UtilMisc.toMap("constraintName", constraintName, "infoString", this.prodCatalogId))); |
| } |
| |
| /** pretty print for log messages and even UI stuff */ |
| @Override |
| public String prettyPrintConstraint(Delegator delegator, boolean detailed, Locale locale) { |
| GenericValue prodCatalog = null; |
| try { |
| prodCatalog = EntityQuery.use(delegator).from("ProdCatalog").where("prodCatalogId", prodCatalogId).cache().queryOne(); |
| } catch (GenericEntityException e) { |
| Debug.logError(e, "Error finding ProdCatalog information for constraint pretty print", module); |
| } |
| StringBuilder ppBuf = new StringBuilder(); |
| ppBuf.append(UtilProperties.getMessage(resource, "ProductCatalog", locale)).append(": "); |
| if (prodCatalog != null) { |
| ppBuf.append(prodCatalog.getString("catalogName")); |
| } |
| return ppBuf.toString(); |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| ProductSearchConstraint psc = (ProductSearchConstraint) obj; |
| if (psc instanceof CatalogConstraint) { |
| CatalogConstraint that = (CatalogConstraint) psc; |
| if (this.prodCatalogId == null) { |
| if (that.prodCatalogId != null) { |
| return false; |
| } |
| } else { |
| if (!this.prodCatalogId.equals(that.prodCatalogId)) { |
| return false; |
| } |
| } |
| return true; |
| } else { |
| return false; |
| } |
| } |
| } |
| |
| @SuppressWarnings("serial") |
| public static class CategoryConstraint extends ProductSearchConstraint { |
| public static final String constraintName = "Category"; |
| protected String productCategoryId; |
| protected boolean includeSubCategories; |
| /** This is a tri-state variable: null = Include, true = Exclude, false = AlwaysInclude */ |
| protected Boolean exclude; |
| |
| /** |
| * |
| * @param productCategoryId |
| * @param includeSubCategories |
| * @param exclude This is a tri-state variable: null = Include, true = Exclude, false = AlwaysInclude |
| */ |
| public CategoryConstraint(String productCategoryId, boolean includeSubCategories, Boolean exclude) { |
| this.productCategoryId = productCategoryId; |
| this.includeSubCategories = includeSubCategories; |
| this.exclude = exclude; |
| } |
| |
| @Override |
| public void addConstraint(ProductSearchContext productSearchContext) { |
| Set<String> productCategoryIdSet = FastSet.newInstance(); |
| if (includeSubCategories) { |
| // find all sub-categories recursively, make a Set of productCategoryId |
| ProductSearch.getAllSubCategoryIds(productCategoryId, productCategoryIdSet, productSearchContext.getDelegator(), productSearchContext.nowTimestamp); |
| } else { |
| productCategoryIdSet.add(productCategoryId); |
| } |
| |
| // just add to global sets |
| if (exclude == null) { |
| productSearchContext.includeCategoryIdOrSetAndList.add(productCategoryIdSet); |
| } else if (exclude.equals(Boolean.TRUE)) { |
| productSearchContext.excludeCategoryIds.addAll(productCategoryIdSet); |
| } else if (exclude.equals(Boolean.FALSE)) { |
| productSearchContext.alwaysIncludeCategoryIdOrSetAndList.add(productCategoryIdSet); |
| } |
| |
| // add in productSearchConstraint, don't worry about the productSearchResultId or constraintSeqId, those will be fill in later |
| productSearchContext.productSearchConstraintList.add(productSearchContext.getDelegator().makeValue("ProductSearchConstraint", UtilMisc.toMap("constraintName", constraintName, "infoString", this.productCategoryId, "includeSubCategories", this.includeSubCategories ? "Y" : "N"))); |
| } |
| |
| /** pretty print for log messages and even UI stuff */ |
| @Override |
| public String prettyPrintConstraint(Delegator delegator, boolean detailed, Locale locale) { |
| GenericValue productCategory = null; |
| try { |
| productCategory = EntityQuery.use(delegator).from("ProductCategory").where("productCategoryId", productCategoryId).cache().queryOne(); |
| } catch (GenericEntityException e) { |
| Debug.logError(e, "Error finding ProductCategory information for constraint pretty print", module); |
| } |
| StringBuilder ppBuf = new StringBuilder(); |
| ppBuf.append(UtilProperties.getMessage(resource, "ProductCategory", locale)).append(": "); |
| if (productCategory != null) { |
| String catInfo = CategoryContentWrapper.getProductCategoryContentAsText(productCategory, "CATEGORY_NAME", locale, null); |
| if (UtilValidate.isEmpty(catInfo)) { |
| catInfo = CategoryContentWrapper.getProductCategoryContentAsText(productCategory, "DESCRIPTION", locale, null); |
| } |
| ppBuf.append(catInfo); |
| } |
| if (productCategory == null || detailed) { |
| ppBuf.append(" ["); |
| ppBuf.append(productCategoryId); |
| ppBuf.append("]"); |
| } |
| if (includeSubCategories) { |
| ppBuf.append(" (").append(UtilProperties.getMessage(resource, "ProductIncludeAllSubCategories", locale)).append(")"); |
| } |
| return ppBuf.toString(); |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| ProductSearchConstraint psc = (ProductSearchConstraint) obj; |
| if (psc instanceof CategoryConstraint) { |
| CategoryConstraint that = (CategoryConstraint) psc; |
| if (this.includeSubCategories != that.includeSubCategories) { |
| return false; |
| } |
| if (this.productCategoryId == null) { |
| if (that.productCategoryId != null) { |
| return false; |
| } |
| } else { |
| if (!this.productCategoryId.equals(that.productCategoryId)) { |
| return false; |
| } |
| } |
| return true; |
| } else { |
| return false; |
| } |
| } |
| } |
| |
| @SuppressWarnings("serial") |
| public static class FeatureConstraint extends ProductSearchConstraint { |
| public static final String constraintName = "Feature"; |
| protected String productFeatureId; |
| /** This is a tri-state variable: null = Include, true = Exclude, false = AlwaysInclude */ |
| protected Boolean exclude; |
| |
| /** |
| * |
| * @param productFeatureId |
| * @param exclude This is a tri-state variable: null = Include, true = Exclude, false = AlwaysInclude |
| */ |
| public FeatureConstraint(String productFeatureId, Boolean exclude) { |
| this.productFeatureId = productFeatureId; |
| this.exclude = exclude; |
| } |
| |
| @Override |
| public void addConstraint(ProductSearchContext productSearchContext) { |
| // just add to global sets |
| if (exclude == null) { |
| productSearchContext.includeFeatureIds.add(productFeatureId); |
| } else if (exclude.equals(Boolean.TRUE)) { |
| productSearchContext.excludeFeatureIds.add(productFeatureId); |
| } else if (exclude.equals(Boolean.FALSE)) { |
| productSearchContext.alwaysIncludeFeatureIds.add(productFeatureId); |
| } |
| |
| // add in productSearchConstraint, don't worry about the productSearchResultId or constraintSeqId, those will be fill in later |
| productSearchContext.productSearchConstraintList.add(productSearchContext.getDelegator().makeValue("ProductSearchConstraint", UtilMisc.toMap("constraintName", constraintName, "infoString", this.productFeatureId))); |
| } |
| |
| @Override |
| public String prettyPrintConstraint(Delegator delegator, boolean detailed, Locale locale) { |
| GenericValue productFeature = null; |
| GenericValue productFeatureType = null; |
| try { |
| productFeature = EntityQuery.use(delegator).from("ProductFeature").where("productFeatureId", productFeatureId).cache().queryOne(); |
| productFeatureType = productFeature == null ? null : productFeature.getRelatedOne("ProductFeatureType", false); |
| } catch (GenericEntityException e) { |
| Debug.logError(e, "Error finding ProductFeature and Type information for constraint pretty print", module); |
| } |
| StringBuilder ppBuf = new StringBuilder(); |
| if (productFeatureType == null) { |
| ppBuf.append(UtilProperties.getMessage(resource, "ProductFeature", locale)).append(": "); |
| ppBuf.append("[").append(this.productFeatureId).append("]"); |
| } else { |
| // TODO getString to be localized like get("description", locale) |
| ppBuf.append(productFeatureType.getString("description")).append(": "); |
| ppBuf.append(productFeature.getString("description")); |
| } |
| if (this.exclude != null) { |
| if (Boolean.TRUE.equals(this.exclude)) { |
| ppBuf.append(" (Exclude)"); |
| } else { |
| ppBuf.append(" (Always Include)"); |
| } |
| } |
| return (ppBuf.toString()); |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| ProductSearchConstraint psc = (ProductSearchConstraint) obj; |
| if (psc instanceof FeatureConstraint) { |
| FeatureConstraint that = (FeatureConstraint) psc; |
| if (this.productFeatureId == null) { |
| if (that.productFeatureId != null) { |
| return false; |
| } |
| } else { |
| if (!this.productFeatureId.equals(that.productFeatureId)) { |
| return false; |
| } |
| } |
| return true; |
| } else { |
| return false; |
| } |
| } |
| } |
| |
| |
| @SuppressWarnings("serial") |
| public static class FeatureCategoryConstraint extends ProductSearchConstraint { |
| public static final String constraintName = "FeatureCategory"; |
| protected String productFeatureCategoryId; |
| /** This is a tri-state variable: null = Include, true = Exclude, false = AlwaysInclude */ |
| protected Boolean exclude; |
| |
| /** |
| * |
| * @param productFeatureCategoryId |
| * @param exclude This is a tri-state variable: null = Include, true = Exclude, false = AlwaysInclude |
| */ |
| public FeatureCategoryConstraint(String productFeatureCategoryId, Boolean exclude) { |
| this.productFeatureCategoryId = productFeatureCategoryId; |
| this.exclude = exclude; |
| } |
| |
| @Override |
| public void addConstraint(ProductSearchContext productSearchContext) { |
| // just add to global sets |
| if (exclude == null) { |
| productSearchContext.includeFeatureCategoryIds.add(productFeatureCategoryId); |
| } else if (exclude.equals(Boolean.TRUE)) { |
| productSearchContext.excludeFeatureCategoryIds.add(productFeatureCategoryId); |
| } else if (exclude.equals(Boolean.FALSE)) { |
| productSearchContext.alwaysIncludeFeatureCategoryIds.add(productFeatureCategoryId); |
| } |
| |
| // add in productSearchConstraint, don't worry about the productSearchResultId or constraintSeqId, those will be fill in later |
| productSearchContext.productSearchConstraintList.add(productSearchContext.getDelegator().makeValue("ProductSearchConstraint", UtilMisc.toMap("constraintName", constraintName, "infoString", this.productFeatureCategoryId))); |
| } |
| |
| @Override |
| public String prettyPrintConstraint(Delegator delegator, boolean detailed, Locale locale) { |
| GenericValue productFeatureCategory = null; |
| try { |
| productFeatureCategory = EntityQuery.use(delegator).from("ProductFeatureCategory").where("productFeatureCategoryId", productFeatureCategoryId).cache().queryOne(); |
| } catch (GenericEntityException e) { |
| Debug.logError(e, "Error finding ProductFeatureCategory and Type information for constraint pretty print", module); |
| } |
| StringBuilder ppBuf = new StringBuilder(); |
| if (productFeatureCategory != null) { |
| ppBuf.append(UtilProperties.getMessage(resource, "ProductFeatureCategory", locale)).append(": "); |
| if (productFeatureCategory.get("description") != null) { |
| ppBuf.append(productFeatureCategory.get("description")); |
| } else { |
| ppBuf.append("[").append(this.productFeatureCategoryId).append("]"); |
| } |
| |
| } |
| if (this.exclude != null) { |
| if (Boolean.TRUE.equals(this.exclude)) { |
| ppBuf.append(" (Exclude)"); |
| } else { |
| ppBuf.append(" (Always Include)"); |
| } |
| } |
| return (ppBuf.toString()); |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| ProductSearchConstraint psc = (ProductSearchConstraint) obj; |
| if (psc instanceof FeatureCategoryConstraint) { |
| FeatureCategoryConstraint that = (FeatureCategoryConstraint) psc; |
| if (this.productFeatureCategoryId == null) { |
| if (that.productFeatureCategoryId != null) { |
| return false; |
| } |
| } else { |
| if (!this.productFeatureCategoryId.equals(that.productFeatureCategoryId)) { |
| return false; |
| } |
| } |
| return true; |
| } else { |
| return false; |
| } |
| } |
| } |
| |
| @SuppressWarnings("serial") |
| public static class FeatureGroupConstraint extends ProductSearchConstraint { |
| public static final String constraintName = "FeatureGroup"; |
| protected String productFeatureGroupId; |
| /** This is a tri-state variable: null = Include, true = Exclude, false = AlwaysInclude */ |
| protected Boolean exclude; |
| |
| /** |
| * |
| * @param productFeatureGroupId |
| * @param exclude This is a tri-state variable: null = Include, true = Exclude, false = AlwaysInclude |
| */ |
| public FeatureGroupConstraint(String productFeatureGroupId, Boolean exclude) { |
| this.productFeatureGroupId = productFeatureGroupId; |
| this.exclude = exclude; |
| } |
| |
| @Override |
| public void addConstraint(ProductSearchContext productSearchContext) { |
| // just add to global sets |
| if (exclude == null) { |
| productSearchContext.includeFeatureGroupIds.add(productFeatureGroupId); |
| } else if (exclude.equals(Boolean.TRUE)) { |
| productSearchContext.excludeFeatureGroupIds.add(productFeatureGroupId); |
| } else if (exclude.equals(Boolean.FALSE)) { |
| productSearchContext.alwaysIncludeFeatureGroupIds.add(productFeatureGroupId); |
| } |
| |
| // add in productSearchConstraint, don't worry about the productSearchResultId or constraintSeqId, those will be fill in later |
| productSearchContext.productSearchConstraintList.add(productSearchContext.getDelegator().makeValue("ProductSearchConstraint", UtilMisc.toMap("constraintName", constraintName, "infoString", this.productFeatureGroupId))); |
| } |
| |
| @Override |
| public String prettyPrintConstraint(Delegator delegator, boolean detailed, Locale locale) { |
| GenericValue productFeatureGroup = null; |
| try { |
| productFeatureGroup = EntityQuery.use(delegator).from("ProductFeatureGroup").where("productFeatureGroupId", productFeatureGroupId).cache().queryOne(); |
| } catch (GenericEntityException e) { |
| Debug.logError(e, "Error finding ProductFeatureGroup and Type information for constraint pretty print", module); |
| } |
| StringBuilder ppBuf = new StringBuilder(); |
| if (productFeatureGroup != null) { |
| ppBuf.append(UtilProperties.getMessage(resource, "ProductFeatureGroup", locale)).append(": "); |
| if (productFeatureGroup.get("description") != null) { |
| ppBuf.append(productFeatureGroup.get("description")); |
| } else { |
| ppBuf.append("[").append(this.productFeatureGroupId).append("]"); |
| } |
| } |
| if (this.exclude != null) { |
| if (Boolean.TRUE.equals(this.exclude)) { |
| ppBuf.append(" (Exclude)"); |
| } else { |
| ppBuf.append(" (Always Include)"); |
| } |
| } |
| return (ppBuf.toString()); |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| ProductSearchConstraint psc = (ProductSearchConstraint) obj; |
| if (psc instanceof FeatureGroupConstraint) { |
| FeatureGroupConstraint that = (FeatureGroupConstraint) psc; |
| if (this.productFeatureGroupId == null) { |
| if (that.productFeatureGroupId != null) { |
| return false; |
| } |
| } else { |
| if (!this.productFeatureGroupId.equals(that.productFeatureGroupId)) { |
| return false; |
| } |
| } |
| return true; |
| } else { |
| return false; |
| } |
| } |
| } |
| |
| |
| @SuppressWarnings("serial") |
| public static class FeatureSetConstraint extends ProductSearchConstraint { |
| public static final String constraintName = "Feature Set"; |
| protected Set<String> productFeatureIdSet; |
| /** This is a tri-state variable: null = Include, true = Exclude, false = AlwaysInclude */ |
| protected Boolean exclude; |
| |
| /** |
| * |
| * @param productFeatureIdSet |
| * @param exclude This is a tri-state variable: null = Include, true = Exclude, false = AlwaysInclude |
| */ |
| public FeatureSetConstraint(Collection<String> productFeatureIdSet, Boolean exclude) { |
| this.productFeatureIdSet = FastSet.newInstance(); |
| this.productFeatureIdSet.addAll(productFeatureIdSet); |
| this.exclude = exclude; |
| } |
| |
| @Override |
| public void addConstraint(ProductSearchContext productSearchContext) { |
| // just add to global sets |
| if (exclude == null) { |
| productSearchContext.includeFeatureIdOrSetAndList.add(productFeatureIdSet); |
| } else if (exclude.equals(Boolean.TRUE)) { |
| productSearchContext.excludeFeatureIds.addAll(productFeatureIdSet); |
| } else if (exclude.equals(Boolean.FALSE)) { |
| productSearchContext.alwaysIncludeFeatureIdOrSetAndList.add(productFeatureIdSet); |
| } |
| |
| // add in productSearchConstraint, don't worry about the productSearchResultId or constraintSeqId, those will be fill in later |
| StringBuilder featureIdInfo = new StringBuilder(); |
| for (String featureId: this.productFeatureIdSet) { |
| if (featureIdInfo.length() > 0) { |
| featureIdInfo.append(","); |
| } |
| featureIdInfo.append(featureId); |
| } |
| |
| productSearchContext.productSearchConstraintList.add(productSearchContext.getDelegator().makeValue("ProductSearchConstraint", UtilMisc.toMap("constraintName", constraintName, "infoString", featureIdInfo.toString()))); |
| } |
| |
| @Override |
| public String prettyPrintConstraint(Delegator delegator, boolean detailed, Locale locale) { |
| StringBuilder infoOut = new StringBuilder(); |
| try { |
| for (String featureId: this.productFeatureIdSet) { |
| if (infoOut.length() > 0) { |
| infoOut.append(", "); |
| } |
| GenericValue productFeature = EntityQuery.use(delegator).from("ProductFeature").where("productFeatureId", featureId).cache().queryOne(); |
| GenericValue productFeatureType = productFeature == null ? null : productFeature.getRelatedOne("ProductFeatureType", true); |
| if (productFeatureType == null) { |
| infoOut.append(UtilProperties.getMessage(resource, "ProductFeature", locale)).append(": "); |
| } else { |
| infoOut.append(productFeatureType.getString("description")); |
| infoOut.append(": "); |
| } |
| if (productFeature == null) { |
| infoOut.append("["); |
| infoOut.append(featureId); |
| infoOut.append("]"); |
| } else { |
| infoOut.append(productFeature.getString("description")); |
| } |
| |
| } |
| } catch (GenericEntityException e) { |
| Debug.logError(e, "Error finding ProductFeature and Type information for constraint pretty print", module); |
| } |
| |
| return infoOut.toString(); |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| ProductSearchConstraint psc = (ProductSearchConstraint) obj; |
| if (psc instanceof FeatureSetConstraint) { |
| FeatureSetConstraint that = (FeatureSetConstraint) psc; |
| if (this.productFeatureIdSet == null) { |
| if (that.productFeatureIdSet != null) { |
| return false; |
| } |
| } else { |
| if (!this.productFeatureIdSet.equals(that.productFeatureIdSet)) { |
| return false; |
| } |
| } |
| return true; |
| } else { |
| return false; |
| } |
| } |
| } |
| |
| @SuppressWarnings("serial") |
| public static class KeywordConstraint extends ProductSearchConstraint { |
| public static final String constraintName = "Keyword"; |
| protected String keywordsString; |
| protected boolean anyPrefix; |
| protected boolean anySuffix; |
| protected boolean isAnd; |
| protected boolean removeStems; |
| |
| public KeywordConstraint(String keywordsString, boolean anyPrefix, boolean anySuffix, Boolean removeStems, boolean isAnd) { |
| this.keywordsString = keywordsString; |
| this.anyPrefix = anyPrefix; |
| this.anySuffix = anySuffix; |
| this.isAnd = isAnd; |
| if (removeStems != null) { |
| this.removeStems = removeStems.booleanValue(); |
| } else { |
| this.removeStems = UtilProperties.propertyValueEquals("keywordsearch", "remove.stems", "true"); |
| } |
| } |
| |
| public Set<String> makeFullKeywordSet(Delegator delegator) { |
| Set<String> keywordSet = KeywordSearchUtil.makeKeywordSet(this.keywordsString, null, true); |
| Set<String> fullKeywordSet = new TreeSet<String>(); |
| |
| // expand the keyword list according to the thesaurus and create a new set of keywords |
| for (String keyword: keywordSet) { |
| Set<String> expandedSet = new TreeSet<String>(); |
| boolean replaceEntered = KeywordSearchUtil.expandKeywordForSearch(keyword, expandedSet, delegator); |
| fullKeywordSet.addAll(expandedSet); |
| if (!replaceEntered) { |
| fullKeywordSet.add(keyword); |
| } |
| } |
| |
| return fullKeywordSet; |
| } |
| |
| @Override |
| public void addConstraint(ProductSearchContext productSearchContext) { |
| // just make the fixed keyword lists and put them in the context |
| if (isAnd) { |
| // when isAnd is true we need to make a list of keyword sets where each set corresponds to one |
| //incoming/entered keyword and contains all of the expanded keywords plus the entered keyword if none of |
| //the expanded keywords are flagged as replacements; now the tricky part: each set should be or'ed together, |
| //but then the sets should be and'ed to produce the overall expression; create the SQL for this |
| //needs some work as the current method only support a list of and'ed words and a list of or'ed words, not |
| //a list of or'ed sets to be and'ed together |
| Set<String> keywordSet = KeywordSearchUtil.makeKeywordSet(this.keywordsString, null, true); |
| |
| // expand the keyword list according to the thesaurus and create a new set of keywords |
| for (String keyword: keywordSet) { |
| Set<String> expandedSet = new TreeSet<String>(); |
| boolean replaceEntered = KeywordSearchUtil.expandKeywordForSearch(keyword, expandedSet, productSearchContext.getDelegator()); |
| if (!replaceEntered) { |
| expandedSet.add(keyword); |
| } |
| Set<String> fixedSet = KeywordSearchUtil.fixKeywordsForSearch(expandedSet, anyPrefix, anySuffix, removeStems, isAnd); |
| Set<String> fixedKeywordSet = FastSet.newInstance(); |
| fixedKeywordSet.addAll(fixedSet); |
| productSearchContext.keywordFixedOrSetAndList.add(fixedKeywordSet); |
| } |
| } else { |
| // when isAnd is false, just add all of the new entries to the big list |
| Set<String> keywordFirstPass = makeFullKeywordSet(productSearchContext.getDelegator()); // includes keyword expansion, etc |
| Set<String> keywordSet = KeywordSearchUtil.fixKeywordsForSearch(keywordFirstPass, anyPrefix, anySuffix, removeStems, isAnd); |
| productSearchContext.orKeywordFixedSet.addAll(keywordSet); |
| } |
| |
| // add in productSearchConstraint, don't worry about the productSearchResultId or constraintSeqId, those will be fill in later |
| Map<String, String> valueMap = UtilMisc.toMap("constraintName", constraintName, "infoString", this.keywordsString); |
| valueMap.put("anyPrefix", this.anyPrefix ? "Y" : "N"); |
| valueMap.put("anySuffix", this.anySuffix ? "Y" : "N"); |
| valueMap.put("isAnd", this.isAnd ? "Y" : "N"); |
| valueMap.put("removeStems", this.removeStems ? "Y" : "N"); |
| productSearchContext.productSearchConstraintList.add(productSearchContext.getDelegator().makeValue("ProductSearchConstraint", valueMap)); |
| } |
| |
| /** pretty print for log messages and even UI stuff */ |
| @Override |
| public String prettyPrintConstraint(Delegator delegator, boolean detailed, Locale locale) { |
| StringBuilder ppBuf = new StringBuilder(); |
| ppBuf.append(UtilProperties.getMessage(resource, "ProductKeywords", locale)).append(": \""); |
| ppBuf.append(this.keywordsString).append("\", ").append(UtilProperties.getMessage(resource, "ProductKeywordWhere", locale)).append(" "); |
| ppBuf.append(isAnd ? UtilProperties.getMessage(resource, "ProductKeywordAllWordsMatch", locale) : UtilProperties.getMessage(resource, "ProductKeywordAnyWordMatches", locale)); |
| return ppBuf.toString(); |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| ProductSearchConstraint psc = (ProductSearchConstraint) obj; |
| if (psc instanceof KeywordConstraint) { |
| KeywordConstraint that = (KeywordConstraint) psc; |
| if (this.anyPrefix != that.anyPrefix) { |
| return false; |
| } |
| if (this.anySuffix != that.anySuffix) { |
| return false; |
| } |
| if (this.isAnd != that.isAnd) { |
| return false; |
| } |
| if (this.removeStems != that.removeStems) { |
| return false; |
| } |
| if (this.keywordsString == null) { |
| if (that.keywordsString != null) { |
| return false; |
| } |
| } else { |
| if (!this.keywordsString.equals(that.keywordsString)) { |
| return false; |
| } |
| } |
| return true; |
| } else { |
| return false; |
| } |
| } |
| } |
| |
| @SuppressWarnings("serial") |
| public static class LastUpdatedRangeConstraint extends ProductSearchConstraint { |
| public static final String constraintName = "LastUpdatedRange"; |
| protected Timestamp fromDate; |
| protected Timestamp thruDate; |
| |
| public LastUpdatedRangeConstraint(Timestamp fromDate, Timestamp thruDate) { |
| this.fromDate = fromDate; |
| this.thruDate = thruDate; |
| } |
| |
| @Override |
| public void addConstraint(ProductSearchContext productSearchContext) { |
| // TODO: implement LastUpdatedRangeConstraint makeEntityCondition |
| } |
| |
| /** pretty print for log messages and even UI stuff */ |
| @Override |
| public String prettyPrintConstraint(Delegator delegator, boolean detailed, Locale locale) { |
| // TODO: implement the pretty print for log messages and even UI stuff |
| return null; |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| ProductSearchConstraint psc = (ProductSearchConstraint) obj; |
| if (psc instanceof LastUpdatedRangeConstraint) { |
| LastUpdatedRangeConstraint that = (LastUpdatedRangeConstraint) psc; |
| if (this.fromDate == null) { |
| if (that.fromDate != null) { |
| return false; |
| } |
| } else { |
| if (!this.fromDate.equals(that.fromDate)) { |
| return false; |
| } |
| } |
| if (this.thruDate == null) { |
| if (that.thruDate != null) { |
| return false; |
| } |
| } else { |
| if (!this.thruDate.equals(that.thruDate)) { |
| return false; |
| } |
| } |
| return true; |
| } else { |
| return false; |
| } |
| } |
| } |
| |
| @SuppressWarnings("serial") |
| public static class StoreGroupPriceConstraint extends ProductSearchConstraint { |
| public static final String constraintName = "StoreGroupPrice"; |
| protected String productStoreGroupId; |
| protected String productPriceTypeId; |
| protected String currencyUomId; |
| |
| public StoreGroupPriceConstraint(String productStoreGroupId, String productPriceTypeId, String currencyUomId) { |
| this.productStoreGroupId = productStoreGroupId; |
| this.productPriceTypeId = productPriceTypeId == null ? "LIST_PRICE" : productPriceTypeId; |
| this.currencyUomId = currencyUomId; |
| } |
| |
| @Override |
| public void addConstraint(ProductSearchContext context) { |
| String entityAlias = "PSPP" + context.index; |
| String prefix = "PSPP" + context.index; |
| context.dynamicViewEntity.addMemberEntity(entityAlias, "ProductPrice"); |
| |
| context.dynamicViewEntity.addAlias(entityAlias, prefix + "ProductPriceTypeId", "productPriceTypeId", null, null, null, null); |
| context.dynamicViewEntity.addAlias(entityAlias, prefix + "ProductPricePurposeId", "productPricePurposeId", null, null, null, null); |
| context.dynamicViewEntity.addAlias(entityAlias, prefix + "CurrencyUomId", "currencyUomId", null, null, null, null); |
| context.dynamicViewEntity.addAlias(entityAlias, prefix + "ProductStoreGroupId", "productStoreGroupId", null, null, null, null); |
| context.dynamicViewEntity.addAlias(entityAlias, prefix + "FromDate", "fromDate", null, null, null, null); |
| context.dynamicViewEntity.addAlias(entityAlias, prefix + "ThruDate", "thruDate", null, null, null, null); |
| |
| context.dynamicViewEntity.addViewLink("PROD", entityAlias, Boolean.FALSE, ModelKeyMap.makeKeyMapList("productId")); |
| |
| context.entityConditionList.add(EntityCondition.makeCondition(prefix + "ProductPriceTypeId", EntityOperator.EQUALS, productPriceTypeId)); |
| context.entityConditionList.add(EntityCondition.makeCondition(prefix + "ProductPricePurposeId", EntityOperator.EQUALS, "PURCHASE")); |
| context.entityConditionList.add(EntityCondition.makeCondition(prefix + "CurrencyUomId", EntityOperator.EQUALS, currencyUomId)); |
| context.entityConditionList.add(EntityCondition.makeCondition(prefix + "ProductStoreGroupId", EntityOperator.EQUALS, productStoreGroupId)); |
| context.entityConditionList.add(EntityCondition.makeCondition(EntityCondition.makeCondition(prefix + "ThruDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition(prefix + "ThruDate", EntityOperator.GREATER_THAN, context.nowTimestamp))); |
| context.entityConditionList.add(EntityCondition.makeCondition(prefix + "FromDate", EntityOperator.LESS_THAN, context.nowTimestamp)); |
| } |
| |
| @Override |
| public String prettyPrintConstraint(Delegator delegator, boolean detailed, Locale locale) { |
| StringBuilder buff = new StringBuilder(); |
| buff.append("Product Store Mandatory Price Constraint: "); |
| buff.append("Product Store Group [").append(productStoreGroupId).append("], "); |
| buff.append("Product Price Type [").append(productPriceTypeId).append("], "); |
| buff.append("Currency [").append(currencyUomId).append("]."); |
| return buff.toString(); |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (o instanceof StoreGroupPriceConstraint) { |
| StoreGroupPriceConstraint other = (StoreGroupPriceConstraint) o; |
| if (other.productStoreGroupId.equals(productStoreGroupId) && |
| other.productPriceTypeId.equals(productPriceTypeId) && |
| other.currencyUomId.equals(currencyUomId)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| } |
| |
| @SuppressWarnings("serial") |
| public static class ListPriceRangeConstraint extends ProductSearchConstraint { |
| public static final String constraintName = "ListPriceRange"; |
| protected BigDecimal lowPrice; |
| protected BigDecimal highPrice; |
| protected String currencyUomId; |
| |
| public ListPriceRangeConstraint(BigDecimal lowPrice, BigDecimal highPrice, String currencyUomId) { |
| this.lowPrice = lowPrice; |
| this.highPrice = highPrice; |
| this.currencyUomId = UtilValidate.isNotEmpty(currencyUomId) ? currencyUomId : "USD"; |
| } |
| |
| @Override |
| public void addConstraint(ProductSearchContext productSearchContext) { |
| // make index based values and increment |
| String entityAlias = "PP" + productSearchContext.index; |
| String prefix = "pp" + productSearchContext.index; |
| productSearchContext.index++; |
| |
| productSearchContext.dynamicViewEntity.addMemberEntity(entityAlias, "ProductPrice"); |
| |
| productSearchContext.dynamicViewEntity.addAlias(entityAlias, prefix + "ProductPriceTypeId", "productPriceTypeId", null, null, null, null); |
| productSearchContext.dynamicViewEntity.addAlias(entityAlias, prefix + "ProductPricePurposeId", "productPricePurposeId", null, null, null, null); |
| productSearchContext.dynamicViewEntity.addAlias(entityAlias, prefix + "CurrencyUomId", "currencyUomId", null, null, null, null); |
| productSearchContext.dynamicViewEntity.addAlias(entityAlias, prefix + "ProductStoreGroupId", "productStoreGroupId", null, null, null, null); |
| productSearchContext.dynamicViewEntity.addAlias(entityAlias, prefix + "FromDate", "fromDate", null, null, null, null); |
| productSearchContext.dynamicViewEntity.addAlias(entityAlias, prefix + "ThruDate", "thruDate", null, null, null, null); |
| productSearchContext.dynamicViewEntity.addAlias(entityAlias, prefix + "Price", "price", null, null, null, null); |
| |
| productSearchContext.dynamicViewEntity.addViewLink("PROD", entityAlias, Boolean.FALSE, ModelKeyMap.makeKeyMapList("productId")); |
| |
| productSearchContext.entityConditionList.add(EntityCondition.makeCondition(prefix + "ProductPriceTypeId", EntityOperator.EQUALS, "LIST_PRICE")); |
| productSearchContext.entityConditionList.add(EntityCondition.makeCondition(prefix + "ProductPricePurposeId", EntityOperator.EQUALS, "PURCHASE")); |
| productSearchContext.entityConditionList.add(EntityCondition.makeCondition(prefix + "CurrencyUomId", EntityOperator.EQUALS, currencyUomId)); |
| productSearchContext.entityConditionList.add(EntityCondition.makeCondition(prefix + "ProductStoreGroupId", EntityOperator.EQUALS, "_NA_")); |
| productSearchContext.entityConditionList.add(EntityCondition.makeCondition(EntityCondition.makeCondition(prefix + "ThruDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition(prefix + "ThruDate", EntityOperator.GREATER_THAN, productSearchContext.nowTimestamp))); |
| productSearchContext.entityConditionList.add(EntityCondition.makeCondition(prefix + "FromDate", EntityOperator.LESS_THAN, productSearchContext.nowTimestamp)); |
| if (this.lowPrice != null) { |
| productSearchContext.entityConditionList.add(EntityCondition.makeCondition(prefix + "Price", EntityOperator.GREATER_THAN_EQUAL_TO, this.lowPrice)); |
| } |
| if (this.highPrice != null) { |
| productSearchContext.entityConditionList.add(EntityCondition.makeCondition(prefix + "Price", EntityOperator.LESS_THAN_EQUAL_TO, this.highPrice)); |
| } |
| |
| // add in productSearchConstraint, don't worry about the productSearchResultId or constraintSeqId, those will be fill in later |
| productSearchContext.productSearchConstraintList.add(productSearchContext.getDelegator().makeValue("ProductSearchConstraint", |
| UtilMisc.toMap("constraintName", constraintName, "infoString", "low [" + this.lowPrice + "] high [" + this.highPrice + "] currency [" + this.currencyUomId + "]"))); |
| } |
| |
| @Override |
| public String prettyPrintConstraint(Delegator delegator, boolean detailed, Locale locale) { |
| if (this.lowPrice == null && this.highPrice == null) { |
| // dummy constraint, no values |
| return null; |
| } |
| StringBuilder msgBuf = new StringBuilder(); |
| msgBuf.append(UtilProperties.getMessage(resource, "ProductListPriceRange", locale)); |
| msgBuf.append(": "); |
| |
| // NOTE: at this point we know that only one or none are null |
| if (this.lowPrice == null) { |
| msgBuf.append(UtilProperties.getMessage(resourceCommon, "CommonLessThan", locale)); |
| msgBuf.append(" "); |
| msgBuf.append(this.highPrice); |
| } else if (this.highPrice == null) { |
| msgBuf.append(UtilProperties.getMessage(resourceCommon, "CommonMoreThan", locale)); |
| msgBuf.append(" "); |
| msgBuf.append(this.lowPrice); |
| } else { |
| msgBuf.append(this.lowPrice); |
| msgBuf.append(" - "); |
| msgBuf.append(this.highPrice); |
| } |
| return msgBuf.toString(); |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| ProductSearchConstraint psc = (ProductSearchConstraint) obj; |
| if (psc instanceof ListPriceRangeConstraint) { |
| ListPriceRangeConstraint that = (ListPriceRangeConstraint) psc; |
| if (this.lowPrice == null) { |
| if (that.lowPrice != null) { |
| return false; |
| } |
| } else { |
| if (this.lowPrice.compareTo(that.lowPrice) != 0) { |
| return false; |
| } |
| } |
| if (this.highPrice == null) { |
| if (that.highPrice != null) { |
| return false; |
| } |
| } else { |
| if (this.highPrice.compareTo(that.highPrice) != 0) { |
| return false; |
| } |
| } |
| return true; |
| } else { |
| return false; |
| } |
| } |
| } |
| |
| @SuppressWarnings("serial") |
| public static class SupplierConstraint extends ProductSearchConstraint { |
| public static final String constraintName = "Supplier"; |
| protected String supplierPartyId; |
| |
| public SupplierConstraint(String supplierPartyId) { |
| this.supplierPartyId = supplierPartyId; |
| } |
| |
| @Override |
| public void addConstraint(ProductSearchContext productSearchContext) { |
| // make index based values and increment |
| String entityAlias = "SP" + productSearchContext.index; |
| String prefix = "sp" + productSearchContext.index; |
| productSearchContext.index++; |
| |
| productSearchContext.dynamicViewEntity.addMemberEntity(entityAlias, "SupplierProduct"); |
| productSearchContext.dynamicViewEntity.addAlias(entityAlias, prefix + "SupplierPartyId", "partyId", null, null, null, null); |
| productSearchContext.dynamicViewEntity.addViewLink("PROD", entityAlias, Boolean.FALSE, ModelKeyMap.makeKeyMapList("productId")); |
| productSearchContext.entityConditionList.add(EntityCondition.makeCondition(prefix + "SupplierPartyId", EntityOperator.EQUALS, supplierPartyId)); |
| |
| // add in productSearchConstraint, don't worry about the productSearchResultId or constraintSeqId, those will be fill in later |
| productSearchContext.productSearchConstraintList.add(productSearchContext.getDelegator().makeValue("ProductSearchConstraint", UtilMisc.toMap("constraintName", constraintName, "infoString", this.supplierPartyId))); |
| } |
| |
| @Override |
| public String prettyPrintConstraint(Delegator delegator, boolean detailed, Locale locale) { |
| return UtilProperties.getMessage(resource, "ProductSupplier", locale)+": " + PartyHelper.getPartyName(delegator, supplierPartyId, false); |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| ProductSearchConstraint psc = (ProductSearchConstraint) obj; |
| if (psc instanceof SupplierConstraint) { |
| SupplierConstraint that = (SupplierConstraint) psc; |
| if (this.supplierPartyId == null) { |
| if (that.supplierPartyId != null) { |
| return false; |
| } |
| } else { |
| if (!this.supplierPartyId.equals(that.supplierPartyId)) { |
| return false; |
| } |
| } |
| return true; |
| } else { |
| return false; |
| } |
| } |
| } |
| |
| @SuppressWarnings("serial") |
| public static class ExcludeVariantsConstraint extends ProductSearchConstraint { |
| public static final String constraintName = "ExcludeVariants"; |
| |
| public ExcludeVariantsConstraint() { |
| } |
| |
| @Override |
| public void addConstraint(ProductSearchContext productSearchContext) { |
| productSearchContext.dynamicViewEntity.addAlias("PROD", "prodIsVariant", "isVariant", null, null, null, null); |
| productSearchContext.entityConditionList.add(EntityCondition.makeCondition("prodIsVariant", EntityOperator.NOT_EQUAL, "Y")); |
| |
| // add in productSearchConstraint, don't worry about the productSearchResultId or constraintSeqId, those will be fill in later |
| productSearchContext.productSearchConstraintList.add(productSearchContext.getDelegator().makeValue("ProductSearchConstraint", UtilMisc.toMap("constraintName", constraintName, "infoString", ""))); |
| } |
| |
| @Override |
| public String prettyPrintConstraint(Delegator delegator, boolean detailed, Locale locale) { |
| return UtilProperties.getMessage(resource, "ProductExcludeVariants", locale); |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| ProductSearchConstraint psc = (ProductSearchConstraint) obj; |
| if (psc instanceof ExcludeVariantsConstraint) { |
| return true; |
| } else { |
| return false; |
| } |
| } |
| } |
| |
| @SuppressWarnings("serial") |
| public static class AvailabilityDateConstraint extends ProductSearchConstraint { |
| public static final String constraintName = "AvailabilityDate"; |
| |
| public AvailabilityDateConstraint() { |
| } |
| |
| @Override |
| public void addConstraint(ProductSearchContext productSearchContext) { |
| productSearchContext.dynamicViewEntity.addAlias("PROD", "prodIntroductionDate", "introductionDate", null, null, null, null); |
| productSearchContext.entityConditionList.add(EntityCondition.makeCondition(EntityCondition.makeCondition("prodIntroductionDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition("prodIntroductionDate", EntityOperator.LESS_THAN_EQUAL_TO, productSearchContext.nowTimestamp))); |
| productSearchContext.dynamicViewEntity.addAlias("PROD", "prodSalesDiscontinuationDate", "salesDiscontinuationDate", null, null, null, null); |
| productSearchContext.entityConditionList.add(EntityCondition.makeCondition(EntityCondition.makeCondition("prodSalesDiscontinuationDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition("prodSalesDiscontinuationDate", EntityOperator.GREATER_THAN, productSearchContext.nowTimestamp))); |
| productSearchContext.productSearchConstraintList.add(productSearchContext.getDelegator().makeValue("ProductSearchConstraint", UtilMisc.toMap("constraintName", constraintName, "infoString", ""))); |
| } |
| |
| @Override |
| public String prettyPrintConstraint(Delegator delegator, boolean detailed, Locale locale) { |
| return UtilProperties.getMessage(resource, "ProductFilterByAvailabilityDates", locale); |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| ProductSearchConstraint psc = (ProductSearchConstraint) obj; |
| if (psc instanceof AvailabilityDateConstraint) { |
| return true; |
| } else { |
| return false; |
| } |
| } |
| } |
| |
| @SuppressWarnings("serial") |
| public static class GoodIdentificationConstraint extends ProductSearchConstraint { |
| public static final String constraintName = "GoodIdentification"; |
| protected String goodIdentificationTypeId; |
| protected String goodIdentificationValue; |
| protected Boolean include; |
| |
| public GoodIdentificationConstraint(String goodIdentificationTypeId, String goodIdentificationValue, Boolean include) { |
| this.goodIdentificationTypeId = goodIdentificationTypeId; |
| this.goodIdentificationValue = goodIdentificationValue; |
| this.include = include; |
| } |
| |
| @Override |
| public void addConstraint(ProductSearchContext productSearchContext) { |
| if (UtilValidate.isNotEmpty(goodIdentificationTypeId) || |
| UtilValidate.isNotEmpty(goodIdentificationValue) || |
| UtilValidate.isNotEmpty(include)) { |
| |
| // make index based values and increment |
| String entityAlias = "GI" + productSearchContext.index; |
| String prefix = "gi" + productSearchContext.index; |
| productSearchContext.index++; |
| |
| |
| EntityComparisonOperator<?,?> operator = EntityOperator.EQUALS; |
| |
| if (UtilValidate.isNotEmpty(include) && include == Boolean.FALSE) { |
| operator = EntityOperator.NOT_EQUAL; |
| } |
| |
| productSearchContext.dynamicViewEntity.addMemberEntity(entityAlias, "GoodIdentification"); |
| |
| if (UtilValidate.isNotEmpty(goodIdentificationTypeId)) { |
| productSearchContext.dynamicViewEntity.addAlias(entityAlias, prefix + "GoodIdentificationTypeId", "goodIdentificationTypeId", null, null, null, null); |
| productSearchContext.entityConditionList.add(EntityCondition.makeCondition(prefix + "GoodIdentificationTypeId", operator, goodIdentificationTypeId)); |
| } |
| |
| if (UtilValidate.isNotEmpty(goodIdentificationValue)) { |
| productSearchContext.dynamicViewEntity.addAlias(entityAlias, prefix + "GoodIdentificationValue", "idValue", null, null, null, null); |
| productSearchContext.entityConditionList.add(EntityCondition.makeCondition(prefix + "GoodIdentificationValue", operator, goodIdentificationValue)); |
| } |
| |
| productSearchContext.dynamicViewEntity.addViewLink("PROD", entityAlias, Boolean.FALSE, ModelKeyMap.makeKeyMapList("productId")); |
| |
| productSearchContext.productSearchConstraintList.add(productSearchContext.getDelegator().makeValue("ProductSearchConstraint", |
| UtilMisc.toMap("constraintName", constraintName, "infoString", "goodIdentificationTypeId [" + this.goodIdentificationTypeId + "] goodIdentificationValue [" + this.goodIdentificationValue + "] include [" + this.include + "]"))); |
| } |
| } |
| |
| @Override |
| public String prettyPrintConstraint(Delegator delegator, boolean detailed, Locale locale) { |
| if (UtilValidate.isEmpty(goodIdentificationTypeId) && |
| UtilValidate.isEmpty(goodIdentificationValue) && |
| UtilValidate.isEmpty(include)) { |
| return null; |
| } |
| |
| StringBuilder msgBuf = new StringBuilder(); |
| |
| if (UtilValidate.isNotEmpty(include) && include == Boolean.FALSE) { |
| msgBuf.append(UtilProperties.getMessage(resourceCommon, "CommonExclude", locale)); |
| msgBuf.append(" "); |
| } else { |
| msgBuf.append(UtilProperties.getMessage(resourceCommon, "CommonInclude", locale)); |
| msgBuf.append(" "); |
| } |
| |
| if (UtilValidate.isNotEmpty(goodIdentificationTypeId)) { |
| msgBuf.append(UtilProperties.getMessage(resource, "ProductIdType", locale)); |
| msgBuf.append(": "); |
| msgBuf.append(goodIdentificationTypeId); |
| msgBuf.append(" "); |
| } |
| |
| if (UtilValidate.isNotEmpty(goodIdentificationValue)) { |
| msgBuf.append(UtilProperties.getMessage(resource, "ProductIdValue", locale)); |
| msgBuf.append(" "); |
| msgBuf.append(goodIdentificationValue); |
| } |
| return msgBuf.toString(); |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| ProductSearchConstraint psc = (ProductSearchConstraint) obj; |
| if (psc instanceof GoodIdentificationConstraint) { |
| return true; |
| } else { |
| return false; |
| } |
| } |
| } |
| |
| @SuppressWarnings("serial") |
| public static class ProductFieldConstraint extends ProductSearchConstraint { |
| public static final String constraintName = "ProductField"; |
| protected String keyword; |
| protected String productFieldName; |
| |
| public ProductFieldConstraint(String keyword, String productFieldName) { |
| this.keyword = keyword; |
| this.productFieldName = productFieldName; |
| } |
| |
| @Override |
| public void addConstraint(ProductSearchContext productSearchContext) { |
| productSearchContext.dynamicViewEntity.addAlias("PROD", productFieldName, null, null, null, null, null); |
| productSearchContext.entityConditionList.add(EntityCondition.makeCondition(productFieldName ,EntityOperator.LIKE, keyword + "%")); |
| productSearchContext.productSearchConstraintList.add(productSearchContext.getDelegator().makeValue("ProductSearchConstraint", UtilMisc.toMap("constraintName", constraintName, "infoString", this.keyword))); |
| } |
| |
| @Override |
| public String prettyPrintConstraint(Delegator delegator, boolean detailed, Locale locale) { |
| return UtilProperties.getMessage(resource, "ProductKeywords", locale); |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| ProductSearchConstraint psc = (ProductSearchConstraint) obj; |
| if (psc instanceof ProductFieldConstraint) { |
| ProductFieldConstraint that = (ProductFieldConstraint) psc; |
| if (this.keyword == null) { |
| if (that.keyword != null) { |
| return false; |
| } |
| } else { |
| if (!this.keyword.equals(that.keyword)) { |
| return false; |
| } |
| } |
| return true; |
| } else { |
| return false; |
| } |
| } |
| } |
| |
| // ====================================================================== |
| // Result Sort Classes |
| // ====================================================================== |
| |
| @SuppressWarnings("serial") |
| public static abstract class ResultSortOrder implements java.io.Serializable { |
| public ResultSortOrder() { |
| } |
| |
| public abstract void setSortOrder(ProductSearchContext productSearchContext); |
| public abstract String getOrderName(); |
| public abstract String prettyPrintSortOrder(boolean detailed, Locale locale); |
| public abstract boolean isAscending(); |
| } |
| |
| @SuppressWarnings("serial") |
| public static class SortKeywordRelevancy extends ResultSortOrder { |
| public SortKeywordRelevancy() { |
| } |
| |
| @Override |
| public void setSortOrder(ProductSearchContext productSearchContext) { |
| if (productSearchContext.includedKeywordSearch) { |
| // we have to check this in order to be sure that there is a totalRelevancy to sort by... |
| if(productSearchContext.keywordFixedOrSetAndList.size() > 0 || productSearchContext.andKeywordFixedSet.size() > 0) { |
| productSearchContext.orderByList.add("-totalRelevancy"); |
| productSearchContext.fieldsToSelect.add("totalRelevancy"); |
| } |
| if (productSearchContext.keywordFixedOrSetAndList.size() > 0) |
| productSearchContext.productIdGroupBy = true; |
| } |
| } |
| |
| @Override |
| public String getOrderName() { |
| return "KeywordRelevancy"; |
| } |
| |
| @Override |
| public String prettyPrintSortOrder(boolean detailed, Locale locale) { |
| return UtilProperties.getMessage(resource, "ProductKeywordRelevancy", locale); |
| } |
| |
| @Override |
| public boolean isAscending() { |
| return false; |
| } |
| } |
| |
| @SuppressWarnings("serial") |
| public static class SortProductField extends ResultSortOrder { |
| protected String fieldName; |
| protected boolean ascending; |
| |
| /** Some good field names to try might include: |
| * [productName] |
| * [totalQuantityOrdered] for most popular or most purchased |
| * [lastModifiedDate] |
| * |
| * You can also include any other field on the Product entity. |
| */ |
| public SortProductField(String fieldName, boolean ascending) { |
| this.fieldName = fieldName; |
| this.ascending = ascending; |
| } |
| |
| @Override |
| public void setSortOrder(ProductSearchContext productSearchContext) { |
| if (productSearchContext.getDelegator().getModelEntity("Product").isField(fieldName)) { |
| productSearchContext.dynamicViewEntity.addAlias("PROD", fieldName); |
| } else if (productSearchContext.getDelegator().getModelEntity("ProductCalculatedInfo").isField(fieldName)) { |
| productSearchContext.dynamicViewEntity.addAlias("PRODCI", fieldName); |
| } |
| if (ascending) { |
| productSearchContext.orderByList.add("+" + fieldName); |
| } else { |
| productSearchContext.orderByList.add("-" + fieldName); |
| } |
| productSearchContext.fieldsToSelect.add(fieldName); |
| } |
| |
| @Override |
| public String getOrderName() { |
| return "ProductField:" + this.fieldName; |
| } |
| |
| @Override |
| public String prettyPrintSortOrder(boolean detailed, Locale locale) { |
| if ("productName".equals(this.fieldName)) { |
| return UtilProperties.getMessage(resource, "ProductProductName", locale); |
| } else if ("totalQuantityOrdered".equals(this.fieldName)) { |
| return UtilProperties.getMessage(resource, "ProductPopularityByOrders", locale); |
| } else if ("totalTimesViewed".equals(this.fieldName)) { |
| return UtilProperties.getMessage(resource, "ProductPopularityByViews", locale); |
| } else if ("averageCustomerRating".equals(this.fieldName)) { |
| return UtilProperties.getMessage(resource, "ProductCustomerRating", locale); |
| } |
| return this.fieldName; |
| } |
| |
| @Override |
| public boolean isAscending() { |
| return this.ascending; |
| } |
| } |
| |
| @SuppressWarnings("serial") |
| public static class SortProductPrice extends ResultSortOrder { |
| protected String productPriceTypeId; |
| protected String currencyUomId; |
| protected String productStoreGroupId; |
| protected boolean ascending; |
| |
| public SortProductPrice(String productPriceTypeId, boolean ascending) { |
| this.productPriceTypeId = productPriceTypeId; |
| this.ascending = ascending; |
| } |
| |
| public SortProductPrice(String productPriceTypeId, String currencyUomId, String productStoreGroupId, boolean ascending) { |
| this.productPriceTypeId = productPriceTypeId; |
| this.currencyUomId = currencyUomId; |
| this.productStoreGroupId = productStoreGroupId; |
| this.ascending = ascending; |
| } |
| |
| @Override |
| public void setSortOrder(ProductSearchContext productSearchContext) { |
| if (this.currencyUomId == null) { |
| this.currencyUomId = UtilProperties.getPropertyValue("general", "currency.uom.id.default", "USD"); |
| } |
| if (this.productStoreGroupId == null) { |
| this.productStoreGroupId = "_NA_"; |
| } |
| |
| // SortProductPrice, this will be a bit more complex, need to add a ProductPrice member entity |
| productSearchContext.dynamicViewEntity.addMemberEntity("SPPRC", "ProductPrice"); |
| productSearchContext.dynamicViewEntity.addViewLink("PROD", "SPPRC", Boolean.TRUE, UtilMisc.toList(new ModelKeyMap("productId", "productId"))); |
| productSearchContext.dynamicViewEntity.addAlias("SPPRC", "sortProductPriceTypeId", "productPriceTypeId", null, null, null, null); |
| productSearchContext.dynamicViewEntity.addAlias("SPPRC", "sortCurrencyUomId", "currencyUomId", null, null, null, null); |
| productSearchContext.dynamicViewEntity.addAlias("SPPRC", "sortProductStoreGroupId", "productStoreGroupId", null, null, null, null); |
| productSearchContext.dynamicViewEntity.addAlias("SPPRC", "sortFromDate", "fromDate", null, null, null, null); |
| productSearchContext.dynamicViewEntity.addAlias("SPPRC", "sortThruDate", "thruDate", null, null, null, null); |
| productSearchContext.dynamicViewEntity.addAlias("SPPRC", "sortPrice", "price", null, null, null, null); |
| |
| productSearchContext.entityConditionList.add(EntityCondition.makeCondition("sortProductPriceTypeId", EntityOperator.EQUALS, this.productPriceTypeId)); |
| productSearchContext.entityConditionList.add(EntityCondition.makeCondition("sortCurrencyUomId", EntityOperator.EQUALS, this.currencyUomId)); |
| productSearchContext.entityConditionList.add(EntityCondition.makeCondition("sortProductStoreGroupId", EntityOperator.EQUALS, this.productStoreGroupId)); |
| productSearchContext.entityConditionList.add(EntityCondition.makeCondition("sortFromDate", EntityOperator.LESS_THAN_EQUAL_TO, productSearchContext.nowTimestamp)); |
| productSearchContext.entityConditionList.add(EntityCondition.makeCondition( |
| EntityCondition.makeCondition("sortThruDate", EntityOperator.EQUALS, null), EntityOperator.OR, |
| EntityCondition.makeCondition("sortThruDate", EntityOperator.GREATER_THAN_EQUAL_TO, productSearchContext.nowTimestamp))); |
| |
| if (ascending) { |
| productSearchContext.orderByList.add("+sortPrice"); |
| } else { |
| productSearchContext.orderByList.add("-sortPrice"); |
| } |
| productSearchContext.fieldsToSelect.add("sortPrice"); |
| } |
| |
| @Override |
| public String getOrderName() { |
| return "ProductPrice:" + productPriceTypeId; |
| } |
| |
| @Override |
| public String prettyPrintSortOrder(boolean detailed, Locale locale) { |
| String priceTypeName = null; |
| if ("LIST_PRICE".equals(this.productPriceTypeId)) { |
| priceTypeName = UtilProperties.getMessage(resource, "ProductListPrice", locale); |
| } else if ("DEFAULT_PRICE".equals(this.productPriceTypeId)) { |
| priceTypeName = UtilProperties.getMessage(resource, "ProductDefaultPrice", locale); |
| } else if ("AVERAGE_COST".equals(this.productPriceTypeId)) { |
| priceTypeName = UtilProperties.getMessage(resource, "ProductAverageCost", locale); |
| } |
| if (priceTypeName == null) { |
| priceTypeName = UtilProperties.getMessage(resource, "ProductPrice", locale) + " ("; |
| if (this.ascending) { |
| priceTypeName += UtilProperties.getMessage(resource, "ProductLowToHigh", locale)+")"; |
| } else { |
| priceTypeName += UtilProperties.getMessage(resource, "ProductHighToLow", locale)+")"; |
| } |
| } |
| |
| return priceTypeName; |
| } |
| |
| @Override |
| public boolean isAscending() { |
| return this.ascending; |
| } |
| } |
| |
| @SuppressWarnings("serial") |
| public static class SortProductFeature extends ResultSortOrder { |
| protected String productFeatureTypeId; |
| protected boolean ascending; |
| |
| public SortProductFeature(String productFeatureTypeId, boolean ascending) { |
| this.productFeatureTypeId = productFeatureTypeId; |
| this.ascending = ascending; |
| } |
| |
| @Override |
| public void setSortOrder(ProductSearchContext productSearchContext) { |
| productSearchContext.dynamicViewEntity.addMemberEntity("PFAPPL", "ProductFeatureAndAppl"); |
| productSearchContext.dynamicViewEntity.addAlias("PFAPPL", "sortProductFeatureTypeId", "productFeatureTypeId", null, null, null, null); |
| productSearchContext.dynamicViewEntity.addAlias("PFAPPL", "sortProductFeatureId", "productFeatureId", null, null, null, null); |
| productSearchContext.dynamicViewEntity.addAlias("PFAPPL", "sortFromDate", "fromDate", null, null, null, null); |
| productSearchContext.dynamicViewEntity.addAlias("PFAPPL", "sortThruDate", "thruDate", null, null, null, null); |
| productSearchContext.dynamicViewEntity.addViewLink("PROD", "PFAPPL", Boolean.TRUE, UtilMisc.toList(new ModelKeyMap("productId", "productId"))); |
| productSearchContext.entityConditionList.add(EntityCondition.makeCondition("sortProductFeatureTypeId", EntityOperator.EQUALS, this.productFeatureTypeId)); |
| productSearchContext.entityConditionList.add(EntityCondition.makeCondition("sortFromDate", EntityOperator.LESS_THAN_EQUAL_TO, productSearchContext.nowTimestamp)); |
| productSearchContext.entityConditionList.add(EntityCondition.makeCondition( |
| EntityCondition.makeCondition("sortThruDate", EntityOperator.EQUALS, null), EntityOperator.OR, |
| EntityCondition.makeCondition("sortThruDate", EntityOperator.GREATER_THAN_EQUAL_TO, productSearchContext.nowTimestamp))); |
| if (ascending) { |
| productSearchContext.orderByList.add("+sortProductFeatureId"); |
| } else { |
| productSearchContext.orderByList.add("-sortProductFeatureId"); |
| } |
| productSearchContext.fieldsToSelect.add("sortProductFeatureId"); |
| } |
| |
| @Override |
| public String getOrderName() { |
| return "ProductFeature:" + this.productFeatureTypeId; |
| } |
| |
| @Override |
| public String prettyPrintSortOrder(boolean detailed, Locale locale) { |
| String featureTypeName = null; |
| if (this.productFeatureTypeId != null) { |
| featureTypeName = this.productFeatureTypeId; |
| } |
| return featureTypeName; |
| } |
| |
| @Override |
| public boolean isAscending() { |
| return this.ascending; |
| } |
| } |
| /** A rather large and verbose method that doesn't use the cool constraint and sort order objects */ |
| /* |
| public static ArrayList parametricKeywordSearchStandAlone(Set featureIdSet, String keywordsString, Delegator delegator, String productCategoryId, boolean includeSubCategories, String visitId, boolean anyPrefix, boolean anySuffix, boolean isAnd) { |
| // TODO: implement this for the new features |
| boolean removeStems = UtilProperties.propertyValueEquals("prodsearch", "remove.stems", "true"); |
| |
| Timestamp nowTimestamp = UtilDateTime.nowTimestamp(); |
| |
| // make view-entity & EntityCondition |
| int index = 1; |
| List entityConditionList = new FastList.newInstance(); |
| List orderByList = new FastList.newInstance(); |
| List fieldsToSelect = UtilMisc.toList("productId"); |
| DynamicViewEntity dynamicViewEntity = new DynamicViewEntity(); |
| dynamicViewEntity.addMemberEntity("PROD", "Product"); |
| dynamicViewEntity.addAlias("PROD", "productName"); |
| boolean productIdGroupBy = false; |
| |
| // Category |
| if (UtilValidate.isNotEmpty(productCategoryId)) { |
| List productCategoryIdList = null; |
| if (includeSubCategories) { |
| // find all sub-categories recursively, make a Set of productCategoryId |
| Set productCategoryIdSet = Fast.newInstance(); |
| getAllSubCategoryIds(productCategoryId, productCategoryIdSet, delegator, nowTimestamp); |
| productCategoryIdList = UtilMisc.makeListWritable(productCategoryIdSet); |
| } else { |
| productCategoryIdList = UtilMisc.toList(productCategoryId); |
| } |
| |
| // make index based values and increment |
| String entityAlias = "PCM" + index; |
| String prefix = "pcm" + index; |
| index++; |
| |
| dynamicViewEntity.addMemberEntity(entityAlias, "ProductCategoryMember"); |
| dynamicViewEntity.addAlias(entityAlias, prefix + "ProductCategoryId", "productCategoryId", null, null, null, null); |
| dynamicViewEntity.addAlias(entityAlias, prefix + "FromDate", "fromDate", null, null, null, null); |
| dynamicViewEntity.addAlias(entityAlias, prefix + "ThruDate", "thruDate", null, null, null, null); |
| dynamicViewEntity.addViewLink("PROD", entityAlias, Boolean.FALSE, ModelKeyMap.makeKeyMapList("productId")); |
| entityConditionList.add(EntityCondition.makeCondition(prefix + "ProductCategoryId", EntityOperator.IN, productCategoryIdList)); |
| entityConditionList.add(EntityCondition.makeCondition(EntityCondition.makeCondition(prefix + "ThruDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition(prefix + "ThruDate", EntityOperator.GREATER_THAN, nowTimestamp))); |
| entityConditionList.add(EntityCondition.makeCondition(prefix + "FromDate", EntityOperator.LESS_THAN, nowTimestamp)); |
| } |
| |
| // Keyword |
| List keywordFirstPass = KeywordSearch.makeKeywordList(keywordsString); |
| List keywordList = KeywordSearch.fixKeywords(keywordFirstPass, anyPrefix, anySuffix, removeStems, isAnd); |
| |
| if (keywordList.size() > 0) { |
| if (isAnd) { |
| // add up the relevancyWeight fields from all keyword member entities for a total to sort by |
| ComplexAlias complexAlias = new ComplexAlias("+"); |
| |
| for (String keyword: keywordList) { |
| // make index based values and increment |
| String entityAlias = "PK" + index; |
| String prefix = "pk" + index; |
| index++; |
| |
| dynamicViewEntity.addMemberEntity(entityAlias, "ProductKeyword"); |
| dynamicViewEntity.addAlias(entityAlias, prefix + "Keyword", "keyword", null, null, null, null); |
| dynamicViewEntity.addViewLink("PROD", entityAlias, Boolean.FALSE, ModelKeyMap.makeKeyMapList("productId")); |
| entityConditionList.add(EntityCondition.makeCondition(prefix + "Keyword", EntityOperator.LIKE, keyword)); |
| |
| //don't add an alias for this, will be part of a complex alias: dynamicViewEntity.addAlias(entityAlias, prefix + "RelevancyWeight", "relevancyWeight", null, null, null, null); |
| complexAlias.addComplexAliasMember(new ComplexAliasField(entityAlias, "relevancyWeight")); |
| } |
| dynamicViewEntity.addAlias(null, "totalRelevancy", null, null, null, null, null, complexAlias); |
| orderByList.add("-totalRelevancy"); |
| fieldsToSelect.add("totalRelevancy"); |
| } else { |
| // make index based values and increment |
| String entityAlias = "PK" + index; |
| String prefix = "pk" + index; |
| index++; |
| |
| dynamicViewEntity.addMemberEntity(entityAlias, "ProductKeyword"); |
| dynamicViewEntity.addAlias(entityAlias, "totalRelevancy", "relevancyWeight", null, null, null, "sum"); |
| dynamicViewEntity.addAlias(entityAlias, prefix + "Keyword", "keyword", null, null, null, null); |
| dynamicViewEntity.addViewLink("PROD", entityAlias, Boolean.FALSE, ModelKeyMap.makeKeyMapList("productId")); |
| orderByList.add("-totalRelevancy"); |
| fieldsToSelect.add("totalRelevancy"); |
| List<EntityCondition> keywordOrList = new FastList.newInstance(); |
| for (String keyword: keywordList) { |
| keywordOrList.add(EntityCondition.makeCondition(prefix + "Keyword", EntityOperator.LIKE, keyword)); |
| } |
| entityConditionList.add(EntityCondition.makeCondition(keywordOrList, EntityOperator.OR)); |
| |
| productIdGroupBy = true; |
| } |
| } |
| |
| // Features |
| if (UtilValidate.isNotEmpty(featureIdSet)) { |
| for (String productFeatureID: featureIdSet) { |
| // make index based values and increment |
| String entityAlias = "PFA" + index; |
| String prefix = "pfa" + index; |
| index++; |
| |
| dynamicViewEntity.addMemberEntity(entityAlias, "ProductFeatureAppl"); |
| dynamicViewEntity.addAlias(entityAlias, prefix + "ProductFeatureId", "productFeatureId", null, null, null, null); |
| dynamicViewEntity.addAlias(entityAlias, prefix + "FromDate", "fromDate", null, null, null, null); |
| dynamicViewEntity.addAlias(entityAlias, prefix + "ThruDate", "thruDate", null, null, null, null); |
| dynamicViewEntity.addViewLink("PROD", entityAlias, Boolean.FALSE, ModelKeyMap.makeKeyMapList("productId")); |
| entityConditionList.add(EntityCondition.makeCondition(prefix + "ProductFeatureId", EntityOperator.EQUALS, productFeatureId)); |
| entityConditionList.add(EntityCondition.makeCondition(EntityCondition.makeCondition(prefix + "ThruDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition(prefix + "ThruDate", EntityOperator.GREATER_THAN, nowTimestamp))); |
| entityConditionList.add(EntityCondition.makeCondition(prefix + "FromDate", EntityOperator.LESS_THAN, nowTimestamp)); |
| } |
| } |
| |
| dynamicViewEntity.addAlias("PROD", "productId", null, null, null, Boolean.valueOf(productIdGroupBy), null); |
| EntityCondition whereCondition = EntityCondition.makeCondition(entityConditionList, EntityOperator.AND); |
| EntityFindOptions efo = new EntityFindOptions(); |
| efo.setDistinct(true); |
| |
| EntityListIterator eli = null; |
| try { |
| eli = delegator.findListIteratorByCondition(dynamicViewEntity, whereCondition, null, fieldsToSelect, orderByList, efo); |
| } catch (GenericEntityException e) { |
| Debug.logError(e, "Error in product search", module); |
| return null; |
| } |
| |
| ArrayList productIds = FastList.newInstance(); |
| Set productIdSet = Fast.newInstance(); |
| GenericValue searchResult = null; |
| while ((searchResult = (GenericValue) eli.next()) != null) { |
| String productId = searchResult.getString("productId"); |
| if (!productIdSet.contains(productId)) { |
| productIds.add(productId); |
| productIdSet.add(productId); |
| } |
| } |
| |
| return productIds; |
| } |
| */ |
| } |