Update of /cvsroot/displaytag/table-ben/src/com/tablelib/tags
In directory sc8-pr-cvs1:/tmp/cvs-serv11035
Added Files:
ActionTag.java ColumnDecorator.java ColumnTag.java
Decorator.java DecoratorImpl.java PagingInformation.java
PaginigInformationImpl.java SearchTag.java SetPropertyTag.java
SmartListHelper.java TableDecorator.java TableExporter.java
TableImpl.java TableTag.java TableTagExtraInfo.java
Log Message:
initial checkin
--- NEW FILE: ActionTag.java ---
package com.tablelib.tags;
import javax.servlet.jsp.tagext.BodyTagSupport;
import javax.servlet.jsp.JspException;
/**
* Created by IntelliJ IDEA.
* User: simps
* Date: Feb 1, 2003
* Time: 12:57:26 PM
*
* The actionTag is "verb" in the statmement created by each columnTag.
*
*/
public class ActionTag extends BodyTagSupport implements Cloneable {
private String href;
private String actionCommand;
public String getHref() {
return href;
}
public void setHref(String href) {
this.href = href;
}
public String getActionCommand() {
return actionCommand;
}
public void setActionCommand(String actionCommand) {
this.actionCommand = actionCommand;
}
/**
* The TableTag will still be the work horse in this library. The action tag
* will still propigate through the Columntag to the TableTag.
*
* @throws javax.servlet.jsp.JspException if this tag is being used outside of a
* <tablelib:column> tag.
**/
public int doEndTag() throws JspException {
final Object column = this.getParent();
if (column == null || column instanceof ColumnTag == false) {
throw new JspException(
"Can not use an action tag outside of a Columntag. "+
"Invalid parent = "+column.getClass().getName());
}
try {
ColumnTag columnTag = (ColumnTag) column;
columnTag.setAction((ActionTag)this.clone());
} catch (CloneNotSupportedException e) {
throw new JspException(e);
}
return super.doEndTag();
}
}
--- NEW FILE: ColumnDecorator.java ---
/**
* $Id: ColumnDecorator.java,v 1.1 2003/07/18 13:19:57 javabencom Exp $
*
* Status: Ok
**/
package com.tablelib.tags;
public abstract class ColumnDecorator extends DecoratorImpl {
public ColumnDecorator() {
super();
}
public abstract String decorate(Object columnValue);
}
--- NEW FILE: ColumnTag.java ---
/**
* This tag has undergone only minor changes. It was renamed to ensure that there
would be
* no conflict with the original org.apache.taglib.display.ColumnTag
*
* Minor Changes:
* Cleaned up the get Cell Attributes call.
* <li>It could use more refactoring to consider reusing a buffer</li>
* <li>Caching the results to avoid reprocessing during a request</li>
*/
/**
* $Id: ColumnTag.java,v 1.1 2003/07/18 13:19:57 javabencom Exp $
*
* Todo:
* - provide filters in some way? Instead of just getting some bit of data
* also provide a way to feed that data through some other object that
* will reformat it in some way (like converting dates to another format)
* - update documentation, HTML column attributes are not set.
* - specify groupings.
* - error checking, value or property must be set.
**/
package com.tablelib.tags;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.BodyTagSupport;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Attributes:<p>
*
* property - the property method that is called to retrieve the
* information to be displayed in this column. This method
* is called on the current object in the iteration for
* the given row. The property format is in typical struts
* format for properties (required)
*
* title - the title displayed for this column. if this is omitted
* then the property name is used for the title of the column
* (optional)
*
* width - the width of the column (gets passed along to the html
* td tag). (optional)
*
* group - the grouping level (starting at 1 and incrementing) of
* this column (indicates if successive contain the same
* values, then they should not be displayed). The level
* indicates that if a lower level no longer matches, then
* the matching for this higher level should start over as
* well. If this attribute is not included, then no grouping
* is performed. (optional)
*
* decorator - a class that should be used to "decorate" the underlying
* object being displayed. If a decorator is specified for
* the entire table, then this decorator will decorate that
* decorator. (optional)
*
* autolink - if set to true, then any email addresses and URLs found
* in the content of the column are automatically converted
* into a hypertext link.
*
*
*
* maxLength - If this attribute is provided, then the column's displayed
* is limited to this number of characters. An elipse (...)
* is appended to the end if this column is linked, and the
* user can mouseover the elipse to get the full text.
* (optional)
*
* maxWords - If this attribute is provided, then the column's displayed
* is limited to this number of words. An elipse (...) is
* appended to the end if this column is linked, and the user
* can mouseover the elipse to get the full text. (optional)
*/
public class ColumnTag extends BodyTagSupport implements Cloneable {
private String property;
private String title;
private String sort;
boolean doLink;
private String group; /* If this property is set then the values have to be
grouped */
private String paramId;
private String paramName;
private String paramProperty;
private int paramScope;
private int maxLength;
private int maxWords;
private String width;
private String align;
private String background;
private String bgcolor;
private String height;
private String nowrap;
private String valign;
private String clazz;
private String headerClazz;
private String doubleQuote;
private String decorator;
public void setProperty(final String v) {
this.property = v;
}
public void setTitle(final String v) {
this.title = v;
}
public void setSort(final String v) {
this.sort = v;
}
public void setAutolink(final String v) {
doLink = v.equals("true");
}
public void setGroup(final String v) {
this.group = v;
}
public void setParamId(final String v) {
this.paramId = v;
}
public void setParamName(final String v) {
this.paramName = v;
}
public void setParamProperty(final String v) {
this.paramProperty = v;
}
public void setParamScope(String parm) {
if (parm == null)
paramScope = PageContext.REQUEST_SCOPE;
else if ((parm = parm.toLowerCase()).equals("request"))
paramScope = PageContext.REQUEST_SCOPE;
else if (parm.equals("session"))
paramScope = PageContext.SESSION_SCOPE;
else if (parm.equals("application"))
paramScope = PageContext.APPLICATION_SCOPE;
else
paramScope = PageContext.PAGE_SCOPE;
}
public void setMaxLength(final int v) {
this.maxLength = v;
}
public void setMaxWords(final int v) {
this.maxWords = v;
}
public void setWidth(final String v) {
this.width = v;
}
public void setAlign(final String v) {
this.align = v;
}
public void setBackground(final String v) {
this.background = v;
}
public void setBgcolor(final String v) {
this.bgcolor = v;
}
public void setHeight(final String v) {
this.height = v;
}
public void setNowrap(final String v) {
this.nowrap = v;
}
public void setValign(final String v) {
this.valign = v;
}
public void setStyleClass(final String v) {
this.clazz = v;
}
public void setHeaderStyleClass(final String v) {
this.headerClazz = v;
}
public void setDoubleQuote(final String v) {
this.doubleQuote = v;
}
public void setDecorator(final String v) {
this.decorator = v;
}
public String getProperty() {
return this.property;
}
public String getTitle() {
return this.title;
}
public String getSort() {
return this.sort;
}
public String getGroup() {
return this.group;
}
public String getParamId() {
return this.paramId;
}
public String getParamName() {
return this.paramName;
}
public String getParamProperty() {
return this.paramProperty;
}
public int getParamScope() {
return this.paramScope;
}
public int getMaxLength() {
return this.maxLength;
}
public int getMaxWords() {
return this.maxWords;
}
public String getWidth() {
return this.width;
}
public String getAlign() {
return this.align;
}
public String getBackground() {
return this.background;
}
public String getBgcolor() {
return this.bgcolor;
}
public String getHeight() {
return this.height;
}
public String getNowrap() {
return this.nowrap;
}
public String getValign() {
return this.valign;
}
public String getStyleClass() {
return this.clazz;
}
public String getHeaderStyleClass() {
return this.headerClazz;
}
public String getDoubleQuote() {
return this.doubleQuote;
}
public String getDecorator() {
return this.decorator;
}
private List actions = Collections.EMPTY_LIST;
public List getActions() {
return actions;
}
public void setAction(ActionTag action) {
if(this.actions.isEmpty()) this.actions = new ArrayList(5);
this.actions.add(action);
}
// --------------------------------------------------------- Tag API methods
/**
* Passes attribute information up to the parent TableTag.<p>
*
* When we hit the end of the tag, we simply let our parent (which better
* be a TableTag) know what the user wants to do with this column.
* We do that by simple registering this tag with the parent. This tag's
* only job is to hold the configuration information to describe this
* particular column. The TableTag does all the work.
*
* @throws javax.servlet.jsp.JspException if this tag is being used outside of a
* <display:list...> tag.
**/
public int doEndTag() throws JspException {
final Object parent = this.getParent();
if (parent == null || parent instanceof TableTag == false) {
throw new JspException("Can not use column tag outside of a " +
"TableTag. Invalid parent = " +
parent.getClass().getName());
}
// Need to clone the ColumnTag before passing it to the TableTag as
// the ColumnTags can be reused by some containers, and since we are
// using the ColumnTags as basically containers of data, we need to
// save the original values, and not the values that are being changed
// as the tag is being reused...
/** tucked the add column into the try block. **/
try {
((TableTag) parent).addColumn(this.clone());
} catch (CloneNotSupportedException e) {
throw new JspException(e);
} // shouldn't happen...
return super.doEndTag();
}
/**
* Takes all the column pass-through arguments and bundles them up as a
* string that gets tacked on to the end of the td tag declaration.<p>
**/
private static final String DEF_CLAZZ_STR = " class=\"tableCell\"";
private static final String DEF_VALIGNMENT = " valign=\"top\"";
private static final String DEF_ALIGNMENT = " align=\"left\"";
public String getCellAttributes() {
final StringBuffer results = new StringBuffer(256);
if (this.clazz == null)
results.append(DEF_CLAZZ_STR);
else {
results.append(" class=\"");
results.append(this.clazz);
results.append("\"");
}
if (this.width != null) {
results.append(" width=\"");
results.append(this.width);
results.append("\"");
}
if (this.align == null)
results.append(DEF_ALIGNMENT);
else {
results.append(" align=\"");
results.append(this.align);
results.append("\"");
}
if (this.background != null) {
results.append(" background=\"");
results.append(this.background);
results.append("\"");
}
if (this.bgcolor != null) {
results.append(" bgcolor=\"");
results.append(this.bgcolor);
results.append("\"");
}
if (this.height != null) {
results.append(" height=\"");
results.append(this.height);
results.append("\"");
}
if (this.nowrap != null) {
results.append(" nowrap");
}
if (this.valign == null)
results.append(DEF_VALIGNMENT);
else {
results.append(" valign=\"");
results.append(this.valign);
results.append("\"");
}
return results.toString();
}
}
--- NEW FILE: Decorator.java ---
/**
* This file has changed from it's original format. The current purpose for a
decorator is it's original stated purpose in the
* infamous book Design Patterns / Elements of reuses (Gang of 4)
*
* Intent of a decorator: "Attach additional responsibilities to an object
dynamically..."
*
* Use in this package: "Provide a signature for implementation classes to 'attach
additional information to
* an object dynamically'"
*
* @author Ben Simpson
* Date: Jan 30, 2003
*
*/
package com.tablelib.tags;
import java.util.Comparator;
public interface Decorator {
/**
* This method will take an object and transform it according to it's
implementation.
* @param obj
* @return
*/
public Object decorate(Object obj);
}
--- NEW FILE: DecoratorImpl.java ---
/**
* $Id: DecoratorImpl.java,v 1.1 2003/07/18 13:19:57 javabencom Exp $
*
* Status: Ok
*
* Todo
* - push the appropriate stuff down into TableDecorator
**/
package com.tablelib.tags;
import javax.servlet.jsp.PageContext;
import java.util.List;
/**
* This class provides some basic functionality for all objects which serve
* as decorators for the objects in the List being displayed.
**/
public abstract class DecoratorImpl implements Decorator {
private PageContext ctx = null;
private List list = null;
private Object obj = null;
private int viewIndex = -1;
private int listIndex = -1;
public DecoratorImpl() {
}
public void init(final PageContext ctx, final List list) {
this.ctx = ctx;
this.list = list;
}
public String initRow(final Object obj, final int viewIndex, final int listIndex) {
this.obj = obj;
this.viewIndex = viewIndex;
this.listIndex = listIndex;
return "";
}
public String finishRow() {
return "";
}
public void finish() {
}
public PageContext getPageContext() {
return this.ctx;
}
public List getList() {
return this.list;
}
public Object getObject() {
return this.obj;
}
public int getViewIndex() {
return this.viewIndex;
}
public int getListIndex() {
return this.listIndex;
}
}
--- NEW FILE: PagingInformation.java ---
/**
* Software by JavaBen
* User: Ben Simpson
* Date: Feb 2, 2003
* Time: 7:07:44 PM
*/
package com.tablelib.tags;
public interface PagingInformation {
/**
* This is a work in progress. The pattern that has worked for me so far is to
* incorporate much of what was done to the display tag library by Ed Hill. Get
that to
* work in this environment, then start taking out the redundancies. :)
* @return
*/
public String getSearchResultsSummary();
/**
* @param url
* @return
*/
public String getPageNavigationBar(String url);
}
--- NEW FILE: PaginigInformationImpl.java ---
package com.tablelib.tags;
import com.tablelib.core.net.NetUtils;
import java.text.MessageFormat;
import java.util.List;
import java.util.Properties;
/**
* Created by IntelliJ IDEA.
* User: simps
* Date: Feb 1, 2003
* Time: 2:53:43 PM
*/
public class PaginigInformationImpl implements PagingInformation {
private int currentPage;
private int pageSize;
private int pageCount;
private int listSize;
private Properties prop;
private int[] ints;
public PaginigInformationImpl(final Properties props,
final List pList,
final int pCurrentPage,
final int pPageSize
) {
this.prop = props;
this.pageSize = pPageSize;
this.currentPage = pCurrentPage;
this.listSize = pList.size();
computePageCount();
}
/**
* Returns the computed number of pages it would take to show all the
* elements in the list given the pageSize we are working with.
*
* This function was taken in whole from the Display Tag Library Smart Page Helper
*/
void computePageCount() {
if (pageSize == 0) {
pageCount = 0;
return;
}
final int div = listSize / this.pageSize;
pageCount = listSize % this.pageSize == 0 ? div : div + 1;
this.ints = new int[pageCount + 1];
for (int i = 1; i <= pageCount; i++) ints[i] = i;
}
/**
* This is a work in progress. The pattern that has worked for me so far is to
* incorporate much of what was done to the display tag library by Ed Hill. Get
that to
* work in this environment, then start taking out the redundancies. :)
* // @todo
* @return
*/
public String getSearchResultsSummary() {
final StringBuffer buff = new StringBuffer(256);
if (listSize < 2) {
if (listSize == 0)
buff.append(prop.getProperty("paging.banner.no_items_found"));
else
buff.append(prop.getProperty("paging.banner.one_item_found"));
return
buff.append(prop.getProperty("paging.banner.items_name")).toString();
} else if ((currentPage - 1) * this.pageSize ==
this.getLastIndexForCurrentPage()) {
final Object[] objs = {new Integer(listSize),
prop.getProperty("paging.banner.items_name"),
prop.getProperty("paging.banner.items_name")};
return MessageFormat.format(
prop.getProperty("paging.banner.all_items_found"), objs);
} else {
final Object[] objs = {new Integer(listSize),
prop.getProperty("paging.banner.items_name"),
new Integer((currentPage - 1) * this.pageSize),
new Integer(this.getLastIndexForCurrentPage() + 1)};
return MessageFormat.format(
prop.getProperty("paging.banner.some_items_found"), objs);
}
}
protected int getLastIndexForCurrentPage() {
final int firstIndex = (currentPage - 1) * this.pageSize;
final int pageIndex = this.pageSize - 1;
final int lastIndex = this.listSize - 1;
return Math.min(firstIndex + pageIndex, lastIndex);
}
/**
* @param url
* @return
*/
public String getPageNavigationBar(final String url) {
if (pageCount < 2) return "<b>1</b>";
final int maxPages = this.pageCount > 8 ? 8 : this.pageCount;
final StringBuffer retBuff = new StringBuffer(url.length() * maxPages *
2).append("<b>[");
retBuff.append((this.currentPage > 1 ? makeFirst(url) : "First")).append(" ");
retBuff.append((this.currentPage > 1 ? makePrevious(url) : "Prev")).append("]
");
appendIntsToBuff(retBuff, maxPages, url);
retBuff.append(" [").append((this.currentPage < pageCount ? makeNext(url) :
"Next")).append(" ");
retBuff.append((this.currentPage < pageCount ? makeLast(url) :
"Last")).append("] </b>");
return retBuff.toString();
}
/**
* Parts of this algorithm were taken from the SmartListHelper class in Ed Hill's
* Display tag library.
*
* @param buff
* @param maxPagesToShow
* @param url
*/
private void appendIntsToBuff(final StringBuffer buff, final int maxPagesToShow,
final String url) {
int startInt = currentPage < maxPagesToShow ? 1 : currentPage;
final int endInt;
if (currentPage < maxPagesToShow) {
endInt = pageCount < maxPagesToShow ? pageCount : maxPagesToShow;
} else {
final int pc = pageCount + 1;
while (startInt + maxPagesToShow > pc) startInt--;
endInt = startInt + maxPagesToShow - 1;
}
for (int i = startInt; i <= endInt; i++) {
if (i != startInt) buff.append(", ");
buff.append(makeNumberedLink(url, i));
}
}
private static final String makeFirst(final String url) {
return NetUtils.wrapLink(url + 1, null, "First");
}
private String makePrevious(final String url) {
return NetUtils.wrapLink(url + (currentPage - 1), null, "Prev");
}
/**
* This method focuses on making only the Next link in the
* navigation header bar
* @param url
* @return
*/
private String makeNext(final String url) {
return NetUtils.wrapLink(url + (currentPage + 1), null, "Next");
}
/**
* This method focuses on making only the "Last Link" from the navigation
* header
* @param url
* @return
*/
private String makeLast(final String url) {
return NetUtils.wrapLink(url + this.pageCount, null, "Last");
}
/**
* This is the method where the general numbered links in the
* navigation header bar will be made.
* @param url
* @param n
* @return
*/
private String makeNumberedLink(final String url, final int n) {
if (n == currentPage) return String.valueOf(n);
return NetUtils.wrapLink(url + n, null, n);
}
}
--- NEW FILE: SearchTag.java ---
/**
* Software by JavaBen
* User: Ben Simpson
* Date: Feb 18, 2003
* Time: 8:39:39 AM
*/
package com.tablelib.tags;
import com.tablelib.core.taglibs.BaseTag;
/**
* This class follows the same algorithm that the Table Tag follows except for the
following:
* <ul><li>It has an embedded search field (optional).
*/
public class SearchTag extends BaseTag {
/**
* <tablelib:table name:=\"tablename\" key=\"list\">
* <tablelib:search properties(titles or properties) />
* <tablelib:column property=\"propName\" title=\"tname\" sortable />
* <tablelib:column property=\"propNameTwo\" title=\"tnameTwo\" />
* <tablelib:column proprty=\"id\">
* <tablelib:column proprty=\"imageUrl\">
* <tablelib:image width=\"200\" height=\"200\">
* <tablelib:action href=\"view.do?id=\" />
* </tablelib:image>
* </tablelib:column>
* <tablelib:action href=\"delete.do?id=\" command=\"delete\"/>
* <tablelib:action href=\"edit.do?id=\" command=\"edit\"/>
* </tablelib:column>
* </tablelib>
*
*/
}
--- NEW FILE: SetPropertyTag.java ---
/**
* $Id: SetPropertyTag.java,v 1.1 2003/07/18 13:19:57 javabencom Exp $
*
* Status: Under Development
*
* Todo
* - implementation
* - documentation (javadoc, examples, etc...)
* - junit test cases
**/
package com.tablelib.tags;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;
/**
* One line description of what this class does.
*
* More detailed class description, including examples of usage if applicable.
**/
public class SetPropertyTag extends BodyTagSupport implements Cloneable {
private String name;
private String value;
public void setName(String v) {
this.name = v;
}
public void setValue(String v) {
this.value = v;
}
public String getName() {
return this.name;
}
public String getValue() {
return this.value;
}
// --------------------------------------------------------- Tag API methods
/**
* Passes attribute information up to the parent TableTag.<p>
*
* When we hit the end of the tag, we simply let our parent (which better
* be a TableTag) know what the user wants to change a property value, and
* we pass the name/value pair that the user gave us, up to the parent
*
* @throws javax.servlet.jsp.JspException if this tag is being used outside of a
* <display:list...> tag.
**/
public int doEndTag() throws JspException {
Object parent = this.getParent();
if (parent == null) {
throw new JspException("Can not use column tag outside of a " +
"TableTag. Invalid parent = null");
}
if (!(parent instanceof TableTag)) {
throw new JspException("Can not use column tag outside of a " +
"TableTag. Invalid parent = " +
parent.getClass().getName());
}
((TableTag) parent).setProperty(this.name, this.value);
return super.doEndTag();
}
}
--- NEW FILE: SmartListHelper.java ---
/**
* $Id: SmartListHelper.java,v 1.1 2003/07/18 13:19:57 javabencom Exp $
*
* Status: Under Development
**/
package com.tablelib.tags;
import com.tablelib.core.lang.NumberUtils;
import com.tablelib.core.net.NetUtils;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
/**
* This is a little utility class that the SmartListTag uses to chop up a
* List of objects into small bite size pieces that are more suitable for
* display.
*
* This class is a stripped down version of the WebListHelper that we got
* from Tim Dawson ([EMAIL PROTECTED])
*/
class SmartListHelper extends Object {
private List masterList;
private int pageSize;
private int pageCount;
private int currentPage;
private Properties prop = null;
/**
* Creates a SmarListHelper instance that will help you chop up a list
* into bite size pieces that are suitable for display.
*/
protected SmartListHelper(List list, int pageSize, Properties prop) {
if (list == null || pageSize < 1) {
throw new IllegalArgumentException("Bad arguments passed into " +
"SmartListHelper() constructor");
}
this.prop = prop;
this.pageSize = pageSize;
this.masterList = list;
this.pageCount = this.computedPageCount();
this.currentPage = 1;
}
/**
* Returns the computed number of pages it would take to show all the
* elements in the list given the pageSize we are working with.
*/
protected int computedPageCount() {
int result = 0;
if ((this.masterList != null) && (this.pageSize > 0)) {
int size = this.masterList.size();
int div = size / this.pageSize;
int mod = size % this.pageSize;
result = (mod == 0) ? div : div + 1;
}
return result;
}
/**
* Returns the index into the master list of the first object that
* should appear on the current page that the user is viewing.
*/
protected int getFirstIndexForCurrentPage() {
return this.getFirstIndexForPage(this.currentPage);
}
/**
* Returns the index into the master list of the last object that should
* appear on the current page that the user is viewing.
*/
protected int getLastIndexForCurrentPage() {
return this.getLastIndexForPage(this.currentPage);
}
/**
* Returns the index into the master list of the first object that
* should appear on the given page.
*/
protected int getFirstIndexForPage(int page) {
return ((page - 1) * this.pageSize);
}
/**
* Returns the index into the master list of the last object that should
* appear on the given page.
*/
protected int getLastIndexForPage(int page) {
int firstIndex = this.getFirstIndexForPage(page);
int pageIndex = this.pageSize - 1;
int lastIndex = this.masterList.size() - 1;
return Math.min(firstIndex + pageIndex, lastIndex);
}
/**
* Returns a subsection of the list that contains just the elements that
* are supposed to be shown on the current page the user is viewing.
*/
protected List getListForCurrentPage() {
return this.getListForPage(this.currentPage);
}
/**
* Returns a subsection of the list that contains just the elements that
* are supposed to be shown on the given page.
*/
protected List getListForPage(int page) {
List list = new ArrayList(this.pageSize + 1);
int firstIndex = this.getFirstIndexForPage(page);
int lastIndex = this.getLastIndexForPage(page);
for (int i = firstIndex; i <= lastIndex; i++) {
list.add(this.masterList.get(i));
}
return list;
}
/**
* Set's the page number that the user is viewing.
*
* @throws java.lang.IllegalArgumentException if the page provided is invalid.
*/
protected void setCurrentPage(int page) {
if (page < 1 || page > this.pageCount) {
Object[] objs = {new Integer(page), new Integer(pageCount)};
throw new IllegalArgumentException(
MessageFormat.format(prop.getProperty("error.msg.invalid_page"),
objs));
}
this.currentPage = page;
}
/**
* Return the little summary message that lets the user know how many
* objects are in the list they are viewing, and where in the list they
* are currently positioned. The message looks like:
*
* nnn <item(s)> found, displaying nnn to nnn.
*
* <item(s)> is replaced by either itemName or itemNames depending on if
* it should be signular or plurel.
*/
protected String getSearchResultsSummary() {
if (this.masterList.size() == 0) {
Object[] objs = {prop.getProperty("paging.banner.items_name")};
return MessageFormat.format(
prop.getProperty("paging.banner.no_items_found"), objs);
} else if (this.masterList.size() == 1) {
Object[] objs = {prop.getProperty("paging.banner.item_name")};
return MessageFormat.format(
prop.getProperty("paging.banner.one_item_found"), objs);
} else if (this.getFirstIndexForCurrentPage() ==
this.getLastIndexForCurrentPage()) {
Object[] objs = {new Integer(this.masterList.size()),
prop.getProperty("paging.banner.items_name"),
prop.getProperty("paging.banner.items_name")};
return MessageFormat.format(
prop.getProperty("paging.banner.all_items_found"), objs);
} else {
Object[] objs = {new Integer(this.masterList.size()),
prop.getProperty("paging.banner.items_name"),
new Integer(this.getFirstIndexForCurrentPage() + 1),
new Integer(this.getLastIndexForCurrentPage() + 1)};
return MessageFormat.format(
prop.getProperty("paging.banner.some_items_found"), objs);
}
}
/**
* Returns a string containing the nagivation bar that allows the user
* to move between pages within the list.
*
* The urlFormatString should be a URL that looks like the following:
*
* http://.../somepage.page?page={0}
*/
protected String getPageNavigationBar(String urlFormatString) {
MessageFormat form = new MessageFormat(urlFormatString);
int maxPages =
NumberUtils.parseInt(prop.getProperty("paging.banner.group_size"), 8);
int currentPage = this.currentPage;
int pageCount = this.pageCount;
int startPage = 1;
int endPage = maxPages;
if (pageCount == 1 || pageCount == 0) {
return "<b>1</b>";
}
if (currentPage < maxPages) {
startPage = 1;
endPage = maxPages;
if (pageCount < endPage) {
endPage = pageCount;
}
} else {
startPage = currentPage;
while (startPage + maxPages > (pageCount + 1)) {
startPage--;
}
endPage = startPage + (maxPages - 1);
}
boolean includeFirstLast =
prop.getProperty("paging.banner.include_first_last").equals("true");
String msg = "";
if (currentPage == 1) {
if (includeFirstLast) {
msg += "[" + prop.getProperty("paging.banner.first_label") +
"/" + prop.getProperty("paging.banner.prev_label") + "] ";
} else {
msg += "[" + prop.getProperty("paging.banner.prev_label") + "] ";
}
} else {
Object[] objs = {new Integer(currentPage - 1)};
Object[] v1 = {new Integer(1)};
if (includeFirstLast) {
msg += "[<a href=\"" + form.format(v1) + "\">" +
prop.getProperty("paging.banner.first_label") + "</a>/<a
href=\"" +
form.format(objs) + "\">" +
prop.getProperty("paging.banner.prev_label") + "</a>] ";
} else {
msg += "[" + NetUtils.wrapLink(form.format(objs), "",
prop.getProperty("paging.banner.prev_label")) + "]";
}
}
for (int i = startPage; i <= endPage; i++) {
msg += i == currentPage ? "<b>" + i + "</b>" :
NetUtils.wrapLink(form.format(new Object[]{i + ""}), "", i + "");
msg += i != endPage ? ", " : " ";
}
if (currentPage == pageCount) {
if (includeFirstLast) {
msg += "[" + prop.getProperty("paging.banner.next_label") +
"/" + prop.getProperty("paging.banner.last_label") + "] ";
} else {
msg += "[" + prop.getProperty("paging.banner.next_label") + "] ";
}
} else {
Object[] objs = {new Integer(currentPage + 1)};
Object[] v1 = {new Integer(pageCount)};
if (includeFirstLast) {
msg += "[<a href=\"" + form.format(objs) + "\">" +
prop.getProperty("paging.banner.next_label") + "</a>/<a
href=\"" +
form.format(v1) + "\">" +
prop.getProperty("paging.banner.last_label") + "</a>] ";
} else {
msg += "[<a href=\"" + form.format(objs) + "\">" +
prop.getProperty("paging.banner.next_label") + "</a>] ";
}
}
return msg;
}
}
--- NEW FILE: TableDecorator.java ---
/**
* $Id: TableDecorator.java,v 1.1 2003/07/18 13:19:57 javabencom Exp $
*
* Status: Ok
*
* Todo:
* - setup the correct deprecation rules, so that people know to extend
* this class, rather then the Decorator class.
**/
package com.tablelib.tags;
public class TableDecorator extends DecoratorImpl {
public TableDecorator() {
super();
}
}
--- NEW FILE: TableExporter.java ---
/**
* Created by IntelliJ IDEA.
* User: Benjamin Simpson
* Date: Jan 11, 2003
* Time: 8:44:51 PM
*/
package com.tablelib.tags;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyTag;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import com.tablelib.core.lang.StringUtils;
/**
* The class TableExporter is the encapsulation the routine
* of formatting and sending the table data back via the response.
* The data is typed by the named values in the Download types array.
*
* The types seem pretty solid for now, so they dont need to be grabbed from
* a configuration file.
*
* The routines themselves are based upon the data processing methods once found
* in the display tag library by Ed Hill
(http://edhill.its.uiowa.edu/display-docs-0.8/).
*
* The emphasis on this refactoring was not speed as much as maintainability. It is
the intent of
* this programmer to come back and do the following:
*
*/
public final class TableExporter {
public static final int EXPORT_TYPE_NONE = -1;
public static final int EXPORT_TYPE_CSV = 0;
public static final int EXPORT_TYPE_EXCEL = 1;
public static final int EXPORT_TYPE_XML = 2;
private static final String[] DOWNLOAD_TYPES = new String[]{ "text/csv",
"application/vnd.ms-excel", "text/xml" };
private static final char[] EOL_TYPES = new char[]{ '\n', '\n', '\n' };
private static final char[] DELIM_TYPES = new char[]{ ',', 't', '\n' };
/**
*
* @param type
* @param tag
* @param data
* @return Tag.SKIP_BODY
* @throws Exception
*/
public static int export(final int type, final TableTag tag, final List data)
throws Exception {
final JspWriter out = tag.getOut();
out.clear();
tag.getResponse().setContentType(DOWNLOAD_TYPES[type]);
out.write(type == EXPORT_TYPE_CSV ? getRawData(data, tag) :
type == EXPORT_TYPE_EXCEL ? getExcelData(data, tag) :
getXMLData(data, tag)
);
out.flush();
return BodyTag.SKIP_PAGE;
}
/**
* This returns a table of data in XML format
*
* FIXME - this obviously needs cleaned up...
*/
private static String getXMLData(final List rows, final TableTag tableTag) throws
JspException {
final StringBuffer buf = new StringBuffer(8000);
final List columns = tableTag.columns;
int rowcnt = 0;
buf.append("<table>\n");
for (Iterator it = rows.iterator(); it.hasNext();) {
Object obj = it.next();
tableTag.setPageContextAttribute("smartRow", obj);
buf.append("<row>\n");
Object value;
for (int i = 0, len = columns.size(); i < len; i++) {
ColumnTag tag = (ColumnTag) columns.get(i);
value = tag.getProperty().equals("table_index") ?
String.valueOf(rowcnt) :
tableTag.lookup("smartRow", tag.getProperty(),
tableTag.scope);
if (value == null) value = "";
// TODO - need to escape this or something...
buf.append("<column>" + value + "</column>\n");
}
rowcnt++;
buf.append("</row>\n");
}
return buf.append("</table>\n").toString();
}
/**
* This returns a table of data in Excel format
*/
private static final char xls_delim = '\t';
private static final char xls_eol = '\n';
private static String getExcelData(final List rows, final TableTag tableTag)
throws JspException {
final ArrayList lines = new ArrayList(rows.size()+1);
final char eol = xls_eol;
final char delim = xls_delim;
final int colsSize = tableTag.columns.size();
lines.add(getHeaderBuffer(EXPORT_TYPE_EXCEL,colsSize,tableTag));
for(int rowcnt = 0, len = rows.size(); rowcnt < len; rowcnt++) {
Object row = rows.get(rowcnt);
StringBuffer buf = new StringBuffer(256);
// if (decorated && tableTag.dec != null) {
// buf.append(tableTag.dec.initRow(row, rowcnt, rowcnt +
tableTag.getOffsetValue()));
// }
tableTag.setPageContextAttribute("smartRow", row);
for (int i = 0; i < colsSize; i++) {
ColumnTag tag = (ColumnTag) tableTag.columns.get(i);
Object value = null;
String prop = tag.getProperty();
if(prop.equals("table_index")) value = String.valueOf(rowcnt);
else value = tableTag.lookup("smartRow",prop, tableTag.scope);
if (value == null) value = "";
if (tag.getDoubleQuote() != null) value = "\"" + value + "\"";
buf.append(value);
if (colsSize > (i + 1)) buf.append(delim);
}
lines.add(buf.toString().trim());
}
return StringUtils.delimit(lines.toArray(),eol);
}
private static String getRawData(final List rows, final TableTag tableTag) throws
JspException {
final ArrayList lines = new ArrayList(rows.size() +1);
final int colsSize = tableTag.columns.size();
final StringBuffer buf = new StringBuffer(8000);
lines.add(getHeaderBuffer(EXPORT_TYPE_CSV,colsSize,tableTag));
for(int rowcnt = 0, len = rows.size(); rowcnt < len; rowcnt++) {
Object row = rows.get(rowcnt);
//if (decorated && tableTag.dec != null) {
// String rt = tableTag.dec.initRow(row, rowcnt, rowcnt +
tableTag.getOffsetValue());
// if (rt != null) buf.append(rt);
// }
tableTag.setPageContextAttribute("smartRow", row);
for (int i = 0; i < colsSize; i++) {
ColumnTag tag = (ColumnTag) tableTag.columns.get(i);
Object value = null;
String prop = tag.getProperty();
if(prop.equals("table_index")) value = String.valueOf(rowcnt);
else value = tableTag.lookup("smartRow",prop, tableTag.scope);
if (value == null) value = "";
if (tag.getDoubleQuote() != null) value = "\"" + value + "\"";
buf.append(value);
if (colsSize > (i + 1)) buf.append(DELIM_TYPES[EXPORT_TYPE_CSV]);
}
lines.add(buf.append(EOL_TYPES[EXPORT_TYPE_CSV]).toString());
rowcnt++;
}
return buf.toString();
}
/**
* Processor utilities
*/
private static final String getHeaderBuffer(final int typeOfExport, final int
colsSize, final TableTag tableTag) {
final String [] headers = new String [colsSize];
final ColumnTag [] cols = new ColumnTag[colsSize];
tableTag.columns.toArray(cols);
String tmp;
for(int i = 0; i < colsSize; i++) {
headers[i] = (tmp = cols[i].getTitle()) == null ? cols[i].getProperty() :
tmp;
}
return StringUtils.delimit(headers,DELIM_TYPES[typeOfExport]);
}
}
--- NEW FILE: TableImpl.java ---
/**
* Created by IntelliJ IDEA.
* User: Benjamin Simpson
* Date: Jan 11, 2003
* Time: 8:44:51 PM
*/
package com.tablelib.tags;
import com.tablelib.core.table.Table;
public class TableImpl implements Table {
private Object key = null;
private int width = 100;
private boolean isWidthPercentage = true;
private int height = -1;
private String backGround = null;
private int border = 0;
private int cellPadding = -1;
private int cellSpacing = -1;
private int hSpace = -1;
private int vSpace = -1;
private String bgColor = "#FFFFFF";
public void declareTable(final StringBuffer buff) {
buff.append("\n<table class=\"table\"");
buff.append(" width=\"").append(this.width);
if (isWidthPercentage) buff.append('%');
buff.append('\"');
buff.append(" border=\"").append(this.border).append('\"');
if (this.cellSpacing > 0)
buff.append(" cellspacing=\"").append(this.cellSpacing).append('\"');
if (this.cellPadding > 0)
buff.append(" cellpadding=\"").append(this.cellPadding).append('\"');
if (this.backGround != null)
buff.append(" background=\"").append(this.backGround).append("\"");
if (this.bgColor != null)
buff.append(" bgcolor=\"").append(this.bgColor).append("\"");
if (this.height > 0)
buff.append(" height=\"").append(this.height).append("\"");
if (this.hSpace > 0)
buff.append(" hspace=\"").append(this.hSpace).append("\"");
if (this.vSpace > 0)
buff.append(" vspace=\"").append(this.vSpace).append("\"");
buff.append(" >\n");
}
public boolean isWidthPercentage() {
return isWidthPercentage;
}
public void setWidthIsPercentage(final boolean isPercentage) {
isWidthPercentage = isPercentage;
}
public Object getKey() {
return key;
}
public void setKey(final Object key) {
this.key = key;
}
public int getWidth() {
return width;
}
public void setWidth(final int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(final int height) {
this.height = height;
}
public String getBackGround() {
return backGround;
}
public void setBackGround(final String backGround) {
this.backGround = backGround;
}
public int getBorder() {
return border;
}
public void setBorder(final int border) {
this.border = border;
}
public int getCellPadding() {
return cellPadding;
}
public void setCellPadding(final int cellPadding) {
this.cellPadding = cellPadding;
}
public int getCellSpacing() {
return cellSpacing;
}
public void setCellSpacing(final int cellSpacing) {
this.cellSpacing = cellSpacing;
}
public int getHSpace() {
return hSpace;
}
public void setHSpace(final int hSpace) {
this.hSpace = hSpace;
}
public int getVSpace() {
return vSpace;
}
public void setVSpace(final int vSpace) {
this.vSpace = vSpace;
}
public String getBgColor() {
return bgColor;
}
public void setBgColor(final String bgColor) {
this.bgColor = bgColor;
}
}
--- NEW FILE: TableTag.java ---
/**
* Created by IntelliJ IDEA.
* User: Benjamin Simpson
* Date: Jan 11, 2003
* Time: 8:44:51 PM
*/
package com.tablelib.tags;
import com.tablelib.core.lang.ArrayUtils;
import com.tablelib.core.lang.NumberUtils;
import com.tablelib.core.lang.StringUtils;
import com.tablelib.core.net.NetUtils;
import com.tablelib.core.table.Table;
import com.tablelib.core.taglibs.BaseTag;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import java.text.MessageFormat;
import java.util.*;
import org.apache.commons.beanutils.BeanUtils;
public class TableTag extends BaseTag {
private static final boolean SORT_ORDER_DECENDING = true;
private static final boolean SORT_ORDER_ASCENDING = false;
private Table table = null;
public List columns;
private List list = null;
private String key = null;
private String property = null;
public int scope = PageContext.REQUEST_SCOPE;
private String pagesize = null;
private String export = null;
// Variables that get set by investigating the request parameters
private int sortColumn = -1;
private PaginigInformationImpl pagingInformation;
private boolean sortOrder = SORT_ORDER_ASCENDING;
private int pageNumber = 1;
private int exportType = TableExporter.EXPORT_TYPE_NONE;
public TableTag() {
this.table = new TableImpl();
}
public void setHeight(final int parm) {
table.setHeight(parm);
}
public void setWidth(String parm) {
table.setWidthIsPercentage(parm.indexOf("%") > -1);
parm = table.isWidthPercentage() ? parm.substring(0, parm.length() - 1) : parm;
table.setWidth(NumberUtils.parseInt(parm, -1));
}
public void setBorder(final int parm) {
table.setBorder(parm);
}
public void setCellspacing(final int parm) {
table.setCellSpacing(parm);
}
public void setCellpadding(final int parm) {
table.setCellPadding(parm);
}
public void setBackGround(final String parm) {
table.setBackGround(parm);
}
public void setBgColor(final String parm) {
table.setBgColor(parm);
}
public void setHSpace(final int parm) {
table.setHSpace(parm);
}
public void setVSpace(final int parm) {
table.setVSpace(parm);
}
public void setList(final Object obj) {
this.list = (List) obj;
}
public void setKey(final String parm) {
this.key = parm;
}
public void setProperty(final String parm) {
this.property = parm;
}
public void setScope(String parm) {
if (parm == null)
scope = PageContext.REQUEST_SCOPE;
else if ((parm = parm.toLowerCase()).equals("request"))
scope = PageContext.REQUEST_SCOPE;
else if (parm.equals("session"))
scope = PageContext.SESSION_SCOPE;
else if (parm.equals("application"))
scope = PageContext.APPLICATION_SCOPE;
else
scope = PageContext.PAGE_SCOPE;
}
public void setPagesize(final String parm) {
this.pagesize = parm;
}
public void setExport(final String parm) {
this.export = parm;
}
public Object getList() {
return this.list;
}
public String getProperty() {
return this.property;
}
public String getPagesize() {
return this.pagesize;
}
public void reset() {
this.pageNumber = 1;
this.sortColumn = 1;
}
private int parseInt(final String keyOrVal, final int def, final boolean negsOk) {
if (keyOrVal == null) return def; //if the key or value does not exist, do
the default!
int ret;
try {
ret = Integer.parseInt(keyOrVal);
} catch (NumberFormatException nfe) {
Integer obj = (Integer) pageContext.findAttribute(keyOrVal);
ret = obj == null ? 0 : obj.intValue();
}
return !negsOk && ret < 0 ? def : ret;
}
/**
* Returns the pagesize that the person provided as an int. If the user does
* not provide a pagesize, or we can't figure out what they are trying to tell
* us, then we default to 0.
*
* @return the maximum number of objects that should be shown on any one page
* when displaying the list. Setting this value also indicates that the
* person wants us to manage the paging of the list.
**/
private int getPagesizeValue() {
return parseInt(this.pagesize, 0, false);
}
/**
* This method is called by the columns themselves.
* This method was inherited from the display taglibrary.
* @param obj
*/
public void addColumn(final Object obj) {
columns.add(obj);
}
/**
* When the tag starts, we just initialize some of our variables, and do a
* little bit of error checking to make sure that the user is not trying
* to give us parameters that we don't expect.
**/
public int doStartTag() throws JspException {
columns = new ArrayList(10);
if (getParameter("page", "").length() > 0) {
this.pageNumber = NumberUtils.parseInt(getParameter("page"), 1);
}
if (getParameter("sort", "").length() > 0) {
this.sortColumn = NumberUtils.parseInt(getParameter("sort", "0"), 0);
this.sortOrder = getParameter("sort", "").equals("dec") ?
SORT_ORDER_DECENDING : SORT_ORDER_ASCENDING;
}
this.exportType = TableExporter.EXPORT_TYPE_NONE;
if (this.export != null) {
if (getParameter("exportType") != null) {
this.exportType = NumberUtils.parseInt(getParameter("exportType"),
TableExporter.EXPORT_TYPE_NONE);
}
}
return super.doStartTag();
}
/**
* Draw the table. This is the meat of the tag set.
* The method getHTMLData slice is the method that will actually
* draw the page. The rest will perform an export.
*/
public int doEndTag() throws JspException {
final List slice = getPageSlice();
try {
if (this.exportType == TableExporter.EXPORT_TYPE_NONE) {
write(getHTMLData(slice));
return EVAL_PAGE;
}
return TableExporter.export(this.exportType,
this,
getProperty("export.amount").equals("list") ? this.list : slice);
} catch (Exception e) {
throw new JspException(e.getMessage());
}
}
/**
* This returns a list of all of the data that will be displayed on the
* page via the table tag. This might include just a subset of the total
* data in the list due to to paging being active, or the user asking us
* to just show a subset, etc...<p>
*
* The list that is returned from here is not the original list, but it
* does contain references to the same objects in the original list, so that
* means that we can sort and reorder the list, but we can't mess with the
* data objects in the list.
*/
private List getPageSlice() {
if (this.list == null) {
this.list = getListData(key, property, scope);
if (this.list == null) {
this.list = Collections.EMPTY_LIST;
}
}
sortDataIfNeeded();
if (getParameter("sort") != null) {
if (!getProperty("sort.behavior").equals("page")) {
this.pageNumber = 1;
}
}
int pageSize = this.getPagesizeValue();
if(pageSize == 0) return list;
pagingInformation = new
PaginigInformationImpl(this.getProperties(),list,pageNumber,pageSize);
int start = pageSize * (pageNumber-1);
int listSize = list.size();
int end = start + pageSize;
if(end > listSize) end = listSize;
return start == 0 && end == listSize ? list : list.subList(start,end);
}
/**
* This method will sort the data in either ascending or decending order
* based on the user clicking on the column headers.
*/
private void sortDataIfNeeded() {
String prop = ((ColumnTag) columns.get(this.sortColumn == -1 ? 0 :
this.sortColumn)).getProperty();
try {
Object [] values = list.toArray();
ArrayUtils.sort(values,prop,this.sortOrder);
list = Arrays.asList(values);
} catch (Exception e) {
e.printStackTrace();
}
}
private Hashtable previousRow = null;
private Hashtable nextRow = null;
private String getRowClass(final int count) {
return count % 2 == 0 ? " class=\"tableRowOdd\"" : " class=\"tableRowEven\"";
}
private String getHTMLData(final List rows) throws Exception {
final int colsSize = this.columns.size();
final ArrayList lines = new ArrayList(rows.size() * colsSize);
/** This algrithm looks perishable :) **/
previousRow = new Hashtable(colsSize, 1f); // variables to hold the previous
row columns values.
nextRow = new Hashtable(colsSize, 1f); // variables to hold next row column
values.
lines.add(getTableHeader());
// this should be done earlier in the process: this will permit removal of
the trivial doendtag do one thing...
final Object[] colAttributes = ArrayUtils.accessValues(columns.toArray(),
"getCellAttributes", ColumnTag.class);
for (int rowcnt = 0, len = rows.size(); rowcnt < len; rowcnt++) {
/** this is our row: an expected type of data might be a
* Struts Form Bean an Object [] or a map.
* if a formbean we are expecting to be able to have access to the values.
*/
Object row = rows.get(rowcnt);
lines.add(new
StringBuffer("<tr").append(getRowClass(rowcnt)).append(">\n").toString());
for (int i = 0; i < colsSize; i++) {
StringBuffer colBuffer = new StringBuffer(256);
ColumnTag tag = (ColumnTag) this.columns.get(i);
colBuffer.append("<td ").append(colAttributes[i]).append(">");
String valueStr = getColumnValue(tag, row, rowcnt);
StringBuffer xsBuffer = new StringBuffer(64);
StringBuffer valBuffer = new StringBuffer(64);
final int valLength = valueStr == null ? (valueStr =
String.valueOf(valueStr)).length() : valueStr.length();
final int maxLength = tag.getMaxLength();
final int maxWords = tag.getMaxWords();
while ((maxLength > 0 && valLength > maxLength) || maxWords > 0) {
if (maxLength > 0 && valLength > maxLength) {
xsBuffer.append("..." + valueStr.substring(maxLength,
valLength));
valBuffer.append(valueStr.substring(0, maxLength));
break;
}
if (maxWords > 0) {
final StringTokenizer st = new StringTokenizer(valueStr);
final int numTokens = st.countTokens();
if (numTokens <= maxWords) break;
for (int x = 0; x < maxWords; x++) {
if (!st.hasMoreTokens()) continue;
valBuffer.append(st.nextToken() + " ");
}
if (st.hasMoreTokens()) {
xsBuffer.append("...");
while (st.hasMoreTokens())
xsBuffer.append(st.nextToken()).append(" ");
}
break;
}
}
boolean chopped = xsBuffer.length() > 0;
if (tag.doLink && !chopped)
valBuffer.append(NetUtils.autolink(valueStr.toString()));
if (tag.getGroup() != null) {
try {
colBuffer.append(this.groupColumns(valueStr, new
Integer(tag.getGroup()).intValue()));
} catch (Exception e) {
System.err.println(e.getMessage());
e.printStackTrace(System.err);
}
} else {
if (chopped) {
colBuffer.append(valBuffer);
colBuffer.append("<a style=\"cursor: help;\" title=\"" +
xsBuffer + "\">...</a>");
} else {
colBuffer.append(valueStr);
}
}
colBuffer.append("</td>\n");
lines.add(colBuffer.toString());
}
// Special case, if they didn't provide any columns, then just spit out
// the object's string representation to the table.
if (this.columns.isEmpty()) {
lines.add("<td class=\"tableCell\">" + row + "</td>");
}
lines.add("</tr>");
}
//end row!!!
if (rows.isEmpty()) {
lines.add("<tr class=\"tableRowOdd\">");
lines.add("<td class=\"tableCell\" align=\"center\" colspan=\"" +
(colsSize + 1) + "\">" +
getProperty("basic.msg.empty_list") + "</td></tr>");
}
lines.add(this.getTableFooter());
lines.add("</table>\n");
return StringUtils.delimit(lines.toArray(), '\n');
}
private String getColumnValue(final ColumnTag tag, Object row, final int rowcnt) {
String value;
final String property = tag.getProperty();
try {
if(property.toLowerCase().equals("table_index")) return
String.valueOf(rowcnt);
value = BeanUtils.getSimpleProperty(row,tag.getProperty());
} catch (Exception e) {
e.printStackTrace();
value = " not able to get value";
}
List actions = tag.getActions();
String val = value.toString();
if(actions.isEmpty()) return val;
StringBuffer ret = new StringBuffer(actions.size()*20);
String delim = " ";
for(int i = 0, len = actions.size(); i < len; i++) {
if(i != 0) ret.append(delim);
ActionTag action = (ActionTag) actions.get(i);
boolean needsStartingMark = action.getHref().indexOf('?') == -1;
String href = action.getHref() + (needsStartingMark ? "?" : "&") +
property +"="+val;
ret.append(NetUtils.wrapLink(href+val,null,action.getActionCommand()));
}
return ret.toString();
}
/**
* Generates the table header, including the first row of the table which
* displays the titles of the various columns
**/
private String getTableHeader() {
final StringBuffer buf = new StringBuffer(1000);
final int pagesizeValue = this.getPagesizeValue();
final String url = getRequest().getRequestURL().toString();
table.declareTable(buf);
// If they don't want the header shown for some reason, then stop here.
if (!this.getProperty("basic.show.header").equals("true")) {
return buf.toString();
}
if (pagesizeValue != 0 ){
buf.append("<tr><td width=\"100%\" colspan=\"" + this.columns.size());
buf.append("\"><table width=\"100%\" border=\"0\" cellspacing=\"0\" ");
buf.append("cellpadding=\"0\"><tr class=\"tableRowAction\">");
buf.append("<td align=\"left\" valign=\"bottom\" class=\"");
buf.append("tableCellAction\">");
buf.append(pagingInformation.getSearchResultsSummary());
buf.append("</td>\n");
buf.append("<td valign=\"bottom\" align=\"right\" class=\"");
buf.append("tableCellAction\">\n");
buf.append(pagingInformation.getPageNavigationBar(url + "?page="));
buf.append("</td>\n</tr></table></td></tr>\n");
}
buf.append("<tr class=\"tableRowHeader\">");
for (int i = 0, len = this.columns.size(); i < len; i++) {
ColumnTag tag = (ColumnTag) this.columns.get(i);
buf.append("<th");
if (tag.getWidth() != null)
buf.append(" width=\"" + tag.getWidth() + "\"");
if (tag.getAlign() != null)
buf.append(" align=\"" + tag.getAlign() + "\"");
if (tag.getHeaderStyleClass() != null) {
buf.append(" class=\"" + tag.getHeaderStyleClass() + "\">");
} else {
buf.append(" class=\"tableCellHeader\">");
}
String header = tag.getTitle();
if (header == null) {
header = StringUtils.toUpperCaseAt(tag.getProperty(), 0);
}
if (tag.getSort() != null) {
if (this.sortOrder == SORT_ORDER_ASCENDING) {
buf.append("<a href=\"" + url + "?order=dec&sort=" + i + "\"
class=\"tableCellHeader\">");
} else {
buf.append("<a href=\"" + url + "?order=asc&sort=" + i + "\"
class=\"tableCellHeader\">");
}
buf.append(header);
buf.append("</a>");
} else {
buf.append(header);
}
buf.append("</th>\n");
}
// Special case, if they don't provide any columns, then just set
// the title to a message, telling them to provide some...
if (columns.isEmpty()) {
buf.append("<td><b>").append(getProperty("error.msg.no_column_tags"));
buf.append("</b></td>");
}
buf.append("</tr>\n");
return buf.toString();
}
/**
* Generates table footer with links for export commands.
**/
private String getTableFooter() {
final StringBuffer buf = new StringBuffer(1000);
final int pagesizeValue = this.getPagesizeValue();
String url = getRequest().getRequestURL().toString();
// Put the page stuff there if it needs to be there...
if (getProperty("paging.banner.placement").equals("both") ||
getProperty("paging.banner.placement").equals("bottom")) {
if (pagesizeValue != 0 ) {
buf.append("<tr><td width=\"100%\" colspan=\"" + columns.size());
buf.append("\"><table width=\"100%\" border=\"0\" cellspacing=\"0\" ");
buf.append("cellpadding=\"0\"><tr class=\"tableRowAction\">");
buf.append("<td align=\"left\" valign=\"bottom\" class=\"");
buf.append("tableCellAction\">");
buf.append(pagingInformation.getSearchResultsSummary());
buf.append("</td>\n");
buf.append("<td valign=\"bottom\" align=\"right\" class=\"");
buf.append("tableCellAction\">\n");
buf.append(pagingInformation.getPageNavigationBar(url + "?page="));
buf.append("</td>\n</tr></table></td></tr>\n");
}
}
final String qString = getRequest().getQueryString();
url += qString != null && !qString.equals("") ? "?" + qString + "&" : "?";
if (this.export != null) {
buf.append("<tr><td align=\"left\" width=\"100%\" colspan=\"" +
this.columns.size() + "\">");
buf.append("<table width=\"100%\" border=\"0\" cellspacing=\"0\"
cellpadding=0>");
buf.append("\t<tr class=\"tableRowAction\">");
buf.append("\t\t<td align=\"left\" valign=\"bottom\"
class=\"tableCellAction\"><br><Br>");
// Figure out what formats they want to export, make up a little string
StringBuffer formats = new StringBuffer();
if (getProperty("export.csv").equals("true")) {
formats.append("<a href=\"")
.append(url)
.append("exportType=")
.append(TableExporter.EXPORT_TYPE_CSV)
.append("\">")
.append(getProperty("export.csv.label"))
.append("</a>\n");
}
if (getProperty("export.excel").equals("true")) {
if (formats.length() > 0)
formats.append(getProperty("export.banner.sepchar"));
formats.append(NetUtils.wrapLink(url + "exportType=" +
TableExporter.EXPORT_TYPE_EXCEL + "", "", "Excel") + "\n");
}
if (getProperty("export.xml").equals("true")) {
if (formats.length() > 0)
formats.append(getProperty("export.banner.sepchar"));
formats.append("<a href=\"" + url + "exportType=" +
TableExporter.EXPORT_TYPE_XML + "\">");
formats.append(getProperty("export.xml.label") + "</a>\n");
}
Object[] objs = {formats.toString()};
buf.append(MessageFormat.format(getProperty("export.banner"), objs));
buf.append("\t\t</td></tr></table>\n");
buf.append("</td></tr>");
}
return buf.toString();
}
/**
* This takes a cloumn value and grouping index as the argument.
* It then groups the column and returns the appropritate string back to the
* caller.
*/
private String groupColumns(final String value,
final int group) {
final Integer groupInteger = new Integer(group);
if (groupInteger.intValue() == 1 && !this.nextRow.isEmpty()) { // we are at
the begining of the next row so copy the contents from .
// nextRow to the previousRow.
this.previousRow.clear();
this.previousRow.putAll(nextRow);
this.nextRow.clear();
}
if (!this.nextRow.containsKey(groupInteger)) {
// Key not found in the nextRow so adding this key now... remember all the
old values.
this.nextRow.put(groupInteger, value);
}
/**
* Start comparing the value we received, along with the grouping index.
* if no matching value is found in the previous row then return the value.
* if a matching value is found then this value should not get printed out
* so reuturn ""
**/
if (this.previousRow.containsKey(groupInteger)) {
for (int x = 1; x <= group; x++) {
final Integer xInteger = new Integer(x);
if (this.previousRow.get(xInteger).equals(this.nextRow.get(xInteger)))
continue;
// no match found so return this value back to the caller.
return value;
}
}
}
return previousRow.isEmpty() ? value : "";
}
}
--- NEW FILE: TableTagExtraInfo.java ---
/**
* $Id: TableTagExtraInfo.java,v 1.1 2003/07/18 13:19:57 javabencom Exp $
*
* Status: Under Development
*
* Todo
* - impementation
* - documentation (javadoc, examples, etc...)
* - junit test cases
**/
package com.tablelib.tags;
import javax.servlet.jsp.tagext.TagData;
import javax.servlet.jsp.tagext.TagExtraInfo;
import javax.servlet.jsp.tagext.VariableInfo;
/**
* One line description of what this class does.
*
* More detailed class description, including examples of usage if applicable.
**/
public class TableTagExtraInfo extends TagExtraInfo {
public VariableInfo[] getVariableInfo(final TagData data) {
return new VariableInfo[]{
new VariableInfo("table_index",
"java.lang.Integer",
true,
VariableInfo.NESTED),
new VariableInfo("table_item",
"java.lang.Object",
true,
VariableInfo.NESTED),
};
}
}
-------------------------------------------------------
This SF.net email is sponsored by: VM Ware
With VMware you can run multiple operating systems on a single machine.
WITHOUT REBOOTING! Mix Linux / Windows / Novell virtual machines at the
same time. Free trial click here: http://www.vmware.com/wl/offer/345/0
_______________________________________________
displaytag-devel mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/displaytag-devel