FileDocCategorySizeDatePackage
TreeRenderer.javaAPI DocExample3966Tue Jun 08 11:26:42 BST 2004com.mycompany.jsf.renderer

TreeRenderer.java

package com.mycompany.jsf.renderer;

import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.component.NamingContainer;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.render.Renderer;

import com.mycompany.jsf.component.UITree;
import com.mycompany.jsf.model.TreeNode;

/**
 * This class is a JSF Renderer for the "com.mycompany.Tree"
 * component type. It renders a tree structure for the nodes
 * represented by the component's model using the "openNode",
 * "closedNode" and "leafNode" facets.
 *
 * @author Hans Bergsten, Gefion Software <hans@gefionsoftware.com>
 * @version 1.0
 */
public class TreeRenderer extends Renderer {

    /**
     * Returns "true".
     */
    public boolean getRendersChildren() {
	return true;
    }

    /**
     * Calls encodeNodes() to write the HTML elements for all nodes,
     * within a "span" element with an "id" attribute set to the
     * component's client ID if explicitly set.
     */
    public void encodeChildren(FacesContext context, UIComponent component)
        throws IOException {

        if (!component.isRendered()) {
            return;
        }

	if (((UITree) component).getValue() == null) {
	    return;
	}
	
        ResponseWriter out = context.getResponseWriter();
	String clientId = null;
	if (component.getId() != null && 
	    !component.getId().startsWith(UIViewRoot.UNIQUE_ID_PREFIX)) {
	    clientId = component.getClientId(context);
	}

	boolean isOuterSpanUsed = false;
	if (clientId != null) {
	    isOuterSpanUsed = true;
	    out.startElement("span", component);
	    out.writeAttribute("id", clientId, "id");
	}
	encodeNodes(context, out, (UITree) component, null, 0);
	((UITree) component).setNodeId(null);
	if (isOuterSpanUsed) {
            out.endElement("span");
	}
    }

    /**
     * Iterates over all expanded nodes in the model and processes the
     * appropriate facet for each node. Writes a "br" elements after
     * each node and embeds child nodes within a "blockquote" element.
     */
    private void encodeNodes(FacesContext context, ResponseWriter out,
	UITree tree, String parentId, int childLevel) throws IOException {

	UIComponent facet = null;
	tree.setNodeId(parentId != null ? 
            parentId + NamingContainer.SEPARATOR_CHAR + childLevel : "0");
	TreeNode node = tree.getNode();
	if (node.isLeafNode()) {
	    facet = tree.getLeafNode();
	} 
	else if (node.isExpanded()) {
	    facet = tree.getOpenNode();
	}
	else {
	    facet = tree.getClosedNode();
	}

	encodeRecursive(context, facet);
	out.startElement("br", tree);
	out.endElement("br");
	if (node.isExpanded()) {
	    out.startElement("blockquote", tree);
	    int kidId = 0;
	    String currId = tree.getNodeId();
	    Iterator i = node.getChildren().iterator();
	    while (i.hasNext()) {
		TreeNode kid = (TreeNode) i.next();
		encodeNodes(context, out, tree, currId, kidId++);
	    }
	    out.endElement("blockquote");
	}
    }

    /**
     * Calls the appropriate encoding methods on the component and
     * calls itself recursively for all component children.
     */
    private void encodeRecursive(FacesContext context, UIComponent component)
        throws IOException {

        if (!component.isRendered()) {
            return;
        }

        component.encodeBegin(context);
        if (component.getRendersChildren()) {
            component.encodeChildren(context);
        } else {
            Iterator i = component.getChildren().iterator();
            while (i.hasNext()) {
                UIComponent child = (UIComponent) i.next();
                encodeRecursive(context, child);
            }
        }
        component.encodeEnd(context);
    }
}