Last active
December 18, 2015 14:18
-
-
Save uklance/5795703 to your computer and use it in GitHub Desktop.
A more database friendly TreeModel implementation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class LazyTreeModel<T> implements TreeModel<T> { | |
private final ValueEncoder<T> encoder; | |
private final LazyTreeModelSource<T> source; | |
public LazyTreeModel<T>(ValueEncoder<T> encoder, LazyTreeModelSource<T> source) { | |
this.encoder = encoder; | |
this.source = source; | |
} | |
@Override | |
public List<TreeNode<T>> getRootNodes() { | |
List<T> roots = source.getRoots(); | |
return LazyTreeModel.createTreeNodes(encoder, source, roots); | |
} | |
@Override | |
public TreeNode<T> getById(String id) { | |
return find(encoder.toValue(id)); | |
} | |
@Override | |
public TreeNode<T> find(T value) { | |
return new LazyTreeNode<T>(encoder, source, value); | |
} | |
public static List<TreeNode> createTreeNodes(ValueEncoder<T> encoder, LazyTreeModelSource<T> source, List<T> siblings) { | |
if (siblings == null || siblings.isEmpty()) { | |
return Collections.emptyList(); | |
} | |
List<TreeNode> treeNodes = new ArrayList<TreeNode>(siblings.size()); | |
for (T value : siblings) { | |
treeNodes.add(new LazyTreeNode<T>(encoder, source, value)); | |
} | |
return treeNodes; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public interface LazyTreeModelSource<T> { | |
/** | |
* Get the label from the value. Note: for efficiency this should be sourced | |
* directly from the value and should not require an extra database lookup | |
**/ | |
String getLabel(T value); | |
/** | |
* Get the isLeaf flag from the value. Note: for efficiency this should be sourced | |
* directly from the value and should not require an extra database lookup | |
**/ | |
boolean isLeaf(T value); | |
/** | |
* Get the hasChildren flag from the value. Note: for efficiency this should be sourced | |
* directly from the value and should not require an extra database lookup | |
**/ | |
boolean hasChildren(T value); | |
/** | |
* Get the children of the value | |
**/ | |
List<T> getChildren(T value); | |
/** | |
* Get the roots of the TreeModel | |
**/ | |
List<T> getRoots(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class LazyTreeNode<T> implements TreeNode<T> { | |
private final ValueEncoder<T> encoder; | |
private final LazyTreeModelSource<T> source; | |
private final T value; | |
public LazyTreeNode<T>(ValueEncoder<T> encoder, LazyTreeModelSource<T> source, T value) { | |
this.encoder = encoder; | |
this.source = source; | |
this.value = value; | |
} | |
@Override | |
public T getValue() { | |
return value; | |
} | |
@Override | |
public String getId() { | |
return encoder.toClient(value); | |
} | |
@Override | |
public boolean isLeaf() { | |
return source.isLeaf(value); | |
} | |
@Override | |
public boolean getHasChildren() { | |
return source.hasChildren(value); | |
} | |
@Override | |
public String getLabel() { | |
return source.getLabel(value); | |
} | |
@Override | |
public List<TreeNode<T>> getChildren() { | |
List<T> children = source.getChildren(value); | |
return LazyTreeModel.createTreeNodes(encoder, source, children); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The roots are intentionally not part of LazyTreeModel. The roots are looked up via LazyTreeNodeSource on demand. The roots are ONLY required when rendering the root of the tree and are NOT required when expanding a node. I prefer this approach to DefaultTreeModel which ALWAYS requires the roots.