/**
* Copyright (c) 2009--2014 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;
import java.io.IOException;
import java.io.Writer;
import java.util.Arrays;
import java.util.Collections;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspTagException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyContent;
import org.apache.commons.lang.StringUtils;
import com.redhat.rhn.common.localization.LocalizationService;
import com.redhat.rhn.common.util.DynamicComparator;
import com.redhat.rhn.common.util.ExportWriter;
import com.redhat.rhn.common.util.ServletExportHandler;
import com.redhat.rhn.frontend.dto.BaseListDto;
import com.redhat.rhn.frontend.dto.UserOverview;
import com.redhat.rhn.frontend.struts.RequestContext;
/**
* The UnpagedListDisplayTag defines the structure of the ListView. This tag iterates
* through the {@link com.redhat.rhn.common.db.datasource.DataResult DataResult}
* contained in its parent tag,
* {@link com.redhat.rhn.frontend.taglibs.ListTag ListTag}. In the first
* iteration the {@link com.redhat.rhn.frontend.taglibs.ColumnTag ColumnTags}
* render the headers of the ListView, while subsequent iterations render the
* data contained within the
* {@link com.redhat.rhn.common.db.datasource.DataResult DataResult}.
* <p>
* The UnpagedListTag has the following optional attributes:
* <code>filterBy</code>
* <code>renderDisabled</code>
* <code>domainClass</code>
* <code>title</code>
* <code>type</code>
* <code>transparent</code>
*
* The <code>filterBy</code> attribute specifies the column name with which
* to filter the data.
* <p>
* The <code> type </code> attribute sepcifies what class the list is
* <p>
* <code>transparent</code> if set to true will make it so that the
* table has no borders, and all the rows are white.
* Example usage of the ListDisplayTag with no sets:
* <pre>
* ...
* <rhn:unpagedlistdisplay>
* <rhn:column header="l10n.jsp.messagekey">
* display this value
* </rhn:column>
* <rhn:column header="l10n.jsp.messagekey1">
* display this value too
* </rhn:column>
* </rhn:unpagedlistdisplay>
* ...
* </pre>
* The following shows how to define a ListView with a set column.
* <pre>
* ...
* <rhn:unpagedlistdisplay title="example.title"
* transparent="true">
* <rhn:column header="l10n.jsp.messagekey1">
* display this value
* </rhn:column>
* </rhn:unpagedlistdisplay>
* ...
* </pre>
*
* @version $Rev: 79797 $
* @see com.redhat.rhn.frontend.taglibs.ColumnTag
* @see com.redhat.rhn.frontend.taglibs.ListTag
*/
public class UnpagedListDisplayTag extends ListDisplayTagBase {
/** row count determines whether we're an even or odd row */
private int rowCnt = 0;
protected int currRow = 0;
/** determines whether or not we should show the borders
* of the list and if the rows should all be white
*/
private boolean transparent = false;
/** determines whether we should show the disabled CSS */
private String nodeIdString = null;
/** Public constructor */
public UnpagedListDisplayTag() {
}
/**
* @return returns whether or not the table is transparent
*/
public boolean isTransparent() {
return transparent;
}
/**
* @param booleanIn sets transparent
*/
public void setTransparent(boolean booleanIn) {
transparent = booleanIn;
}
private void doSort(String sortedColumn) {
HttpServletRequest request = (HttpServletRequest)pageContext.getRequest();
Collections.sort(getPageList(), new DynamicComparator(sortedColumn,
request.getParameter(RequestContext.SORT_ORDER)));
}
private String getSortedColumn() {
HttpServletRequest request =
(HttpServletRequest) pageContext.getRequest();
return request.getParameter(RequestContext.LIST_SORT);
}
protected void setupPageList() throws JspTagException {
super.setupPageList();
currRow = 0;
}
//////////////////////////////////////////////////////////////////////////
// RENDER methods
//////////////////////////////////////////////////////////////////////////
@Override
protected void renderHeadExtraAddons(Writer out) throws IOException {
super.renderHeadExtraAddons(out);
LocalizationService ls = LocalizationService.getInstance();
if (getType().equals("treeview")) {
out.append("<div class=\"spacewalk-list-channel-show-hide\">" +
"<a class=\"spacewalk-list-channel-show-all\"" +
" href=\"javascript:showAllRows();\" style=\"cursor: pointer;\">" +
ls.getMessage("channels.overview.showall") +
"</a> | " +
"<a class=\"spacewalk-list-channel-hide-all\"" +
" href=\"javascript:hideAllRows();\" style=\"cursor: pointer;\">" +
ls.getMessage("channels.overview.hideall") + "</a></div>");
}
}
private String getTrElement(Object o, int row) {
if (!(o instanceof BaseListDto &&
!((BaseListDto)o).changeRowColor())) {
rowCnt++;
rowCnt = rowCnt % 2;
}
StringBuilder retval;
if (rowCnt == 1 || isTransparent()) {
retval = new StringBuilder("<tr class=\"list-row-odd");
}
else {
retval = new StringBuilder("<tr class=\"list-row-even");
}
if (renderDisabled() && o instanceof UserOverview &&
((UserOverview)o).getStatus().equals("disabled")) {
return retval.append("-disabled>").toString();
}
if ((o instanceof BaseListDto &&
((BaseListDto)o).greyOutRow())) {
retval = retval.append(" greyed-out");
}
if ((o instanceof BaseListDto)) {
nodeIdString = ((BaseListDto)o).getNodeIdString();
retval = retval.append("\" id=\"" + createIdString(nodeIdString));
if (getType().equals("treeview") && isChild(nodeIdString)) {
retval.append("\" style=\"display: none;");
}
}
return retval.append("\">").toString();
}
/**
* Creates the id-string for a given tree-node. For parents, it's id####.
* For children, it's child-id####
*
* @param nId the node's id-string
* @return tr/td id-string
*/
public String createIdString(String nId) {
StringBuilder retval = new StringBuilder();
if (isParent(nId)) {
retval.append("id" + nId.substring(1));
}
else if (isChild(nId)) {
retval.append("child-id" + nId.substring(1) + "-" + currRow);
}
return retval.toString();
}
/**
* Returns true if the node-id-string represent a parent-node
* @param s string of interest
* @return true if parent-string, false else
*/
public boolean isParent(String s) {
return (s != null && s.startsWith("p"));
}
/**
* Returns true if the node-id-string represent a child-node
* @param s string of interest
* @return true if child-string, false else
*/
public boolean isChild(String s) {
return (s != null && s.startsWith("c"));
}
/**
* If the User requested an Export or not.
* @return boolean if export or not
*/
public boolean isExport() {
RequestContext ctx = new RequestContext((HttpServletRequest)
pageContext.getRequest());
return (ctx.isRequestedExport() && getExportColumns() != null);
}
//////////////////////////////////////////////////////////////////////////
// JSP Tag lifecycle methods
//////////////////////////////////////////////////////////////////////////
/** {@inheritDoc} */
public int doStartTag() throws JspException {
rowCnt = 0;
JspWriter out = null;
try {
out = pageContext.getOut();
setupPageList();
// Now that we have setup the proper tag state we
// need to return if this is an export render.
if (isExport()) {
return SKIP_PAGE;
}
String sortedColumn = getSortedColumn();
if (sortedColumn != null) {
doSort(sortedColumn);
}
out.print("<div class=\"spacewalk-list\">");
out.print("<div class=\"panel panel-default\">");
renderPanelHeading(out);
/* If the type is list, we must set the width explicitly. Otherwise,
* it shouldn't matter
*/
if (getType().equals("list")) {
out.print("<table class=\"table table-striped\"");
}
else if (getType().equals("treeview")) {
out.print("<table class=\"table table-striped\" id=\"channel-list\"");
}
else {
out.print("<table class=\"" + getType() + "\"");
}
/*if (isTransparent()) {
out.print(" style=\"border-bottom: 1px solid #ffffff;\" ");
}*/
out.println(">");
out.println("<thead>");
out.println("<tr>");
if (getIterator() != null && getIterator().hasNext()) {
// Push a new BodyContent writer onto the stack so that
// we can buffer the body data.
bodyContent = pageContext.pushBody();
return EVAL_BODY_INCLUDE;
}
return SKIP_BODY;
}
catch (IOException ioe) {
throw new JspException("IO error writing to JSP file:", ioe);
}
}
/** {@inheritDoc} */
public int doEndTag() throws JspException {
JspWriter out = null;
try {
if (getPageList().isEmpty()) {
return EVAL_PAGE;
}
if (isExport()) {
ExportWriter eh = createExportWriter();
String[] columns = StringUtils.split(this.getExportColumns(),
',');
eh.setColumns(Arrays.asList(columns));
ServletExportHandler seh = new ServletExportHandler(eh);
pageContext.getOut().clear();
pageContext.getOut().clearBuffer();
pageContext.getResponse().reset();
seh.writeExporterToOutput(
(HttpServletResponse) pageContext.getResponse(),
getPageList());
return SKIP_PAGE;
}
// Get the JSPWriter that the body used, then pop the
// bodyContent, so that we can get the real JspWriter with getOut.
BodyContent body = getBodyContent();
pageContext.popBody();
out = pageContext.getOut();
if (body != null) {
String bodyString = body.getString();
out.println(bodyString);
}
// Rely on content to have emitted a tbody tag somewhere
out.println("</tbody>");
out.println("</table>\n");
out.println("</div>\n");
out.println("</div>\n");
setNumberOfColumns(0);
setColumnCount(0);
setCurrRow(0);
}
catch (IOException e) {
throw new JspException("IO error" + e.getMessage());
}
finally {
pageContext.setAttribute("current", null);
}
return EVAL_PAGE;
}
/** {@inheritDoc} */
public int doAfterBody() throws JspException {
JspWriter out = null;
try {
out = pageContext.getOut();
if (pageContext.getAttribute("current") == null) {
out.println("</tr>");
out.println("</thead>");
out.println("<tbody>");
}
else {
out.println("</tr>");
}
if (getIterator().hasNext()) {
setColumnCount(0);
Object next = getIterator().next();
out.println(getTrElement(next, currRow++));
pageContext.setAttribute("current", next);
return EVAL_BODY_AGAIN;
}
}
catch (IOException e) {
throw new JspException("Error while writing to JSP: " +
e.getMessage());
}
return SKIP_BODY;
}
/** {@inheritDoc} */
@Override
public void release() {
// reset the state of the tag
currRow = 0;
rowCnt = 0;
nodeIdString = null;
// now release our super classes
super.release();
}
/**
* @return Returns the nodeIdString.
*/
public String getNodeIdString() {
return nodeIdString;
}
/**
* Returns row currently being rendered
* @return current row
*/
public int getCurrRow() {
return currRow;
}
/**
* Set current row being rendered
* @param curr new current row
*/
public void setCurrRow(int curr) {
currRow = curr;
}
}