Author: sskracic Date: 2005-12-06 14:18:00 +0100 (Tue, 06 Dec 2005) New Revision: 1033 Modified: trunk/ccm-cms/src/com/arsdigita/cms/search/IntermediaQueryEngine.java trunk/ccm-cms/src/com/arsdigita/cms/search/LuceneQueryEngine.java trunk/ccm-core/src/com/arsdigita/search/filters/CategoryFilterSpecification.java trunk/ccm-core/src/com/arsdigita/search/intermedia/BaseQueryEngine.java trunk/ccm-core/src/com/arsdigita/search/lucene/CategoryFilter.java trunk/ccm-ldn-search/src/com/arsdigita/london/search/ui/AdvancedQueryComponent.java trunk/ccm-ldn-search/src/com/arsdigita/london/search/ui/CategoryHierarchyFilterWidget.java Log: Readding the "descend" option for CategoryFilter. Modified: trunk/ccm-cms/src/com/arsdigita/cms/search/IntermediaQueryEngine.java =================================================================== --- trunk/ccm-cms/src/com/arsdigita/cms/search/IntermediaQueryEngine.java 2005-12-06 10:07:33 UTC (rev 1032) +++ trunk/ccm-cms/src/com/arsdigita/cms/search/IntermediaQueryEngine.java 2005-12-06 13:18:00 UTC (rev 1033) @@ -238,6 +238,7 @@ "com.arsdigita.cms.searchCategoryObjects"); f.set("ids", ids); + f.set("pathLimit", new Integer(filter.isDescending() ? 999999 : 0)); } } Modified: trunk/ccm-cms/src/com/arsdigita/cms/search/LuceneQueryEngine.java =================================================================== --- trunk/ccm-cms/src/com/arsdigita/cms/search/LuceneQueryEngine.java 2005-12-06 10:07:33 UTC (rev 1032) +++ trunk/ccm-cms/src/com/arsdigita/cms/search/LuceneQueryEngine.java 2005-12-06 13:18:00 UTC (rev 1033) @@ -23,6 +23,8 @@ import com.arsdigita.cms.search.ContentTypeFilterSpecification; import com.arsdigita.cms.search.ContentTypeFilterType; import com.arsdigita.kernel.PartyCollection; +import com.arsdigita.persistence.DataQuery; +import com.arsdigita.persistence.SessionManager; import com.arsdigita.search.FilterSpecification; import com.arsdigita.search.FilterType; import com.arsdigita.search.filters.CategoryFilterSpecification; @@ -128,6 +130,17 @@ if (cats == null || cats.length == 0) { return; } - list.add(new CategoryFilter(cats, "com.arsdigita.cms.searchCategoryObjects")); + list.add(new CategoryFilter(cats, filterSpec.isDescending()) { + protected DataQuery getQuery(List catList, boolean descending) { + DataQuery dq = SessionManager.getSession() + .retrieveQuery("com.arsdigita.cms.searchCategoryObjects"); + dq.setParameter("ids", catList); + // 999999 - just need a number that is grater than max. category + // tree depth + dq.setParameter("pathLimit", new Integer(descending ? 999999 : 0)); + return dq; + } + }); + } } Modified: trunk/ccm-core/src/com/arsdigita/search/filters/CategoryFilterSpecification.java =================================================================== --- trunk/ccm-core/src/com/arsdigita/search/filters/CategoryFilterSpecification.java 2005-12-06 10:07:33 UTC (rev 1032) +++ trunk/ccm-core/src/com/arsdigita/search/filters/CategoryFilterSpecification.java 2005-12-06 13:18:00 UTC (rev 1033) @@ -27,23 +27,40 @@ * to the category membership filter type */ public class CategoryFilterSpecification extends FilterSpecification { - + public static final String CATEGORIES = "categories"; + public static final String DESCENDING = "descending"; /** * Creates a new category filter spec * @param cats the categories to check membership of + * @param boolean whether category children trees will be traversed as well */ - public CategoryFilterSpecification(Category[] cats) { - super(new Object[] { CATEGORIES, cats }, + public CategoryFilterSpecification(Category[] cats, boolean descending) { + super(new Object[] { CATEGORIES, cats, DESCENDING, new Boolean(descending) }, new CategoryFilterType()); } - + /** + * Creates a new category filter spec that doesn't check subcategories + * @param cats the categories to check membership of + */ + public CategoryFilterSpecification(Category[] cats) { + this(cats, false); + } + + /** * Returns the list of categories to check * @return the list of categories */ public Category[] getCategories() { return (Category[])get(CATEGORIES); } + + /** + * Checks whether the filter should traverse subcategory tree(s). + */ + public boolean isDescending() { + return Boolean.TRUE.equals(get(DESCENDING)); + } } Modified: trunk/ccm-core/src/com/arsdigita/search/intermedia/BaseQueryEngine.java =================================================================== --- trunk/ccm-core/src/com/arsdigita/search/intermedia/BaseQueryEngine.java 2005-12-06 10:07:33 UTC (rev 1032) +++ trunk/ccm-core/src/com/arsdigita/search/intermedia/BaseQueryEngine.java 2005-12-06 13:18:00 UTC (rev 1033) @@ -59,13 +59,13 @@ /** * This provides the basic intermedia query engine implementation - * which can restrict based on category, object type and + * which can restrict based on category, object type and * permissions * @see com.arsdigita.search.QueryEngine */ public class BaseQueryEngine extends LockableImpl implements QueryEngine { - private static final Logger s_log = + private static final Logger s_log = Logger.getLogger(BaseQueryEngine.class); public static final String OBJECT_ID= "object_id"; @@ -91,7 +91,7 @@ addColumn("c.link_text", LINK_TEXT); addColumn("c.summary", SUMMARY); addColumn("c.language", LANGUAGE); - addColumn("c.content_section", CONTENT_SECTION); + addColumn("c.content_section", CONTENT_SECTION); // XML content is labeled as "1" and raw content is labeled as "2" // in buildQueryString(). Those labels must match the arguments // to the "score()" operator used here. @@ -113,7 +113,7 @@ } String terms = cleanSearchString(spec.getTerms()); - + if (terms == null || "".equals(terms)) { return Search.EMPTY_RESULT_SET; } @@ -121,19 +121,19 @@ DataQuery q = buildQuery(terms, spec.allowPartialMatch()); addFilters(q, spec.getFilters()); - - - + + + return new DataQueryResultSet(q); } - + protected DataQuery buildQuery(String terms, boolean partial) { List props = new ArrayList(); String query = buildQueryString(terms, partial, props); - + if (s_log.isDebugEnabled()) { s_log.debug("Query before adding any filters {\n" + query + "}"); } @@ -141,7 +141,7 @@ Session session = SessionManager.getSession(); SearchDataQuery q = new SearchDataQuery( - session, + session, query, (String[])props.toArray(new String[props.size()])); return q; @@ -151,7 +151,7 @@ boolean partial, List props) { StringBuffer sb = new StringBuffer("select \n"); - + Iterator columns = m_columns.keySet().iterator(); while (columns.hasNext()) { String field = (String)columns.next(); @@ -179,7 +179,7 @@ sb.append("\n"); } } - + sb.append("where\n"); Iterator conditions = m_conditions.iterator(); @@ -193,7 +193,7 @@ return sb.toString(); } - protected void addColumn(String field, + protected void addColumn(String field, String propName) { Assert.unlocked(this); m_columns.put(field, propName); @@ -204,32 +204,32 @@ Assert.unlocked(this); m_tables.put(table, alias); } - + protected void addCondition(String condition) { Assert.unlocked(this); m_conditions.add(condition); } - + protected String cleanSearchString(String terms) { return SimpleSearchSpecification.cleanSearchString(terms, " and "); } - + protected void addFilters(DataQuery query, FilterSpecification[] filters) { Assert.locked(this); for (int i = 0 ; i < filters.length ; i++) { - s_log.debug("adding filter " + filters[i]); + s_log.debug("adding filter " + filters[i]); addFilter(query, filters[i]); } } - + protected void addFilter(DataQuery query, FilterSpecification filter) { Assert.locked(this); FilterType type = filter.getType(); - + if (PermissionFilterType.KEY.equals(type.getKey())) { addPermissionFilter(query, (PermissionFilterSpecification)filter); } else if (ObjectTypeFilterType.KEY.equals(type.getKey())) { @@ -237,11 +237,11 @@ } else if (CategoryFilterType.KEY.equals(type.getKey())) { addCategoryFilter(query, (CategoryFilterSpecification)filter); } else if (ContentSectionFilterType.KEY.equals(type.getKey())) { - s_log.debug("adding the ContentSectionFilterSpecification filter"); - addContentSectionFilter(query, (ContentSectionFilterSpecification)filter); - } + s_log.debug("adding the ContentSectionFilterSpecification filter"); + addContentSectionFilter(query, (ContentSectionFilterSpecification)filter); + } } - + protected void addPermissionFilter(DataQuery query, PermissionFilterSpecification filter) { Assert.locked(this); @@ -290,32 +290,33 @@ "object_id", "id", "com.arsdigita.search.categoryObjects"); - + f.set("ids", ids); + f.set("pathLimit", new Integer( filter.isDescending() ? 100 : 0)); } } protected void addContentSectionFilter(DataQuery query, - ContentSectionFilterSpecification filter) { - Assert.locked(this); + ContentSectionFilterSpecification filter) { + Assert.locked(this); Object[] contentSections = filter.getSections(); - s_log.debug("there are " + contentSections.length + " contentSections"); - if (contentSections != null && contentSections.length > 0) { - List contentSectionsList = Arrays.asList(contentSections); - Iterator i = contentSectionsList.iterator(); - StringBuffer filterSql = new StringBuffer(); - while (i.hasNext()) { - filterSql.append("content_section = '"); - filterSql.append((String)i.next()); - filterSql.append("'"); - if (i.hasNext()) { - filterSql.append(" or "); - } - } - s_log.debug("filterSql is " + filterSql.toString()); - query.addFilter(filterSql.toString()); - } + s_log.debug("there are " + contentSections.length + " contentSections"); + if (contentSections != null && contentSections.length > 0) { + List contentSectionsList = Arrays.asList(contentSections); + Iterator i = contentSectionsList.iterator(); + StringBuffer filterSql = new StringBuffer(); + while (i.hasNext()) { + filterSql.append("content_section = '"); + filterSql.append((String)i.next()); + filterSql.append("'"); + if (i.hasNext()) { + filterSql.append(" or "); + } + } + s_log.debug("filterSql is " + filterSql.toString()); + query.addFilter(filterSql.toString()); + } } - + } Modified: trunk/ccm-core/src/com/arsdigita/search/lucene/CategoryFilter.java =================================================================== --- trunk/ccm-core/src/com/arsdigita/search/lucene/CategoryFilter.java 2005-12-06 10:07:33 UTC (rev 1032) +++ trunk/ccm-core/src/com/arsdigita/search/lucene/CategoryFilter.java 2005-12-06 13:18:00 UTC (rev 1033) @@ -44,43 +44,60 @@ public class CategoryFilter extends Filter { - private String m_query; private List m_cats; + private boolean m_descending; + private static final String SEARCH_CATEGORY_OBJECTS_QUERY = "com.arsdigita.search.categoryObjects"; /** - * Create a new CategoryFilter with the default categorisation membership query + * Create a new CategoryFilter with exact category match. * * @param categories restricts the returned result set to objects * that are members of these categories * **/ public CategoryFilter(Category[] categories) { - this(categories, SEARCH_CATEGORY_OBJECTS_QUERY); + this(categories, false); } /** - * Create a CategoryFilter with a custom categorisation membership query - * passed in ID. The custom query must satisfy these 2 conditions: - * <ol> - * <li> it must accept a collection of BigDecimal category ID's - * as a bind paramater :ids - * <li> the result set must contain a BigDecimal field named "id" - * </ol> + * Create a new CategoryFilter with the optional category subtree(s) traversal + * * @param categories restricts the returned result set to objects * that are members of these categories - * @param query the PDL query name used for categorisation membership check - */ - public CategoryFilter(Category[] categories, String query) { + * @param descending whether the category children subtree(s) should be checked as well + * + **/ + public CategoryFilter(Category[] categories, boolean descending) { m_cats = new ArrayList(); for (int i=0; i<categories.length; i++) { m_cats.add(categories[i].getID()); } - m_query = query; + m_descending = descending; } /** + * Provide a custom categorisation membership query. + * The custom query must return a result set containing + * rows with a BigDecimal field named "id". + * @param catList List of category ID's (BigDecimalS) to + * check membership against + * @param descending whether the result set contains objects + * categorised against any of the catList children + */ + protected DataQuery getQuery(List catList, boolean descending) { + DataQuery dq = SessionManager.getSession() + .retrieveQuery(SEARCH_CATEGORY_OBJECTS_QUERY); + dq.setParameter("ids", catList); + // 999999 - just need a number that is grater than max. category + // tree depth + dq.setParameter("pathLimit", new Integer(descending ? 999999 : 0)); + return dq; + } + + + /** * Returns a BitSet with true for documents which * should be permitted in search results, and false * for those that should not. @@ -88,12 +105,8 @@ final public BitSet bits(IndexReader reader) throws IOException { BooleanQuery bq = new BooleanQuery(); - DataQuery dq = SessionManager.getSession() - .retrieveQuery(m_query); - dq.setParameter("ids", m_cats); - int docCount = 0; + DataQuery dq = getQuery(m_cats, m_descending); while (dq.next()) { - docCount++; bq.add(new TermQuery(new Term(Document.ID, dq.get("id").toString())), false, false); } Modified: trunk/ccm-ldn-search/src/com/arsdigita/london/search/ui/AdvancedQueryComponent.java =================================================================== --- trunk/ccm-ldn-search/src/com/arsdigita/london/search/ui/AdvancedQueryComponent.java 2005-12-06 10:07:33 UTC (rev 1032) +++ trunk/ccm-ldn-search/src/com/arsdigita/london/search/ui/AdvancedQueryComponent.java 2005-12-06 13:18:00 UTC (rev 1033) @@ -57,16 +57,17 @@ add(new PermissionFilterComponent( PrivilegeDescriptor.READ)); + } + + if (Search.getConfig().isIntermediaEnabled() || + Search.getConfig().isLuceneEnabled()) { + Application app = Web.getContext().getApplication(); Category root = Category.getRootForObject(app); // amended chr...@we... 29/11/05 // changed from new SimpleCategoryFilterWidget add(new CategoryHierarchyFilterWidget(root)); - } - if (Search.getConfig().isIntermediaEnabled() || - Search.getConfig().isLuceneEnabled()) { - add(new ContentTypeFilterWidget()); add(new VersionFilterComponent(context)); } Modified: trunk/ccm-ldn-search/src/com/arsdigita/london/search/ui/CategoryHierarchyFilterWidget.java =================================================================== --- trunk/ccm-ldn-search/src/com/arsdigita/london/search/ui/CategoryHierarchyFilterWidget.java 2005-12-06 10:07:33 UTC (rev 1032) +++ trunk/ccm-ldn-search/src/com/arsdigita/london/search/ui/CategoryHierarchyFilterWidget.java 2005-12-06 13:18:00 UTC (rev 1033) @@ -17,7 +17,6 @@ package com.arsdigita.london.search.ui; import java.util.HashSet; -import java.util.Iterator; import java.util.Set; import com.arsdigita.bebop.Form; @@ -27,7 +26,6 @@ import com.arsdigita.bebop.parameters.ParameterData; import com.arsdigita.bebop.parameters.StringParameter; import com.arsdigita.categorization.Category; -import com.arsdigita.categorization.CategoryCollection; import com.arsdigita.domain.DomainObjectFactory; import com.arsdigita.persistence.OID; import com.arsdigita.search.FilterSpecification; @@ -39,18 +37,18 @@ /** * @author chr...@we... * - * Category filter widget that includes an extra parameter that can be used to + * Category filter widget that includes an extra parameter that can be used to * search all the subcategories of the selected categories - * - * - * + * + * + * */ public class CategoryHierarchyFilterWidget extends SimpleCategoryFilterWidget { private Form m_form; private StringParameter includeCategoryHierarchy; /** - * @param root the root category for categories available for selection + * @param root the root category for categories available for selection */ public CategoryHierarchyFilterWidget(Category root) { this(new Category[] { root }); @@ -73,10 +71,10 @@ } /** - * + * * returns a FilterSpecification that includes the selected categories - * and if subcats parameter has a value, then includes all descendent - * categories of the selected categories + * and if subcats parameter has a value, then includes all descendent + * categories of the selected categories */ public FilterSpecification getFilter(PageState state) { OID[] oids = (OID[]) getValue(state); @@ -90,35 +88,20 @@ fd.getParameter(includeCategoryHierarchy.getName()); includeSubCats = data.getValue() != null; } - Set includedCats = new HashSet(); + Set cats = new HashSet(); for (int i = 0; i < oids.length; i++) { - Category cat = (Category) DomainObjectFactory.newInstance(oids[i]); - if (includeSubCats) { - CategoryCollection subtree = cat.getDescendants(); - while (subtree.next()) { - includedCats.add(subtree.getCategory()); - - } - } else { - includedCats.add(cat); - } + cats.add( (Category) DomainObjectFactory.newInstance(oids[i])); } - Category[] cats = new Category[includedCats.size()]; - Iterator it = includedCats.iterator(); - int i = 0; - while (it.hasNext()) { - cats[i++] = (Category) it.next(); - } - - return new CategoryFilterSpecification(cats); + Category[] catArray = (Category []) cats.toArray(new Category[0]); + return new CategoryFilterSpecification(catArray, includeSubCats); } /** - * + * * adds xml for the extra parameter to the <search:filter param="category" type="category"> element. * The xml for the parameter is <search:includeSubCats name="subcats" value="true" /> which can be - * transformed into a checkbox or a hidden input + * transformed into a checkbox or a hidden input */ public void generateBodyXML(PageState state, Element parent) { super.generateBodyXML(state, parent); |