<rich:tree> possible performance issue 
---------------------------------------

                 Key: RF-3569
                 URL: http://jira.jboss.com/jira/browse/RF-3569
             Project: RichFaces
          Issue Type: Quality Risk
    Affects Versions: 3.2.0
            Reporter: martin bischoff
             Fix For: 3.2.0.SR1


i've got an quite simple tree with "just" 50 elements á 200 childs -> 10.000 
nodes

every node gots:
- some little text
- image for a checkbox via h:graphicImage
- a4j:support for listenersupport at the image

expanding/collapsing nodes and checking the checkboxes takes a lot of time...

jprofiler tells me that most of the time is spend by domparsing. i dont know if 
i handle the tree as intended. here is some code:

JSP
[code]
<%@ taglib uri="http://richfaces.org/a4j"; prefix="a4j"%>
<%@ taglib uri="http://richfaces.org/rich"; prefix="rich"%>
<%@ taglib uri="http://java.sun.com/jsf/html"; prefix="h"%>
<%@ taglib uri="http://java.sun.com/jsf/core"; prefix="f"%>
<html>
<head>
<title>tree</title>
</head>
<body>
<f:view>
        <h:form>
                        <a4j:loadStyle src="/res/button.css" />
                        <a4j:loadStyle src="/res/tree/style.css" />
                        <a4j:commandButton id="show_me" value="show childs" 
styleClass="normalButton">
                        <a4j:ajaxListener 
type="controller.listener.ListenerBean" />
                </a4j:commandButton>
                <h:panelGrid columns="2">
         <h:outputLabel>
        <h:outputText value="infinite Tree extended"></h:outputText>
        <rich:tree componentState="#{treeBean.treeState}" 
id="infinite_Tree_expanded" style="width:300px" switchType="ajax"  
stateAdvisor="#{treeDemoStateAdvisor}">
     
            <rich:recursiveTreeNodesAdaptor roots="#{treeBean.rootNodes}" 
var="item" nodes="#{item.children}">
                <rich:treeNode 
nodeSelectListener="#{treeBean.processSelection}">
                <h:graphicImage value="/res/tree/chkb_#{item.state}.png">
                        <a4j:support event="onclick" 
reRender="infinite_Tree_expanded" actionListener="#{item.actionListener}"/>
                </h:graphicImage>
                <h:outputText value="#{item.value} - #{item.state}"/> 
                </rich:treeNode>
            </rich:recursiveTreeNodesAdaptor>
       
        </rich:tree>
        </h:outputLabel>
        </h:panelGrid>
        </h:form>
</f:view>
</body>
</html>[/code]

TreeBean:
[code]package my_tree;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import javax.faces.FacesException;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;

import org.richfaces.component.state.TreeState;
import org.richfaces.event.NodeSelectedEvent;

public class TreeBean {

        private TreeNode rootNode = null;
        private TreeNode[] rootNodes = null;

        private TreeState treeState;

        private static final String DATA_PATH = 
"/res/tree/simple-tree-data.properties";

        public TreeNode getRootNode() {
                if (rootNode == null) {
                        loadTree();
                }

                return rootNode;
        }

        public void setRootNode(TreeNode rootNode) {
                this.rootNode = rootNode;
        }

        public TreeNode[] getRootNodes() {
                if (rootNodes == null) {
                        rootNodes = this.getRootNode().getChildren();
                }
                return rootNodes;
        }

        public void setRootNodes(TreeNode[] rootNodes) {
                this.rootNodes = rootNodes;
        }

        public TreeState getTreeState() {
                return treeState;
        }

        public void setTreeState(TreeState treeState) {
                this.treeState = treeState;
        }

        private void addNodes(String path, TreeNode node, Properties 
properties) {
                boolean end = false;
                int counter = 1;

                while (!end) {
                        String key = path != null ? path + '.' + counter : 
String
                                        .valueOf(counter);

                        String value = properties.getProperty(key);
                        if (value != null) {
                                TreeNode newNode = new TreeNode(value);
                                newNode.setParent(node);
                                node.addNode(newNode);
                                addNodes(key, newNode, properties);
                                counter++;
                        } else {
                                end = true;
                        }
                }
        }

        private void loadTree() {
                System.out.println("TreeBean -> loadTree()");
                FacesContext facesContext = FacesContext.getCurrentInstance();
                ExternalContext externalContext = 
facesContext.getExternalContext();
                InputStream dataStream = 
externalContext.getResourceAsStream(DATA_PATH);
                try {
                        Properties properties = new Properties();
                        properties.load(dataStream);

                        rootNode = new TreeNode("root");
                        addNodes(null, rootNode, properties);
                        // manual tree extension

                        TreeNode dummy = new TreeNode("Sichtlinie");
                        int count = 0;
                        for (int i = 1; i <= 50; i++) {
                                count++;
                                TreeNode node = new TreeNode("i" + i);
                                for (int j = 1; j <= 200; j++) {
                                        count++;
                                        if (count % 1000 == 0) {
                                                System.out.println(count);
                                        }
                                        TreeNode child = new TreeNode("j" + j);
                                        child.setParent(node);
                                        node.addNode(child);
                                }
                                node.setParent(dummy);
                                dummy.addNode(node);
                        }
                        rootNode.addNode(dummy);

                } catch (IOException e) {
                        e.printStackTrace();
                        throw new FacesException(e.getMessage(), e);

                } finally {
                        if (dataStream != null) {
                                try {
                                        dataStream.close();
                                } catch (IOException e) {
                                        e.printStackTrace();
                                        externalContext.log(e.getMessage(), e);
                                }
                        }
                }

        }

        public void processSelection(NodeSelectedEvent arg0)
                        throws AbortProcessingException {
                System.out.println("SimpleTreeBean -> processSelection fired by 
"
                                + arg0.getComponent().getId());

        }[/code]

TreeNode:
[code]package my_tree;

import javax.faces.event.ActionEvent;

import org.richfaces.model.TreeNodeImpl;



public class TreeNode{


        private String value;
        private String state;

        private TreeNode parent;
        private TreeNode[] children;
        

        public TreeNode(String value) {
                this.value = value;
                this.state = "";
        }

        public synchronized void addNode(TreeNode newChild) {
                System.out.println("addNode("+newChild.getValue()+")");
                if (this.children == null) {
                        TreeNode[] merged = new TreeNode[1];
                        merged[0] = newChild;
                        this.children = merged;
                } else {
                        TreeNode[] merged = new TreeNode[this.children.length + 
1];
                        int i;
                        for (i = 0; i < this.children.length; i++) {
                                merged[i] = this.children[i];
                        }
                        merged[merged.length - 1] = newChild;
                        this.children = merged;
                }
        }

        public synchronized void addNodes(TreeNode[] newChildren) {
                System.out.println("addNodeS("+newChildren.length+")");
                TreeNode[] merged = new TreeNode[newChildren.length
                                + this.children.length];
                int i;
                for (i = 0; i <= this.children.length; i++) {
                        merged[i] = this.children[i];
                }
                for (int i2 = i; i2 <= newChildren.length + i; i2++) {
                        merged[i2] = newChildren[i2];
                }
                this.children = merged;
        }

        public synchronized void removeNodes(TreeNode[] removeChildren) {
                TreeNode[] splitted = new TreeNode[this.children.length
                                - removeChildren.length];
                int pos = 0;
                for (int i = 0; i <= this.children.length; i++) {
                        boolean contains = false;
                        for (int j = 0; j <= removeChildren.length; j++) {
                                if (this.children[i] == removeChildren[j]) {
                                        contains = true;
                                }
                        }
                        if (contains == false) {
                                splitted[pos] = this.children[i];
                                pos++;
                        }
                }
        }

        public String checkSibling(){
                //System.out.println("checkSibling() of "+this.value);
                if(this.children!=null){
                        String state = null;
                        int checked = 0;
                        int sub = 0;
                        int i;  
                        TreeNode[] siblings = this.children;
                        for (i = 0; i < siblings.length; i++) {
                                
                                TreeNode treeNode = siblings[i];
                                //System.out.println("\t"+treeNode.getValue()+" 
- "+treeNode.getState());
                                        if(!treeNode.getState().equals("")){
                                                
if(treeNode.getState().equals("checked")){
                                                        checked++;
                                                } else  
if(treeNode.getState().equals("sub")){
                                                        sub++;
                                                }
                                        }
                                
                        }
                        
                        if(checked == i){
                                state = "checked";
                        } else if(sub > 0 || checked > 0) {
                                state = "sub";
                        } else {
                                state = "";
                        }
                        //System.out.println("siblings: "+i+" (checked: 
"+checked+" sub: "+sub+") -> "+state);
                        return state;
                } else {
                        return "";
                }

        }
        
        public void setChildsChecked(TreeNode node){
                //System.out.println("TreeNode -> setChildsChecked of 
"+node.getValue());
                if(node.getChildren()!=null){
                        TreeNode[] children = node.getChildren();
                        for (int i = 0; i < children.length; i++) {
                                TreeNode treeNode = children[i];
                                treeNode.setState("checked");
                                setChildsChecked(treeNode);
                        }
                }
        }
        
        public void setChildsUnchecked(TreeNode node){
                //System.out.println("TreeNode -> setChildsUnchecked of 
"+node.getValue());
                if(node.getChildren()!=null){
                        TreeNode[] children = node.getChildren();
                        for (int i = 0; i < children.length; i++) {
                                TreeNode treeNode = children[i];
                                treeNode.setState("");
                                setChildsUnchecked(treeNode);
                        }
                }
        }

        public void setParentsState(TreeNode node){
                System.out.println("TreeNode -> setParentsState of 
"+node.getValue());
                node.setState(node.checkSibling());
                if(node.getParent()!=null){
                        setParentsState(node.getParent());
                }
        }       
        
        public void actionListener(ActionEvent ae){
                //System.out.println("TreeNode -> nodeListener fired by 
"+ae.getComponent().getId());
                if(this.state == "checked"){
                        this.state = "";
                        setChildsUnchecked(this);
                } else {
                        this.state = "checked";
                        setChildsChecked(this);
                }
                if(this.parent!=null){
                        setParentsState(this.parent);
                }
                
        }       
        
                public String getValue() {
                return value;
        }

        public void setValue(String value) {
                this.value = value;
        }

    public TreeNode[] getChildren() {
                return children;
        }

        public void setChildren(TreeNode[] children) {
                this.children = children;
        }

        
        
        public TreeNode getParent() {
                if(parent==null){
                        return null;
                } else {
                return parent;
                }
        }

        public void setParent(TreeNode parent) {
                this.parent = parent;
        }

        public String getState() {
                return state;
        }

        public void setState(String state) {
                this.state = state;
        }


}
[/code]

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: 
http://jira.jboss.com/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

       

_______________________________________________
richfaces-issues mailing list
[email protected]
https://lists.jboss.org/mailman/listinfo/richfaces-issues

Reply via email to