package org.onehippo.forge.weblogdemo.components.overview;
import org.apache.commons.lang.StringUtils;
import org.hippoecm.hst.content.beans.query.HstQuery;
import org.hippoecm.hst.content.beans.query.HstQueryResult;
import org.hippoecm.hst.content.beans.query.exceptions.QueryException;
import org.hippoecm.hst.content.beans.standard.HippoBean;
import org.hippoecm.hst.content.beans.standard.HippoBeanIterator;
import org.hippoecm.hst.content.beans.standard.HippoFolderBean;
import org.hippoecm.hst.core.component.HstComponentException;
import org.hippoecm.hst.core.component.HstRequest;
import org.hippoecm.hst.core.component.HstResponse;
import org.onehippo.forge.weblogdemo.beans.BaseDocument;
import org.onehippo.forge.weblogdemo.beans.BeanConstants;
import org.onehippo.forge.weblogdemo.components.BaseSiteComponent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
/**
* Abstract component for an overview of documents in a folder.
* Queries a folder and puts a paged resultset on the request.
* Implementing classes should define which document type is used as filter.
*
* @author Jasha Joachimsthal
*/
public abstract class AbstractListing extends BaseSiteComponent {
public static final int PAGESIZE = 10;
public static final Logger log = LoggerFactory.getLogger(AbstractListing.class);
@Override
public void doBeforeRender(HstRequest request, HstResponse response) throws HstComponentException {
super.doBeforeRender(request, response);
setPageTitle(request);
HippoBean contentBean = getContentBean(request);
if (!(contentBean instanceof HippoFolderBean)) {
log.warn("Parameter hst:relativecontentpath does not reference a folder");
response.setStatus(HstResponse.SC_NOT_FOUND);
return;
// TODO: redirect to 404?
}
int page = getPageNumber(request);
request.setAttribute("page", page);
request.setAttribute("documents", getDocumentsForOverview(request, page));
}
/**
* Gets a {@link List} of {@link org.hippoecm.hst.content.beans.standard.HippoBean} documents.
* Can call {@link #getDocumentList(org.hippoecm.hst.core.component.HstRequest, int, Class)} with the specific class to get a List of
* documents with a specific class under a folder.
*
* @param request current {@link org.hippoecm.hst.core.component.HstRequest}
* @param page page number within the listing
* @return {@link java.util.List} of {@link org.hippoecm.hst.content.beans.standard.HippoBean} documents
*/
protected abstract List<HippoBean> getDocumentsForOverview(HstRequest request, int page);
protected void setPageTitle(HstRequest request) {
String pageTitle = getParameter("pageTitle", request) == null ? "" : getParameter("pageTitle", request);
request.setAttribute("pageTitle", pageTitle);
}
/**
* Gets the current page number for the listing as int with offset 0.
*
* @param request current {@link org.hippoecm.hst.core.component.HstRequest}
* @return int current page number withing a list, offset 0
*/
private int getPageNumber(HstRequest request) {
String pageStr = request.getParameter("page");
int page = 0;
if (StringUtils.isNotBlank(pageStr)) {
try {
page = Integer.parseInt(pageStr);
} catch (NumberFormatException e) {
log.debug("Value '{}' cannot be converted to an Integer", pageStr);
}
}
return page;
}
private HippoBeanIterator getQueryResultAsIterator(HippoBean contentBean, Class<? extends BaseDocument> beanClass) {
try {
HstQuery hstQuery = getQueryManager().createQuery(contentBean, beanClass);
hstQuery.addOrderByDescending(BeanConstants.PROP_DATE);
HstQueryResult queryResult = hstQuery.execute();
return queryResult.getHippoBeans();
} catch (QueryException e) {
log.warn("Error in querying blogposts", e);
}
return null;
}
/**
* Iterates over query result for the requested "page" and returns a List of documents.
*
* @param request {@link org.hippoecm.hst.core.component.HstRequest}
* @param page current page number
* @param beanClass the Class of documents that is used as query filter
* @return {@link java.util.List} of documents or empty List if no documents are found
*/
protected List<HippoBean> getDocumentList(HstRequest request, int page,
Class<? extends BaseDocument> beanClass) {
List<HippoBean> documents = new ArrayList<HippoBean>();
HippoBeanIterator beans = getQueryResultAsIterator(getContentBean(request), beanClass);
if (beans == null) {
return documents;
}
long beansSize = beans.getSize();
// calculates the total number of pages
long pages = beans.getSize() % PAGESIZE > 0L ? beansSize / PAGESIZE + 1L : beansSize / PAGESIZE;
request.setAttribute("pages", pages);
if (beansSize > page * ((long) PAGESIZE)) {
beans.skip(page * PAGESIZE);
}
int results = 0;
while (beans.hasNext() && results < PAGESIZE) {
HippoBean bean = beans.next();
if (bean != null) { // document may have been deleted after searching
documents.add(bean);
results++;
}
}
return documents;
}
}