diff --git a/zkdoc/release-note b/zkdoc/release-note index eadfa4f7d8b..261135af201 100644 --- a/zkdoc/release-note +++ b/zkdoc/release-note @@ -7,6 +7,7 @@ ZK 10.0.0 ZK-5579: Listbox always renders the same set of items under ROD enabled ZK-5582: Listbox only renders 50 items with client mvvm ZK-5476: client mvvm failed for a tree + ZK-5535: TrackerImplEx#removeAllReference accesses map value by iteration instead of key, lowers performance * Upgrade Notes diff --git a/zktest/build.gradle b/zktest/build.gradle index 797241d135d..43b4ee937f2 100644 --- a/zktest/build.gradle +++ b/zktest/build.gradle @@ -238,6 +238,9 @@ test { testLogging { events("standardOut", "started", "passed", "skipped", "failed") } + + maxHeapSize = "1024m" + jvmArgs '-XX:MaxPermSize=1024m' } task clearNoA11Y(type: Delete) { diff --git a/zktest/src/main/java/org/zkoss/zktest/test2/B100_ZK_5535/Bug.java b/zktest/src/main/java/org/zkoss/zktest/test2/B100_ZK_5535/Bug.java new file mode 100644 index 00000000000..e1f7e663300 --- /dev/null +++ b/zktest/src/main/java/org/zkoss/zktest/test2/B100_ZK_5535/Bug.java @@ -0,0 +1,112 @@ +package org.zkoss.zktest.test2.B100_ZK_5535; + +import org.zkoss.bind.BindUtils; +import org.zkoss.bind.annotation.Command; +public class Bug { + private BugOasiListBoxLayoutModel gridTree=new BugOasiListBoxLayoutModel(); + public BugOasiListBoxLayoutModel getGridTree() { + return gridTree; + } + public void setGridTree(BugOasiListBoxLayoutModel gridTree) { + this.gridTree = gridTree; + } + public Bug() + { + } + public void loadDati() + { + BugOasiTreeNode nodeParent=this.loadDati(null); + for (int i=0;i<2000;i++) + nodeParent=this.loadDati(nodeParent); + this.gridTree.setLeafNodes(); + } + public BugOasiTreeNode loadDati( + BugOasiTreeNode parent) + { + BugFormModel row=null; + /* --------------------------------------- */ + /* Popolo grid tree */ + /* --------------------------------------- */ + BugOasiTreeNode nodeParent; + BugOasiTreeNode node; + /* ------------------------- */ + /* Creo nodo di root */ + /* ------------------------- */ + nodeParent=gridTree.addTreeNode(parent,true); + row=nodeParent.getData(); + row.get("coarfo").setStringVal("1"); + row.get("descri").setStringVal("Nodo root"); + nodeParent=gridTree.addTreeNode(true); + row=nodeParent.getData(); + row.get("coarfo").setStringVal("1"); + row.get("descri").setStringVal("Nodo root2"); + nodeParent=gridTree.addTreeNode(true); + row=nodeParent.getData(); + row.get("coarfo").setStringVal("1"); + row.get("descri").setStringVal("Nodo root3"); + nodeParent=gridTree.addTreeNode(true); + row=nodeParent.getData(); + row.get("coarfo").setStringVal("1"); + row.get("descri").setStringVal("Nodo root4"); + nodeParent=gridTree.addTreeNode(true); + row=nodeParent.getData(); + row.get("coarfo").setStringVal("1"); + row.get("descri").setStringVal("Nodo root5"); + nodeParent=gridTree.addTreeNode(true); + row=nodeParent.getData(); + row.get("coarfo").setStringVal("1"); + row.get("descri").setStringVal("Nodo root6"); + /* ---------------------------------- */ + /* Creo primo nodo figlio senza figli */ + /* ---------------------------------- */ + node=gridTree.addTreeNode(nodeParent); + node.setLeaf(true); + row=node.getData(); + row.get("coarfo").setStringVal("2"); + row.get("descri").setStringVal("nodo figlio 1"); + /* ---------------------------------- */ + /* Creo secondo nodo figlio con figli */ + /* ---------------------------------- */ + node=gridTree.addTreeNode(nodeParent,false); + row=node.getData(); + row.get("coarfo").setStringVal("3"); + row.get("descri").setStringVal("nodo figlio 2"); + /* ---------------------------------- */ + /* Creo figli secondo nodo figlio */ + /* ---------------------------------- */ + nodeParent=node; + node=gridTree.addTreeNode(nodeParent,true); + row=node.getData(); + row.get("coarfo").setStringVal("4"); + row.get("descri").setStringVal("primo figlio del cocondo figlio"); + /* ---------------------------------- */ + /* Creo secondo nodo figlio con figli */ + /* ---------------------------------- */ + node=gridTree.addTreeNode(nodeParent,true); + row=node.getData(); + row.get("coarfo").setStringVal("6"); + row.get("descri").setStringVal("secondo figlio del cocondo figlio"); + /* ---------------------------------- */ + /* Creo figlio in mezzo */ + /* ---------------------------------- */ + node=gridTree.addTreeNode(nodeParent,true,1); + row=node.getData(); + row.get("coarfo").setStringVal("5"); + row.get("descri").setStringVal("creato figlio in mezzo"); + + return nodeParent; + } + @Command + public void showData() + { + this.loadDati(); + BindUtils.postNotifyChange(null, null, this, "gridTree"); + } + @Command + public void clearTree() + { + this.gridTree.clearTree(); + BindUtils.postNotifyChange(null, null, this, "gridTree"); + } +} + diff --git a/zktest/src/main/java/org/zkoss/zktest/test2/B100_ZK_5535/BugFieldLayout.java b/zktest/src/main/java/org/zkoss/zktest/test2/B100_ZK_5535/BugFieldLayout.java new file mode 100644 index 00000000000..c79c9227bba --- /dev/null +++ b/zktest/src/main/java/org/zkoss/zktest/test2/B100_ZK_5535/BugFieldLayout.java @@ -0,0 +1,17 @@ +package org.zkoss.zktest.test2.B100_ZK_5535; + +public class BugFieldLayout { +private String stringVal; + +public String getStringVal() { + return stringVal; +} + +public void setStringVal(String stringVal) { + this.stringVal = stringVal; +} +public void detach() +{ + this.stringVal=null; +} +} diff --git a/zktest/src/main/java/org/zkoss/zktest/test2/B100_ZK_5535/BugFormModel.java b/zktest/src/main/java/org/zkoss/zktest/test2/B100_ZK_5535/BugFormModel.java new file mode 100644 index 00000000000..1cb87d3d3af --- /dev/null +++ b/zktest/src/main/java/org/zkoss/zktest/test2/B100_ZK_5535/BugFormModel.java @@ -0,0 +1,56 @@ +package org.zkoss.zktest.test2.B100_ZK_5535; + +import java.util.LinkedHashMap; +import java.util.Map.Entry; +public class BugFormModel { +public LinkedHashMap fields = new LinkedHashMap(); +private BugOasiTreeNode node=null; + +/** + *
  • BugFormModel
  • + *
    + * Nel caso di un Tree restituisce il nodo associato
    + * 
    + * + * @author m.spuri + */ +public BugOasiTreeNode getNode() { + return node; +} +/** + *
  • BugFormModel
  • + *
    + * Nel caso di un Tree restituisce il nodo associato
    + * 
    + * + * @author m.spuri + */ +public void setNode(BugOasiTreeNode node) { + this.node = node; +} +public LinkedHashMap getFields() { + return fields; +} +public void setFields(LinkedHashMap fields) { + this.fields = fields; +} +public BugFieldLayout get(String name) +{ + return fields.get(name); +} +public BugFormModel() +{ + fields.put("coarfo",new BugFieldLayout()); + fields.put("descri",new BugFieldLayout()); +} +public void detach() +{ + if ( this.fields!=null ) + { + for(Entry obj: this.fields.entrySet()) + obj.getValue().detach(); + this.fields.clear(); + this.fields=null; + } +} +} diff --git a/zktest/src/main/java/org/zkoss/zktest/test2/B100_ZK_5535/BugOasiListBoxLayoutModel.java b/zktest/src/main/java/org/zkoss/zktest/test2/B100_ZK_5535/BugOasiListBoxLayoutModel.java new file mode 100644 index 00000000000..1ae9bfa0c93 --- /dev/null +++ b/zktest/src/main/java/org/zkoss/zktest/test2/B100_ZK_5535/BugOasiListBoxLayoutModel.java @@ -0,0 +1,178 @@ +package org.zkoss.zktest.test2.B100_ZK_5535; + +import java.util.LinkedList; + +import org.zkoss.zul.DefaultTreeModel; +import org.zkoss.zul.TreeModel; +import org.zkoss.zul.TreeNode; +public class BugOasiListBoxLayoutModel { + private BugOasiTreeNode treeRoot = null; + private TreeModel> treeNodes = null; + private boolean enableMultiSelection = false; + public boolean isEnableMultiSelection() { + return enableMultiSelection; + } + + public void setEnableMultiSelection(boolean enableMultiSelection) { + this.enableMultiSelection = enableMultiSelection; + } + + public BugOasiTreeNode getTreeRoot() { + return treeRoot; + } + + public void setTreeRoot(BugOasiTreeNode treeRoot) { + this.treeRoot = treeRoot; + } + public TreeModel> getTreeNodes() { + return this.treeNodes; + } + + public void setTreeNodes(TreeModel> treeNodes) { + this.treeNodes = treeNodes; + } + /** + *
  • OasiListBoxLayoutModel
  • + * + *
    +	 * Aggiunge un nodo al tree
    +	 * 
    + * + * Aggiungo nodo di root + * + * @author m.spuri + */ + public BugOasiTreeNode addTreeNode(boolean open) { + return this.addTreeNode(null, open); + }/** + *
  • OasiListBoxLayoutModel
  • + * + *
    +	 * Aggiunge un nodo al tree
    +	 * 
    + * + * @author m.spuri + */ + public BugOasiTreeNode addTreeNode( + BugOasiTreeNode parent, + boolean open) { + return this.addTreeNode(parent, open, null); + } + public BugOasiTreeNode addTreeNode( + BugOasiTreeNode parent, + boolean open, Integer pos) { + return this.addTreeNode(parent, null, null, open, pos); + } + private BugOasiTreeNode addTreeNode( + BugOasiTreeNode parent, + BugOasiTreeNode newnod, BugFormModel myrow, boolean open, + Integer pos) { + if (parent == null) { + if (this.treeRoot == null) + this.createTreeRoot(); + parent = this.treeRoot; + } + BugFormModel row; + if (newnod == null) { + if (myrow == null) + row = new BugFormModel(); + else + row = myrow; + } else + row = newnod.getData(); + + + BugOasiTreeNode treeNode = null; + if (newnod == null) + treeNode = new BugOasiTreeNode(parent, row, + new LinkedList>(), treeNodes, open, + pos); + else { + treeNode = newnod; + parent.setLeaf(false); + if (pos == null) + parent.add(treeNode); + else + parent.getChildren().add(pos, treeNode); + } + row.setNode(treeNode); + if (treeNode.isOpen()) + ((DefaultTreeModel) treeNodes).addOpenObject(treeNode); + return treeNode; + } + private void createTreeRoot() { + this.treeRoot = new BugOasiTreeNode(null, + new LinkedList>(), treeNodes, true); + + this.treeNodes = new DefaultTreeModel(this.treeRoot); + ((DefaultTreeModel)this.treeNodes).setMultiple(this.isEnableMultiSelection()); + } + /** + *
  • OasiListBoxLayoutModel
  • + * + *
    +	 * Aggiunge un nodo al tree
    +	 * 
    + * + * Di default � chiuso + * + * @author m.spuri + */ + public BugOasiTreeNode addTreeNode( + BugOasiTreeNode parent) { + return this.addTreeNode(parent, false); + } + + public void clearTree() { + int n; + if (this.treeRoot != null) { + n = this.treeRoot.getChildren().size(); + for (int k = 0; k < n; k++) + this.clearTreeNode((BugOasiTreeNode) this.treeRoot.getChildren().get(k)); + try { + this.treeRoot.getChildren().clear(); + } catch (Exception e) { + // TODO: handle exception + } + + this.treeRoot = null; + } + } + private void clearTreeNode(BugOasiTreeNode node) { + if (node == null) + return; + if (!node.isLeaf() && node.isOpen()) + ((DefaultTreeModel) treeNodes).removeOpenObject(node); + + BugFormModel row = (BugFormModel) node.getData(); + row.detach(); + if (node.getChildren() != null) { + int n = node.getChildren().size(); + for (int i = 0; i < n; i++) { + this.clearTreeNode((BugOasiTreeNode) node.getChildren().get(i)); + } + node.getChildren().clear(); + } + } + public void setLeafNodes() { + int n; + if (this.treeRoot != null) { + n = this.treeRoot.getChildren().size(); + for (int k = 0; k < n; k++) + this.setLeaf((BugOasiTreeNode) this.treeRoot.getChildren().get(k)); + } + } + private void setLeaf(BugOasiTreeNode node) { + if (node == null) + return; + if (node.getChildren() != null && node.getChildren().size()>0 ) { + int n = node.getChildren().size(); + for (int i = 0; i < n; i++) { + this.setLeaf((BugOasiTreeNode) node.getChildren().get(i)); + } + } + else + node.setLeaf(true); + } + +} diff --git a/zktest/src/main/java/org/zkoss/zktest/test2/B100_ZK_5535/BugOasiTreeNode.java b/zktest/src/main/java/org/zkoss/zktest/test2/B100_ZK_5535/BugOasiTreeNode.java new file mode 100644 index 00000000000..0ce4fef7369 --- /dev/null +++ b/zktest/src/main/java/org/zkoss/zktest/test2/B100_ZK_5535/BugOasiTreeNode.java @@ -0,0 +1,96 @@ +package org.zkoss.zktest.test2.B100_ZK_5535; + +import java.util.LinkedList; +import org.zkoss.zul.DefaultTreeModel; +import org.zkoss.zul.DefaultTreeNode; +import org.zkoss.zul.TreeModel; +import org.zkoss.zul.TreeNode; + +public class BugOasiTreeNode extends DefaultTreeNode { + private static final long serialVersionUID = -8085873079938209759L; + + // Node Control the default open + private boolean open = false; + private boolean leafNode=true; + private TreeModel> treeNodes=null; + public BugOasiTreeNode(T data, LinkedList> children, TreeModel>treeNodes,boolean open) { + super(data, children); + this.treeNodes=treeNodes; + if ( this.treeNodes!=null ) + this.setOpen(open); + else + this.open=open; + } + public BugOasiTreeNode(BugOasiTreeNode parent,T data, LinkedList> children, TreeModel>treeNodes,boolean open) { + super(data, children); + this.treeNodes=treeNodes; + this.setOpen(open); + parent.setLeaf(false); + parent.add(this); + } + public BugOasiTreeNode(BugOasiTreeNode parent,T data, LinkedList> children,TreeModel>treeNodes, boolean open,Integer pos) { + super(data, children); + this.treeNodes=treeNodes; + this.setOpen(open); + parent.setLeaf(false); + if (pos==null || parent.getChildren().size()==0 ) + parent.add(this); + else + parent.getChildren().add(pos,this); + } + public BugOasiTreeNode(T data, LinkedList> children,TreeModel>treeNodes) { + super(data, children); + this.treeNodes=treeNodes; + } + public BugOasiTreeNode(BugOasiTreeNode parent,T data, LinkedList> children,TreeModel>treeNodes) { + super(data, children); + parent.setLeaf(false); + parent.add(this); + this.treeNodes=treeNodes; + } + + public BugOasiTreeNode(BugOasiTreeNode parent,T data,TreeModel>treeNodes) { + super(data); + parent.setLeaf(false); + parent.add(this); + this.treeNodes=treeNodes; + } + public BugOasiTreeNode(BugOasiTreeNode parent,T data,boolean open,TreeModel>treeNodes) { + super(data); + parent.setLeaf(false); + parent.add(this); + this.treeNodes=treeNodes; + this.setOpen(open); + } + public BugOasiTreeNode(T data,TreeModel>treeNodes) { + super(data); + this.treeNodes=treeNodes; + } + public BugOasiTreeNode(T data,TreeModel>treeNodes,boolean open) { + super(data); + this.treeNodes=treeNodes; + this.setOpen(open); + } + + public boolean isOpen() { + return open; + } + + public void setOpen(boolean open) { + this.open = open; + if ( open ) + ((DefaultTreeModel)treeNodes).addOpenObject(this); + else + ((DefaultTreeModel)treeNodes).removeOpenObject(this); + } + public boolean isLeaf() { + + return leafNode; + } + public void setLeaf(boolean value) { + + this.leafNode=value; + if ( value ) + this.setOpen(false); + } +} diff --git a/zktest/src/main/webapp/test2/B100-ZK-5535.zul b/zktest/src/main/webapp/test2/B100-ZK-5535.zul new file mode 100644 index 00000000000..9f4025486b4 --- /dev/null +++ b/zktest/src/main/webapp/test2/B100-ZK-5535.zul @@ -0,0 +1,76 @@ + + + + +