/**
* Copyright (c) 2009--2016 Red Hat, Inc.
*
* This software is licensed to you under the GNU General Public License,
* version 2 (GPLv2). There is NO WARRANTY for this software, express or
* implied, including the implied warranties of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
* along with this software; if not, see
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*
* Red Hat trademarks are not licensed under GPLv2. No permission is
* granted to use or replicate Red Hat trademarks that are incorporated
* in this software or its documentation.
*/
package com.redhat.rhn.frontend.taglibs.list;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.BodyTagSupport;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import com.redhat.rhn.common.localization.LocalizationService;
import com.redhat.rhn.domain.user.User;
import com.redhat.rhn.frontend.context.Context;
import com.redhat.rhn.frontend.html.HtmlTag;
import com.redhat.rhn.frontend.struts.RequestContext;
import com.redhat.rhn.frontend.taglibs.RhnListTagFunctions;
import com.redhat.rhn.frontend.taglibs.list.decorators.ExpansionDecorator;
import com.redhat.rhn.frontend.taglibs.list.decorators.ListDecorator;
import com.redhat.rhn.frontend.taglibs.list.decorators.PageSizeDecorator;
import com.redhat.rhn.frontend.taglibs.list.helper.ListHelper;
import com.redhat.rhn.frontend.taglibs.list.row.RowRenderer;
/**
* Renders a list of data bean in a page
*
* The list is rendered as a bootstrap 3.x panel
*
* The title of the list is put in the panel-heading
* Pagination, alphabars and addons go into the panel-body
* Bottom pagination and reflinks g into the panel-footer
* The table goes as is, for seamless display into the panel
*
* @see http://getbootstrap.com/components/#panels
*
* @version $Rev $
*/
public class ListTag extends BodyTagSupport {
private static final long serialVersionUID = 8581790371344355223L;
private static final String[] PAGINATION_NAMES = { "allBackward",
"backward", "forward", "allForward" };
private static final String HIDDEN_TEXT = "<input type=\"hidden\" " +
"name=\"%s\" value=\"%s\"/>";
private int columnCount;
private int pageSize = -1;
private String dataSetName = ListHelper.DATA_SET;
private String name = ListHelper.LIST;
private String uniqueName;
private List pageData;
private Iterator iterator;
private Object currentObject;
private Object parentObject;
private String styleClass = "list";
private String styleId;
private int rowCounter = -1;
private String width;
private ListFilter filter;
private String rowName = "current";
private DataSetManipulator manip;
private String emptyKey;
private String decoratorName = null;
private List<ListDecorator> decorators;
private RowRenderer rowRender;
private String alphaBarColumn;
private boolean hidePageNums = false;
private String refLink;
private String refLinkKey;
private String refLinkKeyArg0;
private String title;
private boolean sortable;
private boolean parentIsElement = true;
/**
* method to let the list tag know
* that atleast one of its columns
* is sortable. This will help the
* list tag render the hidden sortBy
* and sortDir fields..
* This method has only package access
* because on ColumnTag needs to talk to this.
* @param isSortable true if atleast
* one of the columns in this list is sortable
*/
void setSortable(boolean isSortable) {
sortable = isSortable;
}
private boolean isSortable() {
return sortable;
}
/**
* Adds a decorator to the parent class..
* @param decName the name of the decorator
* @throws JspException if the decorator can't be loaded.
*/
public void addDecorator(String decName) throws JspException {
ListDecorator dec = getDecorator(decName);
if (dec != null) {
getDecorators().add(dec);
}
}
private List<ListDecorator> getDecorators() {
if (decorators == null) {
decorators = new LinkedList<ListDecorator>();
}
return decorators;
}
/**
* Set the row renderer
* @param newRender the row renderer
*/
public void setRowRenderer(RowRenderer newRender) {
rowRender = newRender;
}
private RowRenderer getRowRenderer() {
if (rowRender == null) {
rowRender = new RowRenderer();
}
return rowRender;
}
private ListDecorator getDecorator(String decName) throws JspException {
if (decName != null) {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
try {
if (decName.indexOf('.') == -1) {
decName = "com.redhat.rhn.frontend.taglibs.list.decorators." +
decName;
}
ListDecorator dec = (ListDecorator) cl.loadClass(decName)
.newInstance();
ListSetTag parent = (ListSetTag) BodyTagSupport
.findAncestorWithClass(this, ListSetTag.class);
dec.setEnvironment(pageContext, parent, getUniqueName());
return dec;
}
catch (Exception e) {
String msg = "Exception while adding Decorator [" + decName + "]";
throw new JspException(msg, e);
}
}
return null;
}
/**
* Sets the decorator class name to use for a list
* @param nameIn decorator class name
*/
public void setDecorator(String nameIn) {
decoratorName = nameIn;
}
/**
* Sets the localized message key used when the list is empty
* @param key message key
*/
public void setEmptykey(String key) {
emptyKey = key;
}
/**
* Bumps up the column count
*
*/
public void addColumn() {
columnCount++;
for (ListDecorator dec : getDecorators()) {
dec.addColumn();
}
}
/**
* Returns
* @return true if the data in use for the current page is empty
*/
public boolean isEmpty() {
return getPageData() == null || getPageData().isEmpty();
}
/**
* Returns the data in use for the current page
* @return list of data
*/
public List getPageData() {
return pageData;
}
/**
* Gets column count
* @return column count
*/
public int getColumnCount() {
return columnCount;
}
/**
* Stores the "name" of the list. This is the "salt" used to build the
* uniqueName used by the ListTag and ColumnTag.
* @param nameIn list name
*/
public void setName(String nameIn) {
name = nameIn;
}
/**
* The name of the list
* @return the list name
*/
public String getName() {
return name;
}
/**
* Build the list's unique name Algorithm for the unique name is: Take the
* CRC value of the following string: request url + ";" + name
* @return unique name
*/
public synchronized String getUniqueName() {
if (uniqueName == null) {
uniqueName = TagHelper.generateUniqueName(name);
}
return uniqueName;
}
/**
* Sets the CSS style class This applies to the enclosing table tag
* @param styleIn class name
*/
public void setStyleclass(String styleIn) {
styleClass = styleIn;
}
/**
* Total width of the table, either in px or percent
* @param widthIn table width
*/
public void setWidth(String widthIn) {
width = widthIn;
}
/**
* Sets the filter used to filter list data
* @param filterIn name of the filter class to use
* @throws JspException error occurred creating an instance of the filter
*/
public void setFilter(String filterIn) throws JspException {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
try {
Class klass = cl.loadClass(filterIn);
filter = (ListFilter) klass.newInstance();
Context threadContext = Context.getCurrentContext();
filter.prepare(threadContext.getLocale());
}
catch (Exception e) {
throw new JspException(e.getMessage());
}
}
/**
*
* @param f the filter to set
*/
void setColumnFilter(ListFilter f) throws JspException {
if (filter != null) {
String msg = "Cannot set the column filter - [%s], " +
"since the table has been has already assigned a filter - [%s]";
throw new JspException(String.format(msg, String.valueOf(f),
String.valueOf(filter)));
}
filter = f;
Context threadContext = Context.getCurrentContext();
filter.prepare(threadContext.getLocale());
manip.filter(filter, pageContext);
}
/**
* Sets the title row needed for this page
* @param titleIn the title row..
*/
public void setTitle(String titleIn) {
title = titleIn;
}
/**
* Get current page row count
* @return number of rows on current page
*/
public int getPageRowCount() {
int retval = pageData == null ? 0 : pageData.size();
return retval;
}
/**
* Sets the name of the dataset to use Tries to locate the list in the
* following order: page context, request attribute, session attribute
*
* @param nameIn name of dataset
* @throws JspException indicates something went wrong
*/
public void setDataset(String nameIn) throws JspException {
dataSetName = nameIn;
Object d = pageContext.getAttribute(nameIn);
if (d == null) {
d = pageContext.getRequest().getAttribute(nameIn);
}
if (d == null) {
HttpServletRequest request = (HttpServletRequest) pageContext
.getRequest();
d = request.getSession(true).getAttribute(nameIn);
}
if (d != null) {
if (d instanceof List) {
pageData = (List) d;
}
else {
throw new JspException("Dataset named \'" + nameIn +
"\' is incompatible." +
" Must be an an instance of java.util.List.");
}
}
else {
pageData = Collections.EMPTY_LIST;
}
}
/**
* The current object being displayed
* @return current object being displayed
*/
public Object getCurrentObject() {
return currentObject;
}
/**
* The parent if this list is dealing with expandable objects
* @return the parent of the current object being displayed
*/
public Object getParentObject() {
return parentObject;
}
/**
* Name used to store the currentObject in the page
* @param nameIn row name
* @throws JspException if row name is empty
*/
public void setRowname(String nameIn) throws JspException {
if (rowName == null || rowName.length() == 0) {
throw new JspException("Row name cannot be empty");
}
rowName = nameIn;
}
/**
* ${@inheritDoc}
*/
@Override
public int doEndTag() throws JspException {
// print the hidden fields after the list widget is printed
// but before the form of the listset is closed.
ListTagUtil.write(pageContext, String.format(HIDDEN_TEXT,
ListTagUtil.makeParentIsAnElementLabel(getUniqueName()),
parentIsElement));
// here decorators should insert other e.g hidden input fields
for (ListDecorator dec : getDecorators()) {
dec.afterList();
}
ListTagUtil.write(pageContext, "<!-- END " + getUniqueName() + " -->");
release();
return BodyTagSupport.EVAL_PAGE;
}
private void doAfterBodyRenderTopAddons() throws JspException {
ListTagUtil.setCurrentCommand(pageContext, getUniqueName(),
ListCommand.TBL_ADDONS);
StringWriter topAlphaBarContent = new StringWriter();
StringWriter topPaginationContent = new StringWriter();
StringWriter topAddonsContent = new StringWriter();
StringWriter topExtraContent = new StringWriter();
pageContext.pushBody(topAlphaBarContent);
if (!manip.isListEmpty() && !StringUtils.isBlank(alphaBarColumn)) {
AlphaBarHelper.getInstance().writeAlphaBar(pageContext,
manip.getAlphaBarIndex(), getUniqueName());
}
pageContext.popBody();
pageContext.pushBody(topPaginationContent);
if (!isEmpty()) {
for (ListDecorator dec : getDecorators()) {
dec.beforeTopPagination();
}
}
if (filter != null && manip.getUnfilteredDataSize() != 0) {
ListTagUtil.renderFilterSubmit(pageContext, getUniqueName());
}
renderTopPaginationControls();
pageContext.popBody();
pageContext.pushBody(topAddonsContent);
if (!isEmpty()) {
for (ListDecorator dec : getDecorators()) {
dec.onTopExtraAddons();
}
}
pageContext.popBody();
int topContentLength = topAddonsContent.getBuffer().length() +
topAlphaBarContent.getBuffer().length() +
topPaginationContent.getBuffer().length() +
topExtraContent.getBuffer().length();
if (topContentLength > 0) {
ListTagUtil.write(pageContext,
"<div class=\"spacewalk-list-top-addons\">");
ListTagUtil.write(pageContext,
"<div class=\"spacewalk-list-alphabar\">");
ListTagUtil.write(pageContext, topAlphaBarContent.toString());
ListTagUtil.write(pageContext, "</div>");
ListTagUtil.write(pageContext,
"<div class=\"spacewalk-list-pagination\">");
ListTagUtil.write(pageContext, topPaginationContent.toString());
ListTagUtil.write(pageContext, "</div>");
ListTagUtil.write(pageContext,
"<div class=\"spacewalk-list-top-addons-extra\">");
ListTagUtil.write(pageContext, topAddonsContent.toString());
ListTagUtil.write(pageContext, "</div>");
ListTagUtil.write(pageContext, "</div>");
ListTagUtil.write(pageContext,
"<div class=\"spacewalk-list-top-extra\">");
ListTagUtil.write(pageContext, "</div>");
}
ListTagUtil.write(pageContext, "<div class=\"panel panel-default\">");
// as the header addons is populated with decorators, we don't
// know if there will be content or not, but we want to avoid
// writing the head tag at all if there is none, so we push a
// buffer into the stack, and empty it later.
StringWriter headAddons = new StringWriter();
StringWriter headFilterContent = new StringWriter();
StringWriter headExtraContent = new StringWriter();
pageContext.pushBody(headAddons);
if (!isEmpty()) {
for (ListDecorator dec : getDecorators()) {
dec.onHeadExtraAddons();
}
}
pageContext.popBody();
pageContext.pushBody(headFilterContent);
if (filter != null && manip.getUnfilteredDataSize() != 0) {
ListTagUtil.renderFilterUI(pageContext, filter,
getUniqueName(), width, columnCount);
}
pageContext.popBody();
pageContext.pushBody(headExtraContent);
if (!isEmpty()) {
for (ListDecorator dec : getDecorators()) {
dec.onHeadExtraContent();
}
}
pageContext.popBody();
int headContentLength = headFilterContent.getBuffer().length() +
headAddons.getBuffer().length() +
headExtraContent.getBuffer().length();
if (!StringUtils.isBlank(title)) {
headContentLength += title.length();
}
// this avoid render the row is there is no content at all
if (headContentLength > 0) {
ListTagUtil.write(pageContext, "<div class=\"panel-heading\">");
// only if there is a title, add a panel-heading
if (!StringUtils.isBlank(title)) {
HtmlTag h3 = new HtmlTag("h3");
h3.setAttribute("class", "panel-title");
h3.addBody(title);
ListTagUtil.write(pageContext, h3.render());
}
// render the navigation and filters as a row of the header
ListTagUtil.write(pageContext,
"<div class=\"spacewalk-list-head-addons\">");
ListTagUtil.write(pageContext,
"<div class=\"spacewalk-list-filter\">");
ListTagUtil.write(pageContext, headFilterContent.toString());
ListTagUtil.write(pageContext, "</div>");
ListTagUtil.write(pageContext,
"<div class=\"spacewalk-list-head-addons-extra\">");
ListTagUtil.write(pageContext, headAddons.toString());
ListTagUtil.write(pageContext, "</div>");
ListTagUtil.write(pageContext, "</div>");
ListTagUtil.write(pageContext,
"<div class=\"spacewalk-list-head-extra\">");
ListTagUtil.write(pageContext, headExtraContent.toString());
ListTagUtil.write(pageContext, "</div>");
// close the panel heading
ListTagUtil.write(pageContext, "</div>");
}
HttpServletRequest request = (HttpServletRequest) pageContext
.getRequest();
manip.bindPaginationInfo();
request.setAttribute("dataSize", String
.valueOf(pageData.size() + 1));
if (pageData != null && pageData.size() > 0) {
iterator = pageData.iterator();
}
else {
iterator = null;
}
}
private int doAfterBodyRenderBeforeData() throws JspException {
ListTagUtil.write(pageContext, "</tr>");
ListTagUtil.write(pageContext, "</thead>");
ListTagUtil.setCurrentCommand(pageContext, getUniqueName(),
ListCommand.BEFORE_RENDER);
if (manip.isListEmpty()) {
renderEmptyList();
ListTagUtil.write(pageContext, "</table>");
// close panel
ListTagUtil.write(pageContext, "</div>");
// close list
ListTagUtil.write(pageContext, "</div>");
return BodyTagSupport.SKIP_BODY;
}
ListTagUtil.write(pageContext, "<tbody>");
// render first row. The rest will be rendered in subsequent
// calls to doAfterBody
return doAfterBodyRenderData();
}
private int doAfterBodyRenderData() throws JspException {
// if there was a previous object, close its row
if (currentObject != null) {
ListTagUtil.write(pageContext, "</tr>");
}
ListTagUtil.setCurrentCommand(pageContext, getUniqueName(),
ListCommand.RENDER);
if (iterator.hasNext()) {
Object obj = iterator.next();
if (RhnListTagFunctions.isExpandable(obj)) {
parentObject = obj;
}
currentObject = obj;
}
else {
currentObject = null;
}
if (currentObject != null) {
ListTagUtil.write(pageContext, "<tr");
renderRowClassAndId();
ListTagUtil.write(pageContext, ">");
pageContext.setAttribute(rowName, currentObject);
}
else {
return doAfterBodyRenderAfterData();
}
return BodyTagSupport.EVAL_BODY_AGAIN;
}
private int doAfterBodyRenderAfterData() throws JspException {
ListTagUtil.setCurrentCommand(pageContext, getUniqueName(),
ListCommand.AFTER_RENDER);
ListTagUtil.write(pageContext, "</tbody>");
return BodyTagSupport.EVAL_BODY_AGAIN;
}
private void doAfterBodyRenderColHeaders() throws JspException {
startTable();
ListTagUtil.setCurrentCommand(pageContext, getUniqueName(),
ListCommand.COL_HEADER);
ListTagUtil.write(pageContext, "<thead>");
// open the row tag for the column header th's
ListTagUtil.write(pageContext, "<tr>");
}
private int doAfterBodyRenderFooterAddons() throws JspException {
ListTagUtil.write(pageContext, "</table>");
ListTagUtil.setCurrentCommand(pageContext, getUniqueName(),
ListCommand.TBL_FOOTER);
// as the footer addons are populated with decorators, we don't
// know if there will be content or not, but we want to avoid
// writing the tfoot tag at all if there is none, so we push a
// buffer into the stack, and empty it later.
StringWriter footAddonsContent = new StringWriter();
StringWriter footLinksContent = new StringWriter();
StringWriter footExtraContent = new StringWriter();
pageContext.pushBody(footAddonsContent);
if (!manip.isListEmpty()) {
for (ListDecorator dec : getDecorators()) {
dec.onFooterExtraAddons();
}
}
pageContext.popBody();
pageContext.pushBody(footExtraContent);
if (!manip.isListEmpty()) {
for (ListDecorator dec : getDecorators()) {
dec.onFooterExtraContent();
}
}
pageContext.popBody();
pageContext.pushBody(footLinksContent);
// if there is reference links, put them as a panel footer
if ((refLink != null) && (!isEmpty())) {
ListTagUtil.write(pageContext, "<a href=\"" + refLink + "\" >");
/* Here we render the reflink and its key. If the key hasn't been set
* we just display the link address itself.
*/
if (refLinkKey != null) {
Object[] args = new Object[2];
args[0] = new Integer(getPageRowCount());
args[1] = refLinkKeyArg0;
String message = LocalizationService.getInstance().
getMessage(refLinkKey, args);
ListTagUtil.write(pageContext, message);
}
else {
ListTagUtil.write(pageContext, refLink);
}
ListTagUtil.write(pageContext, "</a>");
}
pageContext.popBody();
int footerContentLength = footLinksContent.getBuffer().length() +
footAddonsContent.getBuffer().length() +
footExtraContent.getBuffer().length();
if (footerContentLength > 0) {
ListTagUtil.write(pageContext, "<div class=\"panel-footer\">");
ListTagUtil.write(pageContext,
"<div class=\"spacewalk-list-footer-addons\">");
ListTagUtil.write(pageContext,
"<div class=\"spacewalk-list-reflinks\">");
ListTagUtil.write(pageContext, footLinksContent.toString());
ListTagUtil.write(pageContext, "</div>");
ListTagUtil.write(pageContext,
"<div class=\"spacewalk-list-footer-addons-extra\">");
ListTagUtil.write(pageContext, footAddonsContent.toString());
ListTagUtil.write(pageContext, "</div>");
ListTagUtil.write(pageContext, "</div>");
ListTagUtil.write(pageContext,
"<div class=\"spacewalk-list-footer-extra\">");
ListTagUtil.write(pageContext, footExtraContent.toString());
ListTagUtil.write(pageContext, "</div>");
// closes the panel footer
ListTagUtil.write(pageContext, "</div>");
}
// close the panel
ListTagUtil.write(pageContext, "</div>");
ListTagUtil.write(pageContext,
"<div class=\"spacewalk-list-bottom-addons\">");
renderFooterPaginationControls();
ListTagUtil.write(pageContext,
"<div class=\"spacewalk-list-bottom-addons-extra\">");
if (!isEmpty()) {
for (ListDecorator dec : getDecorators()) {
dec.onBottomExtraAddons();
}
}
ListTagUtil.write(pageContext, "</div>");
ListTagUtil.write(pageContext, "</div>");
ListTagUtil.write(pageContext,
"<div class=\"spacewalk-list-bottom-addons-extra\">");
if (!isEmpty()) {
for (ListDecorator dec : getDecorators()) {
dec.onBottomExtraContent();
}
}
ListTagUtil.write(pageContext, "</div>");
// we render the hidden fields outside of the table
if (isSortable()) {
renderSortableHiddenFields();
}
// close list
ListTagUtil.write(pageContext, "</div>");
return BodyTagSupport.SKIP_BODY;
}
private void doAfterBodyRenderListBegin() throws JspException {
ListTagUtil.setCurrentCommand(pageContext, getUniqueName(),
ListCommand.TBL_HEADING);
ListTagUtil.write(pageContext, "<!-- START LIST " + getUniqueName() + " -->");
String listId = (getStyleId() != null) ? getStyleId() : getUniqueName();
setupManipulator();
manip.sort();
pageData = manip.getPage();
for (ListDecorator dec : getDecorators()) {
dec.setCurrentList(this);
dec.beforeList();
}
ListTagUtil.write(pageContext, "<div class=\"spacewalk-list");
if (styleClass != null) {
ListTagUtil.write(pageContext, " " + styleClass);
}
ListTagUtil.write(pageContext, "\" id=\"" + listId + "\">");
}
/**
* ${@inheritDoc}
*/
@Override
public int doAfterBody() throws JspException {
int retval = BodyTagSupport.EVAL_BODY_AGAIN;
ListCommand nextCmd = getNextCommand();
switch (nextCmd) {
case TBL_HEADING: doAfterBodyRenderListBegin(); break;
case TBL_ADDONS: doAfterBodyRenderTopAddons(); break;
case COL_HEADER: doAfterBodyRenderColHeaders(); break;
case BEFORE_RENDER: retval = doAfterBodyRenderBeforeData(); break;
case RENDER: retval = doAfterBodyRenderData(); break;
case AFTER_RENDER: retval = doAfterBodyRenderAfterData(); break;
case TBL_FOOTER: retval = doAfterBodyRenderFooterAddons(); break;
default: break;
}
return retval;
}
private void renderSortableHiddenFields() throws JspException {
String sortByLabel = ListTagUtil.makeSortByLabel(getUniqueName());
String sortDirLabel = ListTagUtil.makeSortDirLabel(getUniqueName());
HtmlTag sortByInputTag = new HtmlTag("input");
sortByInputTag.setAttribute("type", "hidden");
sortByInputTag.setAttribute("name", sortByLabel);
sortByInputTag.setAttribute("id",
ListTagUtil.makeSortById(getUniqueName()));
sortByInputTag.setAttribute("value", StringEscapeUtils.escapeHtml(StringUtils
.defaultString(pageContext.getRequest().getParameter(sortByLabel))));
HtmlTag sortByDirTag = new HtmlTag("input");
sortByDirTag.setAttribute("type", "hidden");
sortByDirTag.setAttribute("name", sortDirLabel);
sortByDirTag.setAttribute("id", ListTagUtil.
makeSortDirId(getUniqueName()));
String dir = StringUtils.defaultString(pageContext.getRequest().getParameter(
sortDirLabel));
if (dir.equals(RequestContext.SORT_ASC)) {
sortByDirTag.setAttribute("value", RequestContext.SORT_ASC);
}
else if (dir.equals(RequestContext.SORT_DESC)) {
sortByDirTag.setAttribute("value", RequestContext.SORT_DESC);
}
else {
sortByDirTag.setAttribute("value", "");
}
ListTagUtil.write(pageContext, sortByInputTag.render());
ListTagUtil.write(pageContext, sortByDirTag.render());
}
private void setupPageData() throws JspException {
Object d = pageContext.getAttribute(dataSetName);
if (d == null) {
d = pageContext.getRequest().getAttribute(dataSetName);
}
if (d == null) {
HttpServletRequest request = (HttpServletRequest) pageContext
.getRequest();
d = request.getSession(true).getAttribute(dataSetName);
}
if (d != null) {
if (d instanceof List) {
pageData = (List) d;
}
else {
throw new JspException("Dataset named \'" + dataSetName +
"\' is incompatible." +
" Must be an an instance of java.util.List.");
}
}
else {
pageData = Collections.EMPTY_LIST;
}
}
/**
* ${@inheritDoc}
*/
@Override
public int doStartTag() throws JspException {
verifyEnvironment();
addDecorator(decoratorName);
setupPageData();
setPageSize();
manip = new DataSetManipulator(pageSize, pageData,
(HttpServletRequest) pageContext.getRequest(),
getUniqueName(), isParentAnElement());
ListTagUtil.setCurrentCommand(pageContext, getUniqueName(),
ListCommand.ENUMERATE);
return BodyTagSupport.EVAL_BODY_INCLUDE;
}
private void setupManipulator() throws JspException {
manip.setAlphaColumn(alphaBarColumn);
manip.filter(filter, pageContext);
if (!StringUtils.isBlank(ListTagHelper.
getFilterValue(pageContext.getRequest(), getUniqueName()))) {
LocalizationService ls = LocalizationService.getInstance();
ListTagUtil.write(pageContext, "<div class=\"site-info\">");
if (manip.getTotalDataSetSize() != manip.getUnfilteredDataSize()) {
if (manip.getAllData().size() == 0) {
ListTagUtil.write(pageContext, ls.getMessage(
"listtag.filteredmessageempty",
new Integer(manip.getTotalDataSetSize())));
}
else {
ListTagUtil.write(pageContext,
ls.getMessage("listtag.filteredmessage",
new Integer(manip.getTotalDataSetSize())));
}
ListTagUtil.write(pageContext, "<br /><a href=\"");
List<String> excludeParams = new ArrayList<String>();
excludeParams.add(ListTagUtil.makeSelectActionName(getUniqueName()));
excludeParams.add(ListTagUtil.makeFilterByLabel(getUniqueName()));
excludeParams.add(ListTagUtil.makeFilterValueByLabel(getUniqueName()));
excludeParams.add(ListTagUtil.makeOldFilterValueByLabel(getUniqueName()));
excludeParams.add(ListTagUtil.
makeParentIsAnElementLabel(getUniqueName()));
excludeParams.add("submitted");
ListTagUtil.write(pageContext,
ListTagUtil.makeParamsLink(pageContext.getRequest(), name,
Collections.EMPTY_MAP, excludeParams));
ListTagUtil.write(pageContext, "\">" +
ls.getMessage("listtag.clearfilter"));
ListTagUtil.write(pageContext, ls.getMessage("listtag.seeall",
new Integer(manip.getUnfilteredDataSize())));
ListTagUtil.write(pageContext, "</a>");
}
else {
ListTagUtil.write(pageContext, ls.getMessage(
"listtag.all_items_in_filter",
ListTagHelper.getFilterValue(pageContext.getRequest(),
getUniqueName())));
}
ListTagUtil.write(pageContext, "</div>");
}
}
/**
* ${@inheritDoc}
*/
@Override
public void release() {
if (pageContext.getAttribute("current") != null) {
pageContext.removeAttribute("current");
}
dataSetName = ListHelper.DATA_SET;
name = ListHelper.LIST;
uniqueName = null;
pageData = null;
iterator = null;
currentObject = null;
parentObject = null;
styleClass = "list";
styleId = null;
rowCounter = -1;
setRowRenderer(null);
width = null;
columnCount = 0;
pageSize = -1;
rowName = "current";
filter = null;
getDecorators().clear();
decorators = null;
decoratorName = null;
title = null;
sortable = false;
parentIsElement = true;
super.release();
}
private void renderEmptyList() throws JspException {
ListTagUtil.write(pageContext, "<tbody>");
ListTagUtil.write(pageContext, "<tr><td ");
ListTagUtil.write(pageContext, "colspan=\"");
ListTagUtil.write(pageContext, String.valueOf(columnCount));
ListTagUtil.write(pageContext, "\">");
if (emptyKey != null) {
LocalizationService ls = LocalizationService.getInstance();
String msg = ls.getMessage(emptyKey);
ListTagUtil
.write(pageContext, "<div class=\"list-empty-message\">");
ListTagUtil.write(pageContext, msg);
ListTagUtil.write(pageContext, "</div>");
}
ListTagUtil.write(pageContext, "</td></tr>");
ListTagUtil.write(pageContext, "</tbody>");
}
private void renderRowClassAndId() throws JspException {
rowCounter++;
ListTagUtil.write(pageContext, " class=\"");
ListTagUtil.write(pageContext, getRowRenderer().getRowClass(getCurrentObject()));
if (rowCounter == manip.findAlphaPosition() % pageSize) {
ListTagUtil.write(pageContext, " alphaResult");
}
ListTagUtil.write(pageContext, "\" ");
if (getCurrentObject() != null) { //if we're rendering a non-item row (e.g. reflink)
ListTagUtil.write(pageContext, "id=\"");
ListTagUtil.write(pageContext, getRowRenderer().getRowId(getUniqueName(),
getCurrentObject()));
ListTagUtil.write(pageContext, "\" ");
String style = getRowRenderer().getRowStyle(getCurrentObject());
if (!StringUtils.isBlank(style)) {
ListTagUtil.write(pageContext, "style=\"");
ListTagUtil.write(pageContext, style);
ListTagUtil.write(pageContext, "\" ");
}
}
}
private void startTable() throws JspException {
if (hasExpansionDecorator()) {
ListTagUtil.write(pageContext, "<table class=\"table table-striped\"" +
" id=\"" + this.getStyleId() + "_exp\"");
}
else {
ListTagUtil.write(pageContext, "<table class=\"table table-striped\"");
}
if (width != null) {
ListTagUtil.write(pageContext, " width=\"");
ListTagUtil.write(pageContext, width);
ListTagUtil.write(pageContext, "\"");
}
ListTagUtil.write(pageContext, ">");
}
private ListCommand getNextCommand() {
ListCommand cmd = ListTagUtil.getCurrentCommand(this, pageContext);
switch (cmd) {
case ENUMERATE: return ListCommand.TBL_HEADING;
case TBL_HEADING: return ListCommand.TBL_ADDONS;
case TBL_ADDONS: return ListCommand.COL_HEADER;
case COL_HEADER: return ListCommand.BEFORE_RENDER;
case BEFORE_RENDER: return ListCommand.RENDER;
// The following RENDER-->RENDER appears to be intentional,
// depending on doAfterBodyRenderData() to eventually set cmd to AFTER_RENDER.
case RENDER: return ListCommand.RENDER;
case AFTER_RENDER: return ListCommand.TBL_FOOTER;
default: return null;
}
}
private void renderFooterPaginationControls() throws JspException {
if (isEmpty() || hidePageNums) {
return;
}
ListTagUtil.write(pageContext,
"<div class=\"spacewalk-list-pagination\">");
if (!isEmpty() && !hidePageNums) {
ListTagUtil.write(pageContext, manip.getPaginationMessage());
}
if (!manip.isListEmpty()) {
for (ListDecorator dec : getDecorators()) {
dec.afterBottomPagination();
}
}
ListTagUtil.renderPaginationLinks(pageContext, PAGINATION_NAMES,
manip.getPaginationLinks());
ListTagUtil.write(pageContext, "</div>");
}
private void renderTopPaginationControls() throws JspException {
if (!isEmpty() && !hidePageNums) {
ListTagUtil.write(pageContext, manip.getPaginationMessage());
}
if (!manip.isListEmpty()) {
for (ListDecorator dec : getDecorators()) {
dec.afterTopPagination();
}
}
ListTagUtil.renderPaginationLinks(pageContext, PAGINATION_NAMES,
manip.getPaginationLinks());
}
private void setPageSize() {
int tmp = -1;
RequestContext rctx = new RequestContext(
(HttpServletRequest) pageContext.getRequest());
User user = rctx.getCurrentUser();
if (user != null) {
tmp = user.getPageSize();
if (tmp > 0) {
pageSize = tmp;
}
}
if (pageSize < 1) {
pageSize = 10;
}
HttpServletRequest httpRequest = (HttpServletRequest)
pageContext.getRequest();
if (PageSizeDecorator.pageWidgetSelected(httpRequest, getUniqueName())) {
int size = PageSizeDecorator.getSelectedPageSize(httpRequest,
getUniqueName());
List <Integer> pageSizes = PageSizeDecorator.getPageSizes();
if (size < 1 || size > pageSizes.get(pageSizes.size() - 1)) {
return;
}
pageSize = size;
}
}
private void verifyEnvironment() throws JspException {
if (BodyTagSupport.findAncestorWithClass(this, ListSetTag.class) == null) {
throw new JspException("List must be enclosed by a ListSetTag");
}
}
/**
*
* @return returns the page context
*/
public PageContext getContext() {
return pageContext;
}
/**
* @return Returns the manip.
*/
public DataSetManipulator getManip() {
return manip;
}
/**
* @param alphaBarColumnIn The alphaBarColumn to set.
*/
public void setAlphabarcolumn(String alphaBarColumnIn) {
this.alphaBarColumn = alphaBarColumnIn;
}
/**
* provides the current page size
* @return the page size
*/
public int getPageSize() {
return pageSize;
}
/**
* @return Returns the alphaBarColumn.
*/
public String getAlphaBarColumn() {
return alphaBarColumn;
}
/**
* if set to true, the page numbers at the top and bottom of the list will not
* be displayed
* @param value true or false
*/
public void setHidepagenums(String value) {
hidePageNums = ListTagUtil.toBoolean(value);
}
/**
* if set to true, the parent in a tree setup will
* be considered as an element by itself
* @param value true or false
*/
public void setParentiselement(String value) {
parentIsElement = ListTagUtil.toBoolean(value);
}
/**
* if set to true, the parent in a tree setup will
* be considered as an element by itself
* @return true if the parent itself is an element
*/
public boolean isParentAnElement() {
return parentIsElement;
}
/**
*
* @return CSS ID for <table>
*/
public String getStyleId() {
if (StringUtils.isBlank(styleId)) {
styleId = "list_" + getUniqueName() + "style_id";
}
return styleId;
}
/**
*
* @param styleIdIn CSS ID to set for HTML table tag
*/
public void setStyleId(String styleIdIn) {
this.styleId = styleIdIn;
}
/**
*
* @return the optional reference link that will be included in the last row
* of the table
*/
public String getRefLink() {
return refLink;
}
/**
*
* @param refLinkIn the optional reference link that will be added to the last row
* of the table
*/
public void setReflink(String refLinkIn) {
this.refLink = refLinkIn;
}
/**
*
* @return the key for the reference link
*/
public String getRefLinkKey() {
return refLinkKey;
}
/**
*
* @param refLinkKeyIn the key for the reference link
*/
public void setReflinkkey(String refLinkKeyIn) {
this.refLinkKey = refLinkKeyIn;
}
/**
*
* @return the optional argument that may be included in the reference link
*/
public String getRefLinkKeyArg0() {
return refLinkKeyArg0;
}
/**
*
* @param refLinkKeyArg0In the optional argument that may be included in the
* reference link
*/
public void setReflinkkeyarg0(String refLinkKeyArg0In) {
this.refLinkKeyArg0 = refLinkKeyArg0In;
}
private boolean hasExpansionDecorator() {
for (ListDecorator dec : getDecorators()) {
if (dec.getClass().equals(ExpansionDecorator.class)) {
return true;
}
}
return false;
}
}