You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by ha...@apache.org on 2011/05/13 05:20:59 UTC
svn commit: r1102554 [1/2] - in /ofbiz/trunk/applications/content:
entitydef/ script/org/ofbiz/content/content/ servicedef/
src/org/ofbiz/content/content/
Author: hansbak
Date: Fri May 13 03:20:58 2011
New Revision: 1102554
URL: http://svn.apache.org/viewvc?rev=1102554&view=rev
Log:
add a keyword search function to the content component
Added:
ofbiz/trunk/applications/content/src/org/ofbiz/content/content/ContentKeywordIndex.java (with props)
ofbiz/trunk/applications/content/src/org/ofbiz/content/content/ContentSearch.java (with props)
ofbiz/trunk/applications/content/src/org/ofbiz/content/content/ContentSearchEvents.java (with props)
ofbiz/trunk/applications/content/src/org/ofbiz/content/content/ContentSearchSession.java (with props)
Modified:
ofbiz/trunk/applications/content/entitydef/eecas.xml
ofbiz/trunk/applications/content/entitydef/entitymodel.xml
ofbiz/trunk/applications/content/script/org/ofbiz/content/content/ContentServices.xml
ofbiz/trunk/applications/content/servicedef/services.xml
Modified: ofbiz/trunk/applications/content/entitydef/eecas.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/content/entitydef/eecas.xml?rev=1102554&r1=1102553&r2=1102554&view=diff
==============================================================================
--- ofbiz/trunk/applications/content/entitydef/eecas.xml (original)
+++ ofbiz/trunk/applications/content/entitydef/eecas.xml Fri May 13 03:20:58 2011
@@ -26,4 +26,36 @@ under the License.
<action service="clearAssociatedRenderCache" mode="sync" />
</eca>
+ <!-- Content Keyword Indexing ECAs -->
+ <eca entity="Content" operation="create" event="return">
+ <action service="indexContentKeywords" mode="sync" value-attr="contentInstance"/>
+ </eca>
+ <eca entity="Content" operation="store" event="return">
+ <action service="indexContentKeywords" mode="sync"/>
+ </eca>
+ <eca entity="ContentAttribute" operation="create-store" event="return">
+ <action service="indexContentKeywords" mode="sync"/>
+ </eca>
+ <eca entity="ContentMetaData" operation="create-store" event="return">
+ <action service="indexContentKeywords" mode="sync"/>
+ </eca>
+ <eca entity="ContentRole" operation="create-store" event="return">
+ <action service="indexContentKeywords" mode="sync"/>
+ </eca>
+ <eca entity="ProductContent" operation="create-store" event="return">
+ <action service="indexContentKeywords" mode="sync"/>
+ </eca>
+ <eca entity="ProductCategoryContent" operation="create-store" event="return">
+ <action service="indexContentKeywords" mode="sync"/>
+ </eca>
+ <eca entity="PartyContent" operation="create-store" event="return">
+ <action service="indexContentKeywords" mode="sync"/>
+ </eca>
+ <eca entity="WebSiteContent " operation="create-store" event="return">
+ <action service="indexContentKeywords" mode="sync"/>
+ </eca>
+ <eca entity="WorkEffortContent " operation="create-store" event="return">
+ <action service="indexContentKeywords" mode="sync"/>
+ </eca>
+
</entity-eca>
Modified: ofbiz/trunk/applications/content/entitydef/entitymodel.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/content/entitydef/entitymodel.xml?rev=1102554&r1=1102553&r2=1102554&view=diff
==============================================================================
--- ofbiz/trunk/applications/content/entitydef/entitymodel.xml (original)
+++ ofbiz/trunk/applications/content/entitydef/entitymodel.xml Fri May 13 03:20:58 2011
@@ -1644,4 +1644,52 @@ under the License.
<key-map field-name="helpContentId" rel-field-name="contentId"/>
</relation>
</extend-entity>
+
+ <entity entity-name="ContentKeyword" package-name="org.ofbiz.content.content" title="Content Keyword Entity" never-cache="true">
+ <field name="contentId" type="id-ne"></field>
+ <field name="keyword" type="short-varchar"></field>
+ <field name="relevancyWeight" type="numeric"></field>
+ <prim-key field="contentId"/>
+ <prim-key field="keyword"/>
+ <relation type="one" fk-name="CNT_KWD_CNT" rel-entity-name="Content">
+ <key-map field-name="contentId"/>
+ </relation>
+ <index name="CNT_KWD_KWD">
+ <index-field name="keyword"/>
+ </index>
+ </entity>
+ <entity entity-name="ContentSearchConstraint" package-name="org.ofbiz.content.content" never-cache="true" title="Content Search Result Constraint Entity">
+ <field name="contentSearchResultId" type="id-ne"></field>
+ <field name="constraintSeqId" type="id-ne"></field>
+ <field name="constraintName" type="long-varchar"></field>
+ <field name="infoString" type="long-varchar"></field>
+ <field name="includeSubCategories" type="indicator"></field>
+ <field name="isAnd" type="indicator"></field>
+ <field name="anyPrefix" type="indicator"></field>
+ <field name="anySuffix" type="indicator"></field>
+ <field name="removeStems" type="indicator"></field>
+ <field name="lowValue" type="short-varchar"></field>
+ <field name="highValue" type="short-varchar"></field>
+ <prim-key field="contentSearchResultId"/>
+ <prim-key field="constraintSeqId"/>
+ <relation type="one" fk-name="CNT_SCHRSI_RES" rel-entity-name="ContentSearchResult">
+ <key-map field-name="contentSearchResultId"/>
+ </relation>
+ </entity>
+ <entity entity-name="ContentSearchResult"
+ package-name="org.ofbiz.content.content"
+ never-cache="true"
+ title="Content Search Result Entity">
+ <field name="contentSearchResultId" type="id-ne"></field>
+ <field name="visitId" type="id"></field>
+ <field name="orderByName" type="long-varchar"></field>
+ <field name="isAscending" type="indicator"></field>
+ <field name="numResults" type="numeric"></field>
+ <field name="secondsTotal" type="floating-point"></field>
+ <field name="searchDate" type="date-time"></field>
+ <prim-key field="contentSearchResultId"/>
+ <relation type="one" fk-name="CNT_SCHRES_VST" rel-entity-name="Visit">
+ <key-map field-name="visitId"/>
+ </relation>
+ </entity>
</entitymodel>
Modified: ofbiz/trunk/applications/content/script/org/ofbiz/content/content/ContentServices.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/content/script/org/ofbiz/content/content/ContentServices.xml?rev=1102554&r1=1102553&r2=1102554&view=diff
==============================================================================
--- ofbiz/trunk/applications/content/script/org/ofbiz/content/content/ContentServices.xml (original)
+++ ofbiz/trunk/applications/content/script/org/ofbiz/content/content/ContentServices.xml Fri May 13 03:20:58 2011
@@ -1229,4 +1229,52 @@
<field-to-result field="subContentList" result-name="subContentList"/>
<field-to-result field="contentViewList" result-name="subSubContentList"/>
</simple-method>
+
+ <!-- Content Keyword Services -->
+ <simple-method method-name="createContentKeyword" short-description="create a ContentKeyword">
+ <make-value entity-name="ContentKeyword" value-field="newEntity"/>
+ <set-pk-fields map="parameters" value-field="newEntity"/>
+ <set-nonpk-fields map="parameters" value-field="newEntity"/>
+ <create-value value-field="newEntity"/>
+ </simple-method>
+
+ <simple-method method-name="updateContentKeyword" short-description="update a ContentKeyword">
+ <entity-one entity-name="ContentKeyword" value-field="lookedUpValue"/>
+ <set-nonpk-fields map="parameters" value-field="lookedUpValue"/>
+ <store-value value-field="lookedUpValue"/>
+ </simple-method>
+
+ <simple-method method-name="deleteContentKeyword" short-description="delete a ContentKeyword">
+ <entity-one entity-name="ContentKeyword" value-field="lookedUpValue"/>
+ <remove-value value-field="lookedUpValue"/>
+ </simple-method>
+
+ <simple-method method-name="forceIndexContentKeywords" short-description="induce all the keywords of a content">
+ <entity-one entity-name="Content" value-field="content"/>
+ <call-class-method class-name="org.ofbiz.content.content.ContentKeywordIndex" method-name="forceIndexKeywords">
+ <field field="content" type="org.ofbiz.entity.GenericValue"/>
+ </call-class-method>
+ </simple-method>
+
+ <simple-method method-name="deleteContentKeywords" short-description="delete all the keywords of a content">
+ <entity-one entity-name="Content" value-field="content"/>
+ <remove-related value-field="content" relation-name="ContentKeyword"/>
+ </simple-method>
+
+ <simple-method method-name="indexContentKeywords" short-description="Index the Keywords for a Content" login-required="false">
+ <!-- this service is meant to be called from an entity ECA for entities that include a contentId -->
+ <!-- if it is the Content entity itself triggering this action, then a [contentInstance] parameter
+ will be passed and we can save a few cycles looking that up -->
+ <set from-field="parameters.contentInstance" field="contentInstance"/>
+ <if-empty field="contentInstance">
+ <set from-field="parameters.contentId" field="findContentMap.contentId"/>
+ <find-by-primary-key entity-name="Content" map="findContentMap" value-field="contentInstance"/>
+ </if-empty>
+
+ <!-- induce keywords-->
+ <call-class-method class-name="org.ofbiz.content.content.ContentKeywordIndex" method-name="indexKeywords">
+ <field field="contentInstance" type="org.ofbiz.entity.GenericValue"/>
+ </call-class-method>
+ </simple-method>
+
</simple-methods>
Modified: ofbiz/trunk/applications/content/servicedef/services.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/content/servicedef/services.xml?rev=1102554&r1=1102553&r2=1102554&view=diff
==============================================================================
--- ofbiz/trunk/applications/content/servicedef/services.xml (original)
+++ ofbiz/trunk/applications/content/servicedef/services.xml Fri May 13 03:20:58 2011
@@ -1152,4 +1152,49 @@
<implements service="permissionInterface"/>
<attribute name="dataResourceId" type="String" mode="IN" optional="true"/>
</service>
+
+ <!-- Content Keyword Services -->
+ <service name="createContentKeyword" default-entity-name="ContentKeyword" engine="simple"
+ location="component://content/script/org/ofbiz/content/content/ContentServices.xml" invoke="createContentKeyword" auth="true">
+ <description>Create a ContentKeyword</description>
+ <permission-service service-name="contentGenericPermission" main-action="CREATE"/>
+ <auto-attributes include="pk" mode="IN" optional="false"/>
+ <auto-attributes include="nonpk" mode="IN" optional="true"/>
+ </service>
+
+ <service name="updateContentKeyword" default-entity-name="ContentKeyword" engine="simple"
+ location="component://content/script/org/ofbiz/content/content/ContentServices.xml" invoke="updateContentKeyword" auth="true">
+ <description>Update a ContentKeyword</description>
+ <permission-service service-name="contentGenericPermission" main-action="UPDATE"/>
+ <auto-attributes include="pk" mode="IN" optional="false"/>
+ <auto-attributes include="nonpk" mode="IN" optional="true"/>
+ </service>
+
+ <service name="deleteContentKeyword" default-entity-name="ContentKeyword" engine="simple"
+ location="component://content/script/org/ofbiz/content/content/ContentServices.xml" invoke="deleteContentKeyword" auth="true">
+ <description>Delete a ContentKeyword</description>
+ <permission-service service-name="contentGenericPermission" main-action="DELETE"/>
+ <auto-attributes include="pk" mode="IN" optional="false"/>
+ </service>
+
+ <service name="deleteContentKeywords" engine="simple"
+ location="component://content/script/org/ofbiz/content/content/ContentServices.xml" invoke="deleteContentKeywords" auth="true">
+ <description>Delete all the keywords of a content</description>
+ <permission-service service-name="contentGenericPermission" main-action="DELETE"/>
+ <attribute name="contentId" type="String" mode="IN" optional="false"/>
+ </service>
+
+ <service name="indexContentKeywords" engine="simple"
+ location="component://content/script/org/ofbiz/content/content/ContentServices.xml" invoke="indexContentKeywords" auth="false">
+ <description>Index the Keywords for a Content</description>
+ <attribute name="contentId" type="String" mode="IN" optional="false"/>
+ <attribute name="contentInstance" type="org.ofbiz.entity.GenericValue" mode="IN" optional="true"/>
+ </service>
+
+ <service name="forceIndexContentKeywords" engine="simple"
+ location="component://content/script/org/ofbiz/content/content/ContentServices.xml" invoke="forceIndexContentKeywords" auth="true">
+ <description>Induce all the keywords of a content, ignoring the flag in the Content.</description>
+ <permission-service service-name="contentGenericPermission" main-action="CREATE"/>
+ <attribute name="contentId" type="String" mode="IN" optional="false"/>
+ </service>
</services>
Added: ofbiz/trunk/applications/content/src/org/ofbiz/content/content/ContentKeywordIndex.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/content/src/org/ofbiz/content/content/ContentKeywordIndex.java?rev=1102554&view=auto
==============================================================================
--- ofbiz/trunk/applications/content/src/org/ofbiz/content/content/ContentKeywordIndex.java (added)
+++ ofbiz/trunk/applications/content/src/org/ofbiz/content/content/ContentKeywordIndex.java Fri May 13 03:20:58 2011
@@ -0,0 +1,243 @@
+/*******************************************************************************
+ * 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.content.content;
+
+import java.io.IOException;
+import java.sql.Timestamp;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+import javolution.util.FastList;
+
+import org.ofbiz.base.util.Debug;
+import org.ofbiz.base.util.GeneralException;
+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.content.data.DataResourceWorker;
+import org.ofbiz.entity.Delegator;
+import org.ofbiz.entity.GenericEntityException;
+import org.ofbiz.entity.GenericValue;
+import org.ofbiz.entity.util.EntityUtil;
+
+/**
+ * Does indexing in preparation for a keyword search.
+ */
+public class ContentKeywordIndex {
+
+ public static final String module = ContentKeywordIndex.class.getName();
+
+ public static void forceIndexKeywords(GenericValue content) throws GenericEntityException {
+ ContentKeywordIndex.indexKeywords(content, true);
+ }
+
+ public static void indexKeywords(GenericValue content) throws GenericEntityException {
+ ContentKeywordIndex.indexKeywords(content, false);
+ }
+
+ public static void indexKeywords(GenericValue content, boolean doAll) throws GenericEntityException {
+ if (content == null) return;
+ Timestamp nowTimestamp = UtilDateTime.nowTimestamp();
+
+ Delegator delegator = content.getDelegator();
+ if (delegator == null) return;
+ String contentId = content.getString("contentId");
+
+ // get these in advance just once since they will be used many times for the multiple strings to index
+ String separators = KeywordSearchUtil.getSeparators();
+ String stopWordBagOr = KeywordSearchUtil.getStopWordBagOr();
+ String stopWordBagAnd = KeywordSearchUtil.getStopWordBagAnd();
+ boolean removeStems = KeywordSearchUtil.getRemoveStems();
+ Set<String> stemSet = KeywordSearchUtil.getStemSet();
+
+ Map<String, Long> keywords = new TreeMap<String, Long>();
+ List<String> strings = FastList.newInstance();
+
+ int pidWeight = 1;
+ keywords.put(content.getString("contentId").toLowerCase(), Long.valueOf(pidWeight));
+
+ addWeightedKeywordSourceString(content, "dataResourceId", strings);
+ addWeightedKeywordSourceString(content, "contentName", strings);
+ addWeightedKeywordSourceString(content, "description", strings);
+
+ // ContentAttribute
+ List<GenericValue> contentAttributes = delegator.findByAnd("ContentAttribute", UtilMisc.toMap("contentId", contentId));
+ for (GenericValue contentAttribute: contentAttributes) {
+ addWeightedKeywordSourceString(contentAttribute, "attrName", strings);
+ addWeightedKeywordSourceString(contentAttribute, "attrValue", strings);
+ }
+
+ // ContentMetaData
+ List<GenericValue> contentMetaDatas = delegator.findByAnd("ContentMetaData", UtilMisc.toMap("contentId", contentId));
+ for (GenericValue contentMetaData: contentMetaDatas) {
+ addWeightedKeywordSourceString(contentMetaData, "metaDataValue", strings);
+ }
+
+ // ContentRole
+ List<GenericValue> contentRoles = delegator.findByAnd("ContentRole", UtilMisc.toMap("contentId", contentId));
+ for (GenericValue contentRole: contentRoles) {
+ GenericValue party = delegator.findByPrimaryKey("PartyNameView", UtilMisc.toMap("partyId", contentRole.getString("partyId")));
+ if (party != null) {
+ addWeightedKeywordSourceString(party, "description", strings);
+ addWeightedKeywordSourceString(party, "firstName", strings);
+ addWeightedKeywordSourceString(party, "middleName", strings);
+ addWeightedKeywordSourceString(party, "lastName", strings);
+ addWeightedKeywordSourceString(party, "groupName", strings);
+ }
+ }
+
+ // DataResourceRole
+ List<GenericValue> dataResourceRoles = delegator.findByAnd("DataResourceRole", UtilMisc.toMap("dataResourceId", content.getString("dataResourceId")));
+ for (GenericValue dataResourceRole: dataResourceRoles) {
+ GenericValue party = delegator.findByPrimaryKey("PartyNameView", UtilMisc.toMap("partyId", dataResourceRole.getString("partyId")));
+ if (party != null) {
+ addWeightedKeywordSourceString(party, "description", strings);
+ addWeightedKeywordSourceString(party, "firstName", strings);
+ addWeightedKeywordSourceString(party, "middleName", strings);
+ addWeightedKeywordSourceString(party, "lastName", strings);
+ addWeightedKeywordSourceString(party, "groupName", strings);
+ }
+ }
+
+ // Product
+ List<GenericValue> productContentList = delegator.findByAnd("ProductContent", UtilMisc.toMap("contentId", contentId));
+ for (GenericValue productContent: productContentList) {
+ GenericValue product = delegator.findByPrimaryKey("Product", UtilMisc.toMap("productId", productContent.getString("productId")));
+ if (product != null) {
+ addWeightedKeywordSourceString(product, "productName", strings);
+ addWeightedKeywordSourceString(product, "internalName", strings);
+ addWeightedKeywordSourceString(product, "brandName", strings);
+ addWeightedKeywordSourceString(product, "description", strings);
+ addWeightedKeywordSourceString(product, "longDescription", strings);
+ }
+ }
+
+ // ProductCategory
+ List<GenericValue> productCategoryContentList = delegator.findByAnd("ProductCategoryContent", UtilMisc.toMap("contentId", contentId));
+ for (GenericValue productCategoryContent: productCategoryContentList) {
+ GenericValue productCategory = delegator.findByPrimaryKey("ProductCategory", UtilMisc.toMap("productCategoryId", productCategoryContent.getString("productCategoryId")));
+ if (productCategory != null) {
+ addWeightedKeywordSourceString(productCategory, "categoryName", strings);
+ addWeightedKeywordSourceString(productCategory, "description", strings);
+ addWeightedKeywordSourceString(productCategory, "longDescription", strings);
+ }
+ }
+
+ // PartyContent
+ List<GenericValue> partyContents = delegator.findByAnd("PartyContent", UtilMisc.toMap("contentId", contentId));
+ for (GenericValue partyContent: partyContents) {
+ GenericValue party = delegator.findByPrimaryKey("PartyNameView", UtilMisc.toMap("partyId", partyContent.getString("partyId")));
+ if (party != null) {
+ addWeightedKeywordSourceString(party, "description", strings);
+ addWeightedKeywordSourceString(party, "firstName", strings);
+ addWeightedKeywordSourceString(party, "middleName", strings);
+ addWeightedKeywordSourceString(party, "lastName", strings);
+ addWeightedKeywordSourceString(party, "groupName", strings);
+ }
+ }
+
+ // WebSiteContent
+ List<GenericValue> webSiteContents = delegator.findByAnd("WebSiteContent", UtilMisc.toMap("contentId", contentId));
+ for (GenericValue webSiteContent: webSiteContents) {
+ GenericValue webSite = delegator.findByPrimaryKey("WebSite", UtilMisc.toMap("webSiteId", webSiteContent.getString("webSiteId")));
+ if (webSite != null) {
+ addWeightedKeywordSourceString(webSite, "siteName", strings);
+ addWeightedKeywordSourceString(webSite, "httpHost", strings);
+ addWeightedKeywordSourceString(webSite, "httpsHost", strings);
+ }
+ }
+
+ // WorkEffortContent
+ List<GenericValue> workEffortContents = delegator.findByAnd("WorkEffortContent", UtilMisc.toMap("contentId", contentId));
+ for (GenericValue workEffortContent: workEffortContents) {
+ GenericValue workEffort = delegator.findByPrimaryKey("WorkEffort", UtilMisc.toMap("workEffortId", workEffortContent.getString("workEffortId")));
+ if (workEffort != null) {
+ addWeightedKeywordSourceString(workEffort, "workEffortName", strings);
+ }
+ }
+
+ // DataResource
+ GenericValue dataResource = delegator.findByPrimaryKey("DataResource", UtilMisc.toMap("dataResourceId", content.getString("dataResourceId")));
+ if (dataResource != null) {
+ addWeightedKeywordSourceString(dataResource, "dataResourceName", strings);
+ addWeightedKeywordSourceString(dataResource, "objectInfo", strings);
+ }
+ /*List<GenericValue> contentDataResourceViews = delegator.findByAnd("ContentDataResourceView", UtilMisc.toMap("contentId", contentId), null);
+ for (GenericValue contentDataResourceView: contentDataResourceViews) {
+ int weight = 1;
+ addWeightedDataResourceString(contentDataResourceView, weight, strings, delegator, content);
+
+ List<GenericValue> alternateViews = contentDataResourceView.getRelated("ContentAssocDataResourceViewTo", UtilMisc.toMap("caContentAssocTypeId", "ALTERNATE_LOCALE"), UtilMisc.toList("-caFromDate"));
+ alternateViews = EntityUtil.filterByDate(alternateViews, UtilDateTime.nowTimestamp(), "caFromDate", "caThruDate", true);
+ for (GenericValue thisView: alternateViews) {
+ addWeightedDataResourceString(thisView, weight, strings, delegator, content);
+ }
+ }*/
+
+ if (UtilValidate.isNotEmpty(strings)) {
+ for (String str: strings) {
+ // call process keywords method here
+ KeywordSearchUtil.processKeywordsForIndex(str, keywords, separators, stopWordBagAnd, stopWordBagOr, removeStems, stemSet);
+ }
+ }
+
+ List<GenericValue> toBeStored = FastList.newInstance();
+ for (Map.Entry<String, Long> entry: keywords.entrySet()) {
+ GenericValue contentKeyword = delegator.makeValue("ContentKeyword", UtilMisc.toMap("contentId", content.getString("contentId"), "keyword", entry.getKey(), "relevancyWeight", entry.getValue()));
+ toBeStored.add(contentKeyword);
+ }
+ if (toBeStored.size() > 0) {
+ if (Debug.verboseOn()) Debug.logVerbose("[ContentKeywordIndex.indexKeywords] Storing " + toBeStored.size() + " keywords for contentId " + content.getString("contentId"), module);
+
+ if ("true".equals(UtilProperties.getPropertyValue("contentsearch", "index.delete.on_index", "false"))) {
+ // delete all keywords if the properties file says to
+ delegator.removeByAnd("ContentKeyword", UtilMisc.toMap("contentId", content.getString("contentId")));
+ }
+
+ delegator.storeAll(toBeStored);
+ }
+ }
+
+ public static void addWeightedDataResourceString(GenericValue drView, int weight, List<String> strings, Delegator delegator, GenericValue content) {
+ Map<String, Object> drContext = UtilMisc.<String, Object>toMap("content", content);
+ try {
+ String contentText = DataResourceWorker.renderDataResourceAsText(delegator, drView.getString("dataResourceId"), drContext, null, null, false);
+ for (int i = 0; i < weight; i++) {
+ strings.add(contentText);
+ }
+ } catch (IOException e1) {
+ Debug.logError(e1, "Error getting content text to index", module);
+ } catch (GeneralException e1) {
+ Debug.logError(e1, "Error getting content text to index", module);
+ }
+ }
+
+ public static void addWeightedKeywordSourceString(GenericValue value, String fieldName, List<String> strings) {
+ if (value.getString(fieldName) != null) {
+ int weight = 1;
+ for (int i = 0; i < weight; i++) {
+ strings.add(value.getString(fieldName));
+ }
+ }
+ }
+}
Propchange: ofbiz/trunk/applications/content/src/org/ofbiz/content/content/ContentKeywordIndex.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: ofbiz/trunk/applications/content/src/org/ofbiz/content/content/ContentKeywordIndex.java
------------------------------------------------------------------------------
svn:keywords = "Date Rev Author URL Id"
Propchange: ofbiz/trunk/applications/content/src/org/ofbiz/content/content/ContentKeywordIndex.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: ofbiz/trunk/applications/content/src/org/ofbiz/content/content/ContentSearch.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/content/src/org/ofbiz/content/content/ContentSearch.java?rev=1102554&view=auto
==============================================================================
--- ofbiz/trunk/applications/content/src/org/ofbiz/content/content/ContentSearch.java (added)
+++ ofbiz/trunk/applications/content/src/org/ofbiz/content/content/ContentSearch.java Fri May 13 03:20:58 2011
@@ -0,0 +1,928 @@
+/*******************************************************************************
+ * 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.content.content;
+
+import java.sql.Timestamp;
+import java.util.ArrayList;
+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.EntityConditionList;
+import org.ofbiz.entity.condition.EntityExpr;
+import org.ofbiz.entity.condition.EntityOperator;
+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.EntityUtil;
+
+public class ContentSearch {
+
+ public static final String module = ContentSearch.class.getName();
+ public static final String resource = "ContentUiLabels";
+
+ public static ArrayList<String> searchContents(List<? extends ContentSearchConstraint> contentSearchConstraintList, ResultSortOrder resultSortOrder, Delegator delegator, String visitId) {
+ ContentSearchContext contentSearchContext = new ContentSearchContext(delegator, visitId);
+
+ contentSearchContext.addContentSearchConstraints(contentSearchConstraintList);
+ contentSearchContext.setResultSortOrder(resultSortOrder);
+
+ ArrayList<String> contentIds = contentSearchContext.doSearch();
+ return contentIds;
+ }
+
+ public static void getAllSubContentIds(String contentId, Set<String> contentIdSet, Delegator delegator, Timestamp nowTimestamp) {
+ if (nowTimestamp == null) {
+ nowTimestamp = UtilDateTime.nowTimestamp();
+ }
+
+ // first make sure the current id is in the Set
+ contentIdSet.add(contentId);
+
+ // now find all sub-categories, filtered by effective dates, and call this routine for them
+ try {
+ List<GenericValue> contentAssocList = delegator.findByAndCache("ContentAssoc", UtilMisc.toMap("contentIdFrom", contentId));
+ for (GenericValue contentAssoc: contentAssocList) {
+ String subContentId = contentAssoc.getString("contentIdTo");
+ if (contentIdSet.contains(subContentId)) {
+ // 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(contentAssoc, nowTimestamp)) {
+ getAllSubContentIds(subContentId, contentIdSet, delegator, nowTimestamp);
+ }
+ }
+
+ // Find Content where current contentId = contentParentId; only select minimal fields to keep the size low
+ List<GenericValue> childContentList = delegator.findList("Content", EntityCondition.makeCondition("contentParentId", EntityComparisonOperator.EQUALS, contentId),
+ UtilMisc.toSet("contentId", "contentParentId"), null, null, true);
+ for (GenericValue childContent: childContentList) {
+ String subContentId = childContent.getString("contentId");
+ if (contentIdSet.contains(subContentId)) {
+ // 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
+ getAllSubContentIds(subContentId, contentIdSet, delegator, nowTimestamp);
+ }
+ } catch (GenericEntityException e) {
+ Debug.logError(e, "Error finding sub-categories for content search", module);
+ }
+ }
+
+ public static class ContentSearchContext {
+ public int index = 1;
+ public List<EntityCondition> entityConditionList = FastList.newInstance();
+ public List<String> orderByList = FastList.newInstance();
+ public List<String> fieldsToSelect = UtilMisc.toList("contentId");
+ public DynamicViewEntity dynamicViewEntity = new DynamicViewEntity();
+ public boolean contentIdGroupBy = 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> contentSearchConstraintList = 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 ContentSearchContext(Delegator delegator, String visitId) {
+ this.delegator = delegator;
+ this.visitId = visitId;
+ dynamicViewEntity.addMemberEntity("CNT", "Content");
+ }
+
+ public Delegator getDelegator() {
+ return this.delegator;
+ }
+
+ public void addContentSearchConstraints(List<? extends ContentSearchConstraint> contentSearchConstraintList) {
+ // Go through the constraints and add them in
+ for (ContentSearchConstraint constraint: contentSearchConstraintList) {
+ 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> contentIds = this.makeContentIdList(eli);
+ if (eli != null) {
+ try {
+ eli.close();
+ } catch (GenericEntityException e) {
+ Debug.logError(e, "Error closing ContentSearch 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(contentIds.size()), Double.valueOf(totalSeconds));
+
+ return contentIds;
+ }
+
+ 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, "ContentKeyword");
+ dynamicViewEntity.addAlias(entityAlias, prefix + "Keyword", "keyword", null, null, null, null);
+ dynamicViewEntity.addViewLink("CNT", entityAlias, Boolean.FALSE, ModelKeyMap.makeKeyMapList("contentId"));
+ 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);
+ 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: contentIdGroupBy = 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, "ContentKeyword");
+ dynamicViewEntity.addAlias(entityAlias, prefix + "Keyword", "keyword", null, null, null, null);
+ dynamicViewEntity.addViewLink("CNT", entityAlias, Boolean.FALSE, ModelKeyMap.makeKeyMapList("contentId"));
+ List<EntityExpr> keywordOrList = FastList.newInstance();
+ for (String keyword: keywordFixedOrSet) {
+ keywordOrList.add(EntityCondition.makeCondition(prefix + "Keyword", EntityOperator.LIKE, keyword));
+ }
+ entityConditionList.add(EntityCondition.makeCondition(keywordOrList, EntityOperator.OR));
+
+ contentIdGroupBy = true;
+
+ 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 EntityListIterator doQuery(Delegator delegator) {
+ // handle the now assembled or and and keyword fixed lists
+ this.finishKeywordConstraints();
+
+ if (resultSortOrder != null) {
+ resultSortOrder.setSortOrder(this);
+ }
+ dynamicViewEntity.addAlias("CNT", "contentId", null, null, null, Boolean.valueOf(contentIdGroupBy), null);
+ EntityCondition whereCondition = EntityCondition.makeCondition(entityConditionList, EntityOperator.AND);
+
+ // Debug.logInfo("ContentSearch, whereCondition = " + whereCondition.toString(), module);
+
+ EntityFindOptions efo = new EntityFindOptions();
+ efo.setDistinct(true);
+ efo.setResultSetType(EntityFindOptions.TYPE_SCROLL_INSENSITIVE);
+ if (maxResults != null) {
+ efo.setMaxRows(maxResults);
+ }
+
+ EntityListIterator eli = null;
+ try {
+ eli = delegator.findListIteratorByCondition(dynamicViewEntity, whereCondition, null, fieldsToSelect, orderByList, efo);
+ } catch (GenericEntityException e) {
+ Debug.logError(e, "Error in content search", module);
+ return null;
+ }
+
+ return eli;
+ }
+
+ public ArrayList<String> makeContentIdList(EntityListIterator eli) {
+ ArrayList<String> contentIds = new ArrayList<String>(maxResults == null ? 100 : maxResults.intValue());
+ if (eli == null) {
+ Debug.logWarning("The eli is null, returning zero results", module);
+ return contentIds;
+ }
+
+ 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 contentIds;
+ }
+
+
+ // init numRetreived to one since we have already grabbed the initial one
+ int numRetreived = 1;
+ int duplicatesFound = 0;
+
+ Set<String> contentIdSet = FastSet.newInstance();
+
+ contentIds.add(searchResult.getString("contentId"));
+ contentIdSet.add(searchResult.getString("contentId"));
+
+ while (((searchResult = eli.next()) != null) && (maxResults == null || numRetreived < maxResults.intValue())) {
+ String contentId = searchResult.getString("contentId");
+ if (!contentIdSet.contains(contentId)) {
+ contentIds.add(contentId);
+ contentIdSet.add(contentId);
+ numRetreived++;
+ } else {
+ duplicatesFound++;
+ }
+
+ /*
+ StringBuilder lineMsg = new StringBuilder("Got search result line: ");
+ Iterator<String> fieldsToSelectIter = fieldsToSelect.iterator();
+ while (fieldsToSelectIter.hasNext()) {
+ String fieldName = fieldsToSelectIter.next();
+ 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 content search query", module);
+ }
+ return contentIds;
+ }
+
+ public void saveSearchResultInfo(Long numResults, Double secondsTotal) {
+ // uses entities: ContentSearchResult and ContentSearchConstraint
+
+ try {
+ // make sure this is in a transaction
+ boolean beganTransaction = TransactionUtil.begin();
+
+ try {
+
+ GenericValue contentSearchResult = delegator.makeValue("ContentSearchResult");
+ String contentSearchResultId = delegator.getNextSeqId("ContentSearchResult");
+
+ contentSearchResult.set("contentSearchResultId", contentSearchResultId);
+ contentSearchResult.set("visitId", this.visitId);
+ if (this.resultSortOrder != null) {
+ contentSearchResult.set("orderByName", this.resultSortOrder.getOrderName());
+ contentSearchResult.set("isAscending", this.resultSortOrder.isAscending() ? "Y" : "N");
+ }
+ contentSearchResult.set("numResults", numResults);
+ contentSearchResult.set("secondsTotal", secondsTotal);
+ contentSearchResult.set("searchDate", nowTimestamp);
+ contentSearchResult.create();
+
+ int seqId = 1;
+ for (GenericValue contentSearchConstraint: contentSearchConstraintList) {
+ contentSearchConstraint.set("contentSearchResultId", contentSearchResultId);
+ contentSearchConstraint.set("constraintSeqId", Integer.toString(seqId));
+ contentSearchConstraint.create();
+ seqId++;
+ }
+
+ TransactionUtil.commit(beganTransaction);
+ } catch (GenericEntityException e1) {
+ String errMsg = "Error saving content search result info/stats";
+ Debug.logError(e1, errMsg, module);
+ TransactionUtil.rollback(beganTransaction, errMsg, e1);
+ }
+ } catch (GenericTransactionException e) {
+ Debug.logError(e, "Error saving content search result info/stats", module);
+ }
+ }
+ }
+
+ // ======================================================================
+ // Search Constraint Classes
+ // ======================================================================
+
+ @SuppressWarnings("serial")
+ public static abstract class ContentSearchConstraint implements java.io.Serializable {
+ public ContentSearchConstraint() { }
+
+ public abstract void addConstraint(ContentSearchContext contentSearchContext);
+ /** pretty print for log messages and even UI stuff */
+ public abstract String prettyPrintConstraint(Delegator delegator, boolean detailed, Locale locale);
+ }
+
+
+ @SuppressWarnings("serial")
+ public static class ContentAssocConstraint extends ContentSearchConstraint {
+ public static final String constraintName = "ContentAssoc";
+ protected String contentId;
+ protected String contentAssocTypeId;
+ protected boolean includeSubContents;
+
+ public ContentAssocConstraint(String contentId, String contentAssocTypeId, boolean includeSubContents) {
+ this.contentId = contentId;
+ this.contentAssocTypeId = contentAssocTypeId;
+ this.includeSubContents = includeSubContents;
+ }
+
+ @Override
+ public void addConstraint(ContentSearchContext contentSearchContext) {
+ Set<String> contentIdSet = FastSet.newInstance();
+ if (includeSubContents) {
+ // find all sub-categories recursively, make a Set of contentId
+ ContentSearch.getAllSubContentIds(contentId, contentIdSet, contentSearchContext.getDelegator(), contentSearchContext.nowTimestamp);
+ } else {
+ contentIdSet.add(contentId);
+ }
+
+ // allow assoc from or to the current WE and the contentId on this constraint
+
+ // make index based values and increment
+ String entityAlias;
+ String prefix;
+
+ // do contentId = contentIdFrom, contentIdTo IN contentIdSet
+ entityAlias = "CNT" + contentSearchContext.index;
+ prefix = "cnt" + contentSearchContext.index;
+ contentSearchContext.index++;
+
+ contentSearchContext.dynamicViewEntity.addMemberEntity(entityAlias, "ContentAssoc");
+ contentSearchContext.dynamicViewEntity.addAlias(entityAlias, prefix + "ContentIdFrom", "contentIdFrom", null, null, null, null);
+ contentSearchContext.dynamicViewEntity.addAlias(entityAlias, prefix + "ContentIdTo", "contentIdTo", null, null, null, null);
+ contentSearchContext.dynamicViewEntity.addAlias(entityAlias, prefix + "ContentAssocTypeId", "contentAssocTypeId", null, null, null, null);
+ contentSearchContext.dynamicViewEntity.addAlias(entityAlias, prefix + "FromDate", "fromDate", null, null, null, null);
+ contentSearchContext.dynamicViewEntity.addAlias(entityAlias, prefix + "ThruDate", "thruDate", null, null, null, null);
+ contentSearchContext.dynamicViewEntity.addViewLink("CNT", entityAlias, Boolean.TRUE, ModelKeyMap.makeKeyMapList("contentId","contentIdFrom"));
+
+ List<EntityExpr> assocConditionFromTo = FastList.newInstance();
+ assocConditionFromTo.add(EntityCondition.makeCondition(prefix + "ContentIdTo", EntityOperator.IN, contentIdSet));
+ if (UtilValidate.isNotEmpty(contentAssocTypeId)) {
+ assocConditionFromTo.add(EntityCondition.makeCondition(prefix + "ContentAssocTypeId", EntityOperator.EQUALS, contentAssocTypeId));
+ }
+ assocConditionFromTo.add(EntityCondition.makeCondition(EntityCondition.makeCondition(prefix + "ThruDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition(prefix + "ThruDate", EntityOperator.GREATER_THAN, contentSearchContext.nowTimestamp)));
+ assocConditionFromTo.add(EntityCondition.makeCondition(prefix + "FromDate", EntityOperator.LESS_THAN, contentSearchContext.nowTimestamp));
+
+ // do contentId = contentIdTo, contentIdFrom IN contentIdSet
+ entityAlias = "CNT" + contentSearchContext.index;
+ prefix = "cnt" + contentSearchContext.index;
+ contentSearchContext.index++;
+
+ contentSearchContext.dynamicViewEntity.addMemberEntity(entityAlias, "ContentAssoc");
+ contentSearchContext.dynamicViewEntity.addAlias(entityAlias, prefix + "ContentIdFrom", "contentIdFrom", null, null, null, null);
+ contentSearchContext.dynamicViewEntity.addAlias(entityAlias, prefix + "ContentIdTo", "contentIdTo", null, null, null, null);
+ contentSearchContext.dynamicViewEntity.addAlias(entityAlias, prefix + "ContentAssocTypeId", "contentAssocTypeId", null, null, null, null);
+ contentSearchContext.dynamicViewEntity.addAlias(entityAlias, prefix + "FromDate", "fromDate", null, null, null, null);
+ contentSearchContext.dynamicViewEntity.addAlias(entityAlias, prefix + "ThruDate", "thruDate", null, null, null, null);
+ contentSearchContext.dynamicViewEntity.addViewLink("CNT", entityAlias, Boolean.TRUE, ModelKeyMap.makeKeyMapList("contentId","contentIdTo"));
+
+ List<EntityExpr> assocConditionToFrom = FastList.newInstance();
+ assocConditionToFrom.add(EntityCondition.makeCondition(prefix + "ContentIdFrom", EntityOperator.IN, contentIdSet));
+ if (UtilValidate.isNotEmpty(contentAssocTypeId)) {
+ assocConditionToFrom.add(EntityCondition.makeCondition(prefix + "ContentAssocTypeId", EntityOperator.EQUALS, contentAssocTypeId));
+ }
+ assocConditionToFrom.add(EntityCondition.makeCondition(EntityCondition.makeCondition(prefix + "ThruDate", EntityOperator.EQUALS, null), EntityOperator.OR, EntityCondition.makeCondition(prefix + "ThruDate", EntityOperator.GREATER_THAN, contentSearchContext.nowTimestamp)));
+ assocConditionToFrom.add(EntityCondition.makeCondition(prefix + "FromDate", EntityOperator.LESS_THAN, contentSearchContext.nowTimestamp));
+
+ // now create and add the combined constraint
+ contentSearchContext.entityConditionList.add(EntityCondition.makeCondition(EntityCondition.makeCondition(assocConditionFromTo, EntityOperator.AND), EntityOperator.OR, EntityCondition.makeCondition(assocConditionToFrom, EntityOperator.AND)));
+
+
+ // add in contentSearchConstraint, don't worry about the contentSearchResultId or constraintSeqId, those will be fill in later
+ contentSearchContext.contentSearchConstraintList.add(contentSearchContext.getDelegator().makeValue("ContentSearchConstraint", UtilMisc.toMap("constraintName", constraintName, "infoString", this.contentId + "," + this.contentAssocTypeId, "includeSubContents", this.includeSubContents ? "Y" : "N")));
+ }
+
+
+ /** pretty print for log messages and even UI stuff */
+ @Override
+ public String prettyPrintConstraint(Delegator delegator, boolean detailed, Locale locale) {
+ GenericValue content = null;
+ GenericValue contentAssocType = null;
+ try {
+ content = delegator.findByPrimaryKeyCache("Content", UtilMisc.toMap("contentId", this.contentId));
+ contentAssocType = delegator.findByPrimaryKeyCache("ContentAssocType", UtilMisc.toMap("contentAssocTypeId", this.contentAssocTypeId));
+ } catch (GenericEntityException e) {
+ Debug.logError(e, "Error looking up ContentAssocConstraint pretty print info: " + e.toString(), module);
+ }
+
+ StringBuilder ppBuf = new StringBuilder();
+ ppBuf.append(UtilProperties.getMessage(resource, "ContentAssoc", locale) + ": ");
+ if (content != null) {
+ ppBuf.append(content.getString("contentName"));
+ }
+ if (content == null || detailed) {
+ ppBuf.append(" [");
+ ppBuf.append(contentId);
+ ppBuf.append("]");
+ }
+ if (UtilValidate.isNotEmpty(this.contentAssocTypeId)) {
+ if (contentAssocType != null) {
+ ppBuf.append(contentAssocType.getString("description"));
+ }
+ if (contentAssocType == null || detailed) {
+ ppBuf.append(" [");
+ ppBuf.append(contentAssocTypeId);
+ ppBuf.append("]");
+ }
+ }
+ if (this.includeSubContents) {
+ ppBuf.append(" (").append(UtilProperties.getMessage(resource, "ContentIncludeAllSubContents", locale)).append(")");
+ }
+ return ppBuf.toString();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ ContentSearchConstraint psc = (ContentSearchConstraint) obj;
+ if (psc instanceof ContentAssocConstraint) {
+ ContentAssocConstraint that = (ContentAssocConstraint) psc;
+ if (this.includeSubContents != that.includeSubContents) {
+ return false;
+ }
+ if (this.contentId == null) {
+ if (that.contentId != null) {
+ return false;
+ }
+ } else {
+ if (!this.contentId.equals(that.contentId)) {
+ return false;
+ }
+ }
+ if (this.contentAssocTypeId == null) {
+ if (that.contentAssocTypeId != null) {
+ return false;
+ }
+ } else {
+ if (!this.contentAssocTypeId.equals(that.contentAssocTypeId)) {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ @SuppressWarnings("serial")
+ public static class KeywordConstraint extends ContentSearchConstraint {
+ 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(ContentSearchContext contentSearchContext) {
+ // 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, contentSearchContext.getDelegator());
+ if (!replaceEntered) {
+ expandedSet.add(keyword);
+ }
+ Set<String> fixedSet = KeywordSearchUtil.fixKeywordsForSearch(expandedSet, anyPrefix, anySuffix, removeStems, isAnd);
+ Set<String> fixedKeywordSet = FastSet.newInstance();
+ fixedKeywordSet.addAll(fixedSet);
+ contentSearchContext.keywordFixedOrSetAndList.add(fixedKeywordSet);
+ }
+ } else {
+ // when isAnd is false, just add all of the new entries to the big list
+ Set<String> keywordFirstPass = makeFullKeywordSet(contentSearchContext.getDelegator()); // includes keyword expansion, etc
+ Set<String> keywordSet = KeywordSearchUtil.fixKeywordsForSearch(keywordFirstPass, anyPrefix, anySuffix, removeStems, isAnd);
+ contentSearchContext.orKeywordFixedSet.addAll(keywordSet);
+ }
+
+ // add in contentSearchConstraint, don't worry about the contentSearchResultId 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");
+ contentSearchContext.contentSearchConstraintList.add(contentSearchContext.getDelegator().makeValue("ContentSearchConstraint", 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, "ContentKeywords", locale)).append(": \"");
+ ppBuf.append(this.keywordsString).append("\", ").append(UtilProperties.getMessage(resource, "ContentKeywordWhere", locale)).append(" ");
+ ppBuf.append(isAnd ? UtilProperties.getMessage(resource, "ContentKeywordAllWordsMatch", locale) : UtilProperties.getMessage(resource, "ContentKeywordAnyWordMatches", locale));
+ return ppBuf.toString();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ ContentSearchConstraint psc = (ContentSearchConstraint) 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 ContentSearchConstraint {
+ 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(ContentSearchContext contentSearchContext) {
+ contentSearchContext.dynamicViewEntity.addAlias("CNT", "lastModifiedDate", "lastModifiedDate", null, null, null, null);
+
+ EntityConditionList<EntityExpr> dateConditions = null;
+ EntityExpr dateCondition=null;
+ if (fromDate !=null && thruDate!=null) {
+ dateConditions= EntityCondition.makeCondition(UtilMisc.toList(
+ EntityCondition.makeCondition("lastModifiedDate", EntityOperator.GREATER_THAN_EQUAL_TO, fromDate),
+ EntityCondition.makeCondition("lastModifiedDate", EntityOperator.LESS_THAN_EQUAL_TO, thruDate)), EntityOperator.AND);
+ } if (fromDate !=null) {
+ dateCondition=EntityCondition.makeCondition("lastModifiedDate", EntityOperator.GREATER_THAN_EQUAL_TO, fromDate);
+ } else if (thruDate != null) {
+ dateCondition = EntityCondition.makeCondition("lastModifiedDate", EntityOperator.LESS_THAN_EQUAL_TO, thruDate);
+ }
+ EntityConditionList<? extends EntityCondition> conditions = null;
+ if (fromDate !=null && thruDate!=null) {
+ conditions=EntityCondition.makeCondition(UtilMisc.toList(
+ dateConditions,
+ EntityCondition.makeCondition("lastModifiedDate", EntityOperator.EQUALS, null)),
+ EntityOperator.OR);
+ } else {
+ conditions=EntityCondition.makeCondition(UtilMisc.toList(
+ dateCondition,
+ EntityCondition.makeCondition("lastModifiedDate", EntityOperator.EQUALS, null)),
+ EntityOperator.OR);
+ }
+
+ contentSearchContext.entityConditionList.add(conditions);
+
+ // add in contentSearchConstraint, don't worry about the contentSearchResultId or constraintSeqId, those will be fill in later
+ contentSearchContext.contentSearchConstraintList.add(contentSearchContext.getDelegator().makeValue("ContentSearchConstraint", UtilMisc.toMap("constraintName", constraintName, "infoString","fromDate : " + fromDate + " thruDate : " + thruDate)));
+ }
+
+ /** 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, "ContentLastModified", locale)).append(": \"");
+ ppBuf.append(fromDate).append("-").append(thruDate).append("\", ").append(UtilProperties.getMessage(resource, "ContentLastModified", locale)).append(" ");
+ return ppBuf.toString();
+ }
+
+
+ @Override
+ public boolean equals(Object obj) {
+ ContentSearchConstraint psc = (ContentSearchConstraint) 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;
+ }
+ }
+ }
+
+ // ======================================================================
+ // Result Sort Classes
+ // ======================================================================
+
+ @SuppressWarnings("serial")
+ public static abstract class ResultSortOrder implements java.io.Serializable {
+ public ResultSortOrder() {
+ }
+
+ public abstract void setSortOrder(ContentSearchContext contentSearchContext);
+ 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(ContentSearchContext contentSearchContext) {
+ if (contentSearchContext.includedKeywordSearch) {
+ // we have to check this in order to be sure that there is a totalRelevancy to sort by...
+ contentSearchContext.orderByList.add("-totalRelevancy");
+ contentSearchContext.fieldsToSelect.add("totalRelevancy");
+ }
+ }
+
+ @Override
+ public String getOrderName() {
+ return "KeywordRelevancy";
+ }
+
+ @Override
+ public String prettyPrintSortOrder(boolean detailed, Locale locale) {
+ return UtilProperties.getMessage(resource, "ContentKeywordRelevancy", locale);
+ }
+
+ @Override
+ public boolean isAscending() {
+ return false;
+ }
+ }
+
+ @SuppressWarnings("serial")
+ public static class SortContentField extends ResultSortOrder {
+ protected String fieldName;
+ protected boolean ascending;
+
+ /** Some good field names to try might include:
+ * [contentName]
+ * [totalQuantityOrdered] for most popular or most purchased
+ * [lastModifiedDate]
+ *
+ * You can also include any other field on the Content entity.
+ */
+ public SortContentField(String fieldName, boolean ascending) {
+ this.fieldName = fieldName;
+ this.ascending = ascending;
+ }
+
+ @Override
+ public void setSortOrder(ContentSearchContext contentSearchContext) {
+ if (contentSearchContext.getDelegator().getModelEntity("Content").isField(fieldName)) {
+ contentSearchContext.dynamicViewEntity.addAlias("CNT", fieldName);
+ }
+ if (ascending) {
+ contentSearchContext.orderByList.add("+" + fieldName);
+ } else {
+ contentSearchContext.orderByList.add("-" + fieldName);
+ }
+ contentSearchContext.fieldsToSelect.add(fieldName);
+ }
+
+ @Override
+ public String getOrderName() {
+ return "ContentField:" + this.fieldName;
+ }
+
+ @Override
+ public String prettyPrintSortOrder(boolean detailed, Locale locale) {
+ if ("contentName".equals(this.fieldName)) {
+ return UtilProperties.getMessage(resource, "ContentName", locale);
+ } else if ("totalQuantityOrdered".equals(this.fieldName)) {
+ return UtilProperties.getMessage(resource, "ContentPopularityByOrders", locale);
+ } else if ("totalTimesViewed".equals(this.fieldName)) {
+ return UtilProperties.getMessage(resource, "ContentPopularityByViews", locale);
+ } else if ("averageCustomerRating".equals(this.fieldName)) {
+ return UtilProperties.getMessage(resource, "ContentCustomerRating", locale);
+ }
+ return this.fieldName;
+ }
+
+ @Override
+ public boolean isAscending() {
+ return this.ascending;
+ }
+ }
+}
Propchange: ofbiz/trunk/applications/content/src/org/ofbiz/content/content/ContentSearch.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: ofbiz/trunk/applications/content/src/org/ofbiz/content/content/ContentSearch.java
------------------------------------------------------------------------------
svn:keywords = "Date Rev Author URL Id"
Propchange: ofbiz/trunk/applications/content/src/org/ofbiz/content/content/ContentSearch.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: ofbiz/trunk/applications/content/src/org/ofbiz/content/content/ContentSearchEvents.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/content/src/org/ofbiz/content/content/ContentSearchEvents.java?rev=1102554&view=auto
==============================================================================
--- ofbiz/trunk/applications/content/src/org/ofbiz/content/content/ContentSearchEvents.java (added)
+++ ofbiz/trunk/applications/content/src/org/ofbiz/content/content/ContentSearchEvents.java Fri May 13 03:20:58 2011
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * 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.content.content;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import javolution.util.FastMap;
+
+import org.ofbiz.base.util.UtilValidate;
+import org.ofbiz.entity.Delegator;
+import org.ofbiz.webapp.stats.VisitHandler;
+import org.ofbiz.content.content.ContentSearch.ResultSortOrder;
+import org.ofbiz.content.content.ContentSearch.ContentSearchConstraint;
+import org.ofbiz.content.content.ContentSearch.ContentSearchContext;
+import org.ofbiz.content.content.ContentSearchSession.ContentSearchOptions;
+
+
+public class ContentSearchEvents {
+
+ public static final String module = ContentSearchEvents.class.getName();
+
+ public static Map<String, Object> getContentSearchResult(HttpServletRequest request, Delegator delegator) {
+
+ // ========== Create View Indexes
+ int viewIndex = 0;
+ int viewSize = 20;
+ int highIndex = 0;
+ int lowIndex = 0;
+ int listSize = 0;
+
+ HttpSession session = request.getSession();
+ ContentSearchOptions contentSearchOptions = ContentSearchSession.getContentSearchOptions(session);
+
+ Integer viewIndexInteger = contentSearchOptions.getViewIndex();
+ if (viewIndexInteger != null) viewIndex = viewIndexInteger.intValue();
+ Integer viewSizeInteger = contentSearchOptions.getViewSize();
+ if (viewSizeInteger != null) viewSize = viewSizeInteger.intValue();
+
+ lowIndex = viewIndex * viewSize;
+ highIndex = (viewIndex + 1) * viewSize;
+
+ // setup resultOffset and maxResults, noting that resultOffset is 1 based, not zero based as these numbers
+ Integer resultOffset = Integer.valueOf(lowIndex + 1);
+ Integer maxResults = Integer.valueOf(viewSize);
+
+ // ========== Do the actual search
+ ArrayList<String> contentIds = null;
+ String visitId = VisitHandler.getVisitId(session);
+ List<ContentSearchConstraint> contentSearchConstraintList = ContentSearchOptions.getConstraintList(session);
+ // if no constraints, don't do a search...
+ if (UtilValidate.isNotEmpty(contentSearchConstraintList)) {
+ // if the search options have changed since the last search, put at the beginning of the options history list
+ ContentSearchSession.checkSaveSearchOptionsHistory(session);
+
+ ResultSortOrder resultSortOrder = ContentSearchOptions.getResultSortOrder(request);
+
+ ContentSearchContext contentSearchContext = new ContentSearchContext(delegator, visitId);
+ contentSearchContext.addContentSearchConstraints(contentSearchConstraintList);
+
+ contentSearchContext.setResultSortOrder(resultSortOrder);
+ contentSearchContext.setResultOffset(resultOffset);
+ contentSearchContext.setMaxResults(maxResults);
+
+ contentIds = contentSearchContext.doSearch();
+
+ Integer totalResults = contentSearchContext.getTotalResults();
+ if (totalResults != null) {
+ listSize = totalResults.intValue();
+ }
+ }
+
+ if (listSize < highIndex) {
+ highIndex = listSize;
+ }
+
+ // ========== Setup other display info
+ List<String> searchConstraintStrings = ContentSearchSession.searchGetConstraintStrings(false, session, delegator);
+ String searchSortOrderString = ContentSearchSession.searchGetSortOrderString(false, request);
+
+ // ========== populate the result Map
+ Map<String, Object> result = FastMap.newInstance();
+
+ result.put("contentIds", contentIds);
+ result.put("viewIndex", Integer.valueOf(viewIndex));
+ result.put("viewSize", Integer.valueOf(viewSize));
+ result.put("listSize", Integer.valueOf(listSize));
+ result.put("lowIndex", Integer.valueOf(lowIndex));
+ result.put("highIndex", Integer.valueOf(highIndex));
+ result.put("searchConstraintStrings", searchConstraintStrings);
+ result.put("searchSortOrderString", searchSortOrderString);
+
+ return result;
+ }
+
+
+}
Propchange: ofbiz/trunk/applications/content/src/org/ofbiz/content/content/ContentSearchEvents.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: ofbiz/trunk/applications/content/src/org/ofbiz/content/content/ContentSearchEvents.java
------------------------------------------------------------------------------
svn:keywords = "Date Rev Author URL Id"
Propchange: ofbiz/trunk/applications/content/src/org/ofbiz/content/content/ContentSearchEvents.java
------------------------------------------------------------------------------
svn:mime-type = text/plain