[richfaces-issues] [JBoss JIRA] Commented: (RF-3569) <rich:tree> possible performance issue
martin bischoff (JIRA)
jira-events at lists.jboss.org
Wed Jun 4 08:38:31 EDT 2008
[ http://jira.jboss.com/jira/browse/RF-3569?page=comments#action_12415550 ]
martin bischoff commented on RF-3569:
-------------------------------------
i articulated myself a little bit unfortunate. i mean the structure of the single treenodes. in original its "nested" that way:
div
|-table - tbody - tr - 3x td
|-div
|-table - tbody - tr - 3x td
|-div ...
i modified the structure to this nesting:
ul
|-li - div - 3x span
|-li
|-ul
|- li - div - 3x span
|- li ...
> <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
> Assigned To: Nick Belaevski
> Fix For: 3.2.2
>
>
> 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
More information about the richfaces-issues
mailing list