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]

Reply via email to