Faceted Navigation combined with Free Text Search and HstQueries 

We assume you have created a faceted navigation node in the repository like we described at Faceted Navigation Configuration. Now, with the help of the HST2, you can very easily access a faceted navigation bean. Assume, the matched sitemap item contains a relativecontentpath pointing to a faceted navigation node.

Faceted Navigation without free text search / HstQueries

In one of your HstComponent's, you can then access this bean for example like:

HippoBean currentBean = this.getContentBean(request);

Now, this currentBean can be the resultset, or some document in the resultset. To make sure you have a faceted navigation bean, use something like:

if(currentBean instanceof HippoDocumentBean && currentBean.getParentBean()
                                           instanceof HippoResultSetBean) {
  // get the current faceted navigation bean
  currentBean = currentBean.getParentBean().getParentBean();
}else if(currentBean instanceof HippoResultSetBean) {
  // get the current faceted navigation bean
  currentBean = currentBean.getParentBean();
}
if(currentBean instanceof HippoFacetNavigation || currentBean
                               instanceof HippoFacetChildNavigationBean) {
   request.setAttribute("facetnav", currentBean);
   if(currentBean instanceof HippoFacetChildNavigationBean) {
      request.setAttribute("childNav", "true");
   }
}

Now, in your jsp, you can really easily print something like:

colors (3466)
   grey (235)
   red (346)
   yellow (1245)
   etc

Also see the testsuite code for examples.

The component that has to show the resultset, can look something like:

HippoBean currentBean = this.getContentBean(request);
if(currentBean instanceof HippoFacetChildNavigationBean) {
            HippoFacetChildNavigationBean facetNav =
                             (HippoFacetChildNavigationBean) currentBean;

  List<ProductBean> resultset = new ArrayList<ProductBean>();
  HippoDocumentIterator<ProductBean> it = facetNav.getResultSet()
                             .getDocumentIterator(ProductBean.class);
  int skip = 0;
  it.skip(skip);
  while(it.hasNext() && it.getPosition() < 10 + (skip - 1)) {
     // the it.getPosition gets increased on it.next() call,
     // hence above, skip - 1
     resultset.add(it.next());
  }
  request.setAttribute("resultset", resultset);
}

Combining free text search / hst queries

Remember

When doing free text search / hst queries for faceted navigation, make sure that every component that wants to use this faceted navigation, injects the exact same free text search / hst query.

Instead of having the above logic, we have added utility methods to org.hippoecm.hst.util.ContentBeanUtils which makes it even easier: in your HstComponent you can use in for example the resultset component something like:

HstQuery query = getHstQuery(request);
HippoFacetNavigationBean facetNav = ContentBeanUtils.getFacetNavigationBean(query);
List<ProductBean> resultset = new ArrayList<ProductBean>();
request.setAttribute("resultset", resultset);
request.setAttribute("facetNavigation", facetNav);
HippoResultSetBean resultSetBean = ((HippoFacetNavigationBean)facetNav)
                                                          .getResultSet();
if(resultSetBean == null) {
   return;
}
HippoDocumentIterator<ProductBean> it =
                      resultSetBean.getDocumentIterator(ProductBean.class);
int skip = 0;
it.skip(skip);
while(it.hasNext() && it.getPosition() < 10 + (skip - 1)) {
    // the it.getPosition gets increased on it.next() call,
    // hence above, skip - 1
    resultset.add(it.next());
}

and in the HstComponent that needs to show the document in context (see navigationStateful URLs at Context Aware, Canonical, Preferred and navigationStateful URLs) of the current faceted navigation.

HstQuery query = getHstQuery(request);
ProductBean product = ContentBeanUtils
                      .getFacetedNavigationResultDocument(
                                 query, 
                                 ProductBean.class);
request.setAttribute("document", product);

Note that the query ( String or HstQuery) object in getFacetedNavigationResultDocument must be the same as the one for which the faceted navigation tree was created: Namely, fetching the document without the query might not result in that very document in the resultset (possibly because it would not be in the limited resultset of say 100 documents max)

In the ContentBeanUtils, we have facilitated the following utility methods. In the methods you can inject a query as String, which is equivalent to a free text search only (or to jcr:contains(.,'query') in xpath) , or a query as a HstQuery.

getFacetNavigationBean(HstQuery q);
getFacetNavigationBean(HstQuery query, String relPath);
getFacetNavigationBean(String query);
getFacetNavigationBean(String query, String relPath);
getFacetedNavigationResultDocument(HstQuery query, Class<T> bean);
getFacetedNavigationResultDocument(HstQuery query, String relPath , Class<T> bean);
getFacetedNavigationResultDocument(String query , Class<T> bean);
getFacetedNavigationResultDocument(String query, String relPath, Class<T> bean);

When creating links for documents in a resultset, you can make use of the navigationStateful attribute, also see Context Aware, Canonical, Preferred and navigationStateful URLs. For example:

JSP

<c:forEach var="result" items="${requestScope.resultset}">
  <hst:link var="link" hippobean="${result}" navigationStateful="true" />
  <a href="${link}">${result.title}</a>
</c:forEach>

Freemarker

<#list resultset as result>
  <@hst.link var="link" hippobean=result navigationStateful="true" />
  <a href="${link}">${result.title}</a>
</#list>