[richfaces-issues] [JBoss JIRA] Updated: (RF-3569) <rich:tree> possible performance issue

Nick Belaevski (JIRA) jira-events at lists.jboss.org
Sat Dec 20 12:21:54 EST 2008


     [ https://jira.jboss.org/jira/browse/RF-3569?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Nick Belaevski updated RF-3569:
-------------------------------

    Fix Version/s: Future
                       (was: 3.3.0)


> <rich:tree> possible performance issue 
> ---------------------------------------
>
>                 Key: RF-3569
>                 URL: https://jira.jboss.org/jira/browse/RF-3569
>             Project: RichFaces
>          Issue Type: Quality Risk
>    Affects Versions: 3.2.0
>            Reporter: martin bischoff
>            Assignee: Nick Belaevski
>             Fix For: Future
>
>
> 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: https://jira.jboss.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

       




More information about the richfaces-issues mailing list