Package ch.entwine.weblounge.taglib.content

Source Code of ch.entwine.weblounge.taglib.content.PageListTag

/*
*  Weblounge: Web Content Management System
*  Copyright (c) 2003 - 2011 The Weblounge Team
*  http://entwinemedia.com/weblounge
*
*  This program is free software; you can redistribute it and/or
*  modify it under the terms of the GNU Lesser General Public License
*  as published by the Free Software Foundation; either version 2
*  of the License, or (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU Lesser General Public License for more details.
*
*  You should have received a copy of the GNU Lesser General Public License
*  along with this program; if not, write to the Free Software Foundation
*  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

package ch.entwine.weblounge.taglib.content;

import static ch.entwine.weblounge.common.content.SearchQuery.Quantifier.All;

import ch.entwine.weblounge.common.content.PageSearchResultItem;
import ch.entwine.weblounge.common.content.Resource;
import ch.entwine.weblounge.common.content.SearchQuery;
import ch.entwine.weblounge.common.content.SearchResult;
import ch.entwine.weblounge.common.content.SearchResultItem;
import ch.entwine.weblounge.common.content.page.Composer;
import ch.entwine.weblounge.common.content.page.Page;
import ch.entwine.weblounge.common.content.page.Pagelet;
import ch.entwine.weblounge.common.impl.content.SearchQueryImpl;
import ch.entwine.weblounge.common.impl.content.page.ComposerImpl;
import ch.entwine.weblounge.common.impl.content.page.PageletImpl;
import ch.entwine.weblounge.common.impl.request.RequestUtils;
import ch.entwine.weblounge.common.repository.ContentRepository;
import ch.entwine.weblounge.common.repository.ContentRepositoryException;
import ch.entwine.weblounge.common.repository.ContentRepositoryUnavailableException;
import ch.entwine.weblounge.common.request.CacheTag;
import ch.entwine.weblounge.common.request.WebloungeRequest;
import ch.entwine.weblounge.common.site.Site;
import ch.entwine.weblounge.common.url.WebUrl;
import ch.entwine.weblounge.taglib.WebloungeTag;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import javax.servlet.jsp.JspException;

/**
* This tag is used to gather a list of pages satisfying certain criteria such
* as the page type, search keywords etc.
*/
public class PageListTag extends WebloungeTag {

  /** Serial version UID */
  private static final long serialVersionUID = -1825541321489778143L;

  /** Logging facility */
  private static final Logger logger = LoggerFactory.getLogger(PageListTag.class.getName());

  /** The list of keywords */
  private List<String> subjects = null;

  /** The number of page headers to return */
  private int count = 10;

  /** The page headers */
  private SearchResult pages = null;

  /** The iteration index */
  private int index = -1;

  /** The pagelet from the request */
  private Pagelet pagelet = null;

  /** The current page */
  private Page page = null;

  /** The current preview */
  private Composer preview = null;

  /** The current page's url */
  private WebUrl url = null;

  /** List of required headlines */
  private List<String> requiredPagelets = null;

  /**
   * Creates a new page header list tag.
   */
  public PageListTag() {
    requiredPagelets = new ArrayList<String>();
    subjects = new ArrayList<String>();
    reset();
  }

  /**
   * Returns the current page. This method serves as a way for embedded tags
   * like the {@link PagePreviewTag} to get to their data.
   *
   * @return the page
   */
  public Page getPage() {
    return page;
  }

  /**
   * Returns the current preview. This method serves as a way for embedded tags
   * like the {@link PagePreviewTag} to get to their data.
   *
   * @return the current page preview
   */
  public Composer getPagePreview() {
    return preview;
  }

  /**
   * Returns the current page's url. This method serves as a way for embedded
   * tags like the {@link PagePreviewTag} to get to their data.
   *
   * @return the page's url
   */
  public WebUrl getPageUrl() {
    return url;
  }

  /**
   * Sets the number of page headers to load. If this attribute is omitted, then
   * all headers are returned.
   *
   * @param count
   *          the number of page headers
   */
  public void setCount(String count) {
    if (count == null)
      throw new IllegalArgumentException("Count must be a positive integer");
    try {
      this.count = Integer.parseInt(count);
    } catch (NumberFormatException e) {
      this.count = Integer.MAX_VALUE;
    }
  }

  /**
   * Sets the list of page keywords to look up. The keywords must consist of a
   * list of strings, separated by either ",", ";" or " ".
   *
   * @param value
   *          the keywords
   */
  public void setKeywords(String value) {
    if (value == null)
      throw new IllegalArgumentException("Keywords cannot be null");
    StringTokenizer tok = new StringTokenizer(value, ",;");
    while (tok.hasMoreTokens()) {
      subjects.add(tok.nextToken().trim());
    }
  }

  /**
   * Indicates the required headlines. The headline element types need to be
   * passed in as comma separated strings, e. g.
   *
   * <pre>
   * text/title, repository/image
   * </pre>
   *
   * @param value
   *          the headlines
   */
  public void setRequireheadlines(String value) {
    StringTokenizer tok = new StringTokenizer(value, ",;");
    while (tok.hasMoreTokens()) {
      String headline = tok.nextToken().trim();
      String[] parts = headline.split("/");
      if (parts.length != 2)
        throw new IllegalArgumentException("Required headlines '" + value + "' are malformed. Required is 'module1/pagelet1, module2/pagelet2, ...");
      requiredPagelets.add(headline);
    }
  }

  /**
   * {@inheritDoc}
   *
   * @see javax.servlet.jsp.tagext.BodyTagSupport#doStartTag()
   */
  @Override
  public int doStartTag() throws JspException {

    // Don't do work if not needed (which is the case during precompilation)
    if (RequestUtils.isPrecompileRequest(request))
      return SKIP_BODY;

    // Make sure we start at the beginning
    index = 0;

    // Save the current pagelet so that we can restore it later
    pagelet = (Pagelet) request.getAttribute(WebloungeRequest.PAGELET);

    stashAttribute(PageListTagExtraInfo.PREVIEW_PAGE);
    stashAttribute(PageListTagExtraInfo.PREVIEW);


    try {
      return (loadNextPage()) ? EVAL_BODY_INCLUDE : SKIP_BODY;
    } catch (ContentRepositoryUnavailableException e) {
      response.invalidate();
      return SKIP_BODY;
    } catch (ContentRepositoryException e) {
      throw new JspException(e);
    }
  }

  /**
   * {@inheritDoc}
   *
   * @see javax.servlet.jsp.tagext.BodyTagSupport#doAfterBody()
   */
  @Override
  public int doAfterBody() throws JspException {
    index++;
    try {
      if (index < count && loadNextPage())
        return EVAL_BODY_AGAIN;
      else
        return SKIP_BODY;
    } catch (ContentRepositoryUnavailableException e) {
      response.invalidate();
      return SKIP_BODY;
    } catch (ContentRepositoryException e) {
      throw new JspException(e);
    }
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.taglib.WebloungeTag#doEndTag()
   */
  @Override
  public int doEndTag() throws JspException {
    removeAndUnstashAttributes();
    request.setAttribute(WebloungeRequest.PAGELET, pagelet);
    return super.doEndTag();
  }

  /**
   * Loads the next page, puts it into the request and returns <code>true</code>
   * if a suitable page was found, false otherwise.
   *
   * @return <code>true</code> if a suitable page was found
   * @throws ContentRepositoryException
   *           if loading the pages fails
   * @throws ContentRepositoryUnavailableException
   *           if the repository is offline
   */
  private boolean loadNextPage() throws ContentRepositoryException,
  ContentRepositoryUnavailableException {
    Site site = request.getSite();

    // Check if headers have already been loaded
    if (pages == null) {
      ContentRepository repository = site.getContentRepository();
      if (repository == null) {
        logger.debug("Unable to load content repository for site '{}'", site);
        throw new ContentRepositoryUnavailableException();
      }

      // Specify which pages to load
      SearchQuery query = new SearchQueryImpl(site);
      query.withVersion(Resource.LIVE);

      // Add the keywords (or)
      for (String subject : subjects) {
        query.withSubject(subject);
      }

      // Add the pagelets required on stage (and)
      if (requiredPagelets.size() > 0) {
        List<Pagelet> pagelets = new ArrayList<Pagelet>();
        for (String headline : requiredPagelets) {
          String[] parts = headline.split("/");
          if (parts.length > 1) {
            Pagelet pagelet = new PageletImpl(parts[0], parts[1]);
            pagelets.add(pagelet);
          }
        }
        query.withPagelets(All, pagelets.toArray(new Pagelet[pagelets.size()])).inStage();
      }

      // Order by date and limit the result set
      query.sortByPublishingDate(SearchQuery.Order.Descending);
      query.withLimit(count);

      // Finally Load the pages
      pages = repository.find(query);
    }

    boolean found = false;
    PageSearchResultItem item = null;
    Page page = null;
    WebUrl url = null;

    // Look for the next header
    while (!found && index < pages.getItems().length) {
      SearchResultItem candidateItem = pages.getItems()[index];
      if (!(candidateItem instanceof PageSearchResultItem)) {
        index++;
        continue;
      }
      item = (PageSearchResultItem) candidateItem;

      // Store the important properties
      url = item.getUrl();
      page = item.getPage();

      // TODO security check

      found = true;
    }

    // Set the headline in the request and add caching information
    if (found && page != null) {
      this.page = page;
      this.preview = new ComposerImpl("stage", page.getPreview());
      this.url = url;
      pageContext.setAttribute(PageListTagExtraInfo.PREVIEW_PAGE, page);
      pageContext.setAttribute(PageListTagExtraInfo.PREVIEW, preview);
     
      // Add cache tags
      response.addTag(CacheTag.Resource, page.getURI().getIdentifier());
      if (url != null)
        response.addTag(CacheTag.Url, url.getPath());
     
      // Adjust modification date
      response.setModificationDate(page.getLastModified());
    }

    return found;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.taglib.WebloungeTag#reset()
   */
  @Override
  protected void reset() {
    super.reset();
    count = 10;
    index = 0;
    page = null;
    pagelet = null;
    pages = null;
    preview = null;
    requiredPagelets.clear();
    subjects.clear();
    url = null;
  }

}
TOP

Related Classes of ch.entwine.weblounge.taglib.content.PageListTag

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.