I wrote the simple tag to handle and show the nested beans. May be it will be good idea to add this tag to the JSTL standard tags repository?
-- Eugene N Dzhurinsky
/* * Created on 19.08.2005 * @author Eugene N. Dzhurinsky, * JDevelop Software * [EMAIL PROTECTED] */ import java.io.IOException; import java.io.Writer; import java.lang.reflect.Method; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.BodyTagSupport; import org.apache.log4j.Logger; /** * Tag to make recursive lists from the nested beans */ public class RecursiveTag extends BodyTagSupport { private static Logger log = Logger.getLogger(RecursiveTag.class.getName()); /** * The name of method, which returns the java.util.List */ private String method; /** * The root object */ private Object object; /** * The name of object to store in the JSP page context */ private String name; /** * The HTML code to place before the item */ private String start; /** * The HTML code to palce after the item */ private String stop; /** * Internal stack to keep the bean (required to emulate the recursive behavior) */ private LinkedList list; /** * The writer used to write out the tag body */ private Writer writer; public RecursiveTag() { super(); list = new LinkedList(); } /** * @param methodName The methodName to set. */ public void setMethod(String methodName) { this.method = methodName; } /** * @param object The object to set. */ public void setObject(Object object) { this.object = object; } /** * @param objectName The objectName to set. */ public void setName(String objectName) { this.name = objectName; } /** * @param start The start to set. */ public void setStart(String start) { this.start = start; } /** * @param stop The stop to set. */ public void setStop(String stop) { this.stop = stop; } /** * The main routine to build recursive list. It takes the current * iterator from the top of the stack and process the bean referenced by the iterator. * If the bean contains the list of nested beans, the iterator of this list is pushed * to the top of the stack, and it will be processed at the next step. */ public int doAfterBody() throws JspException { // if list is empty - do nothing if (list.isEmpty()) { log.info("List is empty"); return SKIP_BODY; } Iterator it = (Iterator) list.getFirst(); // the sequence of the iterators which don't have // items to process will be removed from the top of stack while (!it.hasNext()) { try { // we need to print stop item here, to close the current level of recursion bodyContent.print(stop); } catch (IOException e1) { log.error(e1); } list.removeFirst(); if (!list.isEmpty()) it = (Iterator) list.getFirst(); else return SKIP_BODY; } Object o = it.next(); pageContext.setAttribute(name, o); Iterator newIt = getIterator(o); if (newIt != null) list.addFirst(newIt); log.debug("Current size " + list.size()); try { bodyContent.print(start); } catch (IOException e) { log.error(e); } return EVAL_BODY_AGAIN; } /** * Printing out the contents of the processed tag body */ public int doEndTag() throws JspException { try { if (object == null || getMethod(object) == null) throw new Exception(); if (bodyContent != null) { writer.write(bodyContent.getString()); bodyContent.clearBody(); } } catch (Exception e) { log.error(e, e); } return EVAL_PAGE; } /** * The initial (root) object is placed in the JSP page context here */ public void doInitBody() throws JspException { pageContext.setAttribute(name, object); list.add(getIterator(object)); writer = bodyContent.getEnclosingWriter(); try { bodyContent.print(start); } catch (IOException e) { log.error(e, e); } } /** * The passed bean is examined to have declared method here */ public int doStartTag() throws JspException { int retval = SKIP_BODY; try { log.debug(object); if (object == null || getMethod(object) == null) throw new Exception(); retval = EVAL_BODY_BUFFERED; } catch (Exception e) { log.error(e); } return retval; } /** * Helper method - getting the iterafor of the bean's internal list */ private Iterator getIterator(Object obj) { Iterator it = null; try { Method method = getMethod(obj); List klist = (List) method.invoke(obj, null); if (klist != null) it = klist.iterator(); } catch (Exception e) { log.error(e, e); } return it; } /** * Helper method to get the reference to bean method */ private Method getMethod(Object obj) throws NoSuchMethodException { return obj.getClass().getMethod(method, null); } }
<?xml version="1.0" encoding="UTF-8" ?> <taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" version="2.0"> <tlibversion>1.1</tlibversion> <shortname>test</shortname> <info> </info> <tag> <name>recursive</name> <tagclass> RecursiveTag</tagclass> <body-content>JSP</body-content> <attribute> <name>method</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>name</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>object</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>start</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>stop</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> </tag> </taglib>
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]