001    package biz.hammurapi.swing;
002    
003    import java.util.ArrayList;
004    import java.util.Collections;
005    import java.util.Enumeration;
006    import java.util.List;
007    
008    import javax.swing.tree.TreeNode;
009    
010    import biz.hammurapi.util.CollectionVisitable;
011    import biz.hammurapi.util.Visitable;
012    import biz.hammurapi.util.Visitor;
013    
014    /**
015     * Base class for tree nodes which load their children on demand.
016     * Subclasses shall implement loadChildren() method.
017     * @author Pavel
018     *
019     */
020    public abstract class LazyTreeNode implements TreeNode, Visitable {
021            
022            private List children;
023            
024            protected String name;
025    
026            protected TreeNode parent;
027            
028            protected String description;
029            
030            protected static final List EMPTY_LIST = Collections.unmodifiableList(new ArrayList());
031            
032            public String toString() {
033                    return name;
034            }
035            
036            public LazyTreeNode(TreeNode parent, String name) {
037                    this(parent);
038                    this.name = name;
039            }
040            
041            protected LazyTreeNode(TreeNode parent, String name, List children) {
042                    this(parent, name);
043                    this.children = children;
044            }       
045            
046            public LazyTreeNode(TreeNode parent) {
047                    this.parent = parent;
048            }
049            
050            /**
051             * Visits only children if they are loaded.
052             */
053            public boolean accept(Visitor visitor) {
054                    if (visitor.visit(this)) {
055                            if (children!=null) {
056                                    new CollectionVisitable(children, false).accept(visitor);
057                            }
058                            return true;
059                    }
060                    return false;
061            }
062            
063            protected List getChildren() {
064                    if (children==null) {
065                            children = loadChildren();
066                            if (children == null) {
067                                    children = EMPTY_LIST;
068                            }
069                    }
070                    return children;
071            }
072    
073            /**
074             * Loads node children.
075             * @return
076             */
077            protected abstract List loadChildren();
078    
079            public Enumeration children() {
080                    return Collections.enumeration(getChildren());
081            }
082    
083            public boolean getAllowsChildren() {
084                    return true;
085            }
086    
087            public TreeNode getChildAt(int childIndex) {
088                    return (TreeNode) getChildren().get(childIndex);
089            }
090    
091            public int getChildCount() {
092                    return getChildren().size();
093            }
094    
095            public int getIndex(TreeNode node) {
096                    return getChildren().indexOf(node);
097            }
098    
099            public TreeNode getParent() {
100                    return parent;
101            }
102    
103            public boolean isLeaf() {
104                    return getChildren().isEmpty();
105            }
106                    
107            public boolean isSelectable() {
108                    return true;
109            }
110            
111            /**
112             * @return Text for rendering tooltip.
113             */
114            public String getDescription() {
115                    return description;
116            }
117    }