Sorting tree nodes in Primefaces
You will need to sort the Primefaces objects DefaultTreeNode
in the ManagedBean using Collections.sort
the Comparator class as well.
public TreeNodeComparator() implements Comparator<TreeNode> {
public int compare(TreeNode n1, TreeNode n2) {
// This assumes the tree node data is a string
return n1.getData().compareTo(n2.getData());
}
}
In your managed bean, you will need to collect your child lists without adding their parents. This may happen later. Now create lists of children for each level and set the parameter parent
to null
;
TreeNode node1 = new DefaultTreeNode("node1", null);
TreeNode node2 = new DefaultTreeNode("node2", null);
TreeNode child1node1 = new DefaultTreeNode("zgnagn", null);
TreeNode child2node1 = new DefaultTreeNode("vvnieeianag", null);
TreeNode child1node2 = new DefaultTreeNode("cajkgnagair", null);
TreeNode child2node2 = new DefaultTreeNode("ajaavnagwokd", null);
rootNodeChildren.add(node1);
rootNodeChildren.add(node2);
node1Children.add(child1node1);
node1Children.add(child2node1);
node2Children.add(child1node2);
node2Children.add(child2node2);
The reason we set everything to null is because when the parent is set to DefaultTreeNode, it is added to the list of children. The order in which you set the parent nodes determines the order in which they appear in the Tree component.
Knowing that we can use our comparator to sort each list separately.
Collections.sort(rootNodeChildren, new TreeNodeComparator());
Collections.sort(node1Children, new TreeNodeComparator());
Collections.sort(node2Children, new TreeNodeComparator());
Now all the lists are sorted so that we can scroll through the respective parents one at a time. You can probably write an algorithm to determine this, or you can keep a separate data structure that builds the tree hierarchy without being added to the list.
Another way and probably easiest is to just override the DefaultTreeNode class and give it a sort method:
public SortableDefaultTreeNode extends DefaultTreeNode {
public void sort() {
TreeNodeComparator comparator = new TreeNodeComparator();
Collections.sort(this.children, comparator);
for (TreeNode child : children) {
child.sort();
}
}
}
Now you can just create your TreeNodes and then call root.sort()
and it will recursively sort all of its children at each level in alphabetical order.
source to share
we had problems sorting through Comparator
and found out that there is a handy PrimeFaces TreeUtils.sortNode (TreeNode, Comparator) class already provided which works like a charm :)
source to share
You can also use a generic comparable TreeNode attribute like:
The base was taken from the priils DefaultTreeNode
, the unmodified changes are not indicated in the code below.
If the child does not need to be constrained to T, you can use TreeNodeComparable<T extends Comparable<?>>
and apply the method Comparable
in compareTo()
.
public class TreeNodeComparable<T extends Comparable<T>> implements TreeNode, Serializable,
Comparable<TreeNodeComparable<T>>
{
private static final long serialVersionUID = ...;
private T data;
private List<TreeNodeComparable<T>> children;
public TreeNodeComparable(final String type, final T data, final TreeNodeComparable<T> parent)
{
this.type = type;
this.data = data;
this.children = (List) new TreeNodeChildren(this);
if (parent != null)
parent.getChildren().add(this);
}
/**
* Comparison only depends on the underlying data
*
* @see ObjectUtils#compare(Comparable, Comparable)
*/
@Override
public int compareTo(final TreeNodeComparable<T> node)
{
if (node == null)
throw new NullPointerException("node");
return ObjectUtils.compare((T) this.getData(), (T) node.getData());
}
/**
* Recursively sorts the complete tree.
*/
public void sort()
{
Collections.sort(this.children);
for (final TreeNodeComparable<T> child : this.children)
{
child.sort();
// must reset parent due to PF problems
// http://forum.primefaces.org/posting.php?mode=reply&f=3&t=39752
child.setParent(this);
}
}
@SuppressWarnings("unchecked")
@Override
public boolean equals(final Object obj)
{
if (this == obj)
return true;
if (obj == null || this.getClass() != obj.getClass())
return false;
final TreeNodeComparable<T> other = (TreeNodeComparable<T>) obj;
return ObjectUtils.equals(this.data, other.data);
}
@Override
public int hashCode()
{
return new HashCodeBuilder().append(this.data).toHashCode();
}
public void setData(final Object data)
{
if (data != null && !(data instanceof Comparable))
throw new IllegalArgumentException();
this.data = (T) data;
}
@SuppressWarnings(
{
"unchecked", "rawtypes"
})
public List<TreeNode> getChildren()
{
return (List) this.children;
}
}
source to share