KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tonbeller > wcf > tree > OptimizingTreeModelDecorator


1 /*
2  * ====================================================================
3  * This software is subject to the terms of the Common Public License
4  * Agreement, available at the following URL:
5  * http://www.opensource.org/licenses/cpl.html .
6  * Copyright (C) 2003-2004 TONBELLER AG.
7  * All Rights Reserved.
8  * You must accept the terms of that agreement to use this software.
9  * ====================================================================
10  *
11  *
12  */

13 package com.tonbeller.wcf.tree;
14
15 import java.util.ArrayList JavaDoc;
16 import java.util.Comparator JavaDoc;
17 import java.util.HashSet JavaDoc;
18 import java.util.List JavaDoc;
19 import java.util.Set JavaDoc;
20 import java.util.TreeSet JavaDoc;
21
22
23 /**
24  * Hides branches that do not contain significant nodes.
25  * <p>
26  * Significance is defined by a node filter. If the filter accepts a
27  * node, its significant, else its not.
28  * <p>
29  * Significance is transitive.
30  * A node, that is not accepted by the filter itself, is considered significant if
31  * it has at least one descendant that is accepted by the filter.
32  * <p>
33  * Example usecase: hide empty directories.
34  * <p>
35  * <b>Warning:</b> This class reads the whole tree model to find
36  * "significant" nodes.
37  *
38  * @author av
39  */

40
41 public class OptimizingTreeModelDecorator extends TreeModelDecorator {
42   NodeFilter filter;
43
44   Object JavaDoc[] roots;
45   Set JavaDoc significant;
46   boolean dirty = true;
47
48   boolean optimizeRoot = true;
49   boolean optimizeLeafs = false;
50   
51   /**
52    * creates a reduced view on a tree model that uses a HashMap for implementation
53    * @param treeModel the tree model to decorate
54    * @param filter accepted nodes are considered "significant"
55    */

56   public OptimizingTreeModelDecorator(NodeFilter filter, TreeModel decoree) {
57     super(decoree);
58     this.filter = filter;
59     this.significant = new HashSet JavaDoc();
60     installChangeListener(decoree);
61   }
62
63   /**
64    * creates a new optimizing tree model that uses a TreeMap for implementation
65    * @param treeModel the tree model to decorate
66    * @param filter accepted nodes are considered "significant"
67    */

68   public OptimizingTreeModelDecorator(NodeFilter filter, TreeModel decoree, Comparator JavaDoc nodeComparator) {
69     // super(decoree, nodeComparator);
70
super(decoree);
71     this.filter = filter;
72     this.significant = new TreeSet JavaDoc(nodeComparator);
73     installChangeListener(decoree);
74   }
75
76   private void installChangeListener(TreeModel decoree) {
77     decoree.addTreeModelChangeListener(new TreeModelChangeListener() {
78       public void treeModelChanged(TreeModelChangeEvent event) {
79         dirty = true;
80       }
81     });
82   }
83   
84
85   public Object JavaDoc[] getRoots() {
86     if (dirty)
87       initialize();
88     return roots;
89   }
90
91   void initialize() {
92     dirty = false;
93     significant.clear();
94     recurseFindSignificant(super.getRoots());
95
96     roots = optimize(super.getRoots());
97     if (optimizeRoot) {
98       while (roots.length == 1 && !filter.accept(roots[0]))
99         roots = optimize(getChildren(roots[0]));
100     }
101   }
102
103   boolean isSignificant(Object JavaDoc node) {
104     return significant.contains(node);
105   }
106
107   void recurseFindSignificant(Object JavaDoc[] nodes) {
108     for (int i = 0; i < nodes.length; i++) {
109       Object JavaDoc node = nodes[i];
110       if (super.hasChildren(node)) {
111         if (filter.accept(node))
112           addSignificant(node);
113         recurseFindSignificant(super.getChildren(node));
114       } else if (filter.accept(node))
115         addSignificant(node);
116       else if (!optimizeLeafs)
117         significant.add(node); // leafs only
118
}
119   }
120
121   private void addSignificant(Object JavaDoc node) {
122     Object JavaDoc n = node;
123     while (n != null) {
124       significant.add(n);
125       n = super.getParent(n);
126     }
127   }
128
129   private Object JavaDoc[] optimize(Object JavaDoc[] nodes) {
130     List JavaDoc optimized = new ArrayList JavaDoc();
131     for (int i = 0; i < nodes.length; i++) {
132       if (significant.contains(nodes[i]))
133         optimized.add(nodes[i]);
134     }
135     return optimized.toArray();
136   }
137
138   public boolean hasChildren(Object JavaDoc node) {
139     if (super.hasChildren(node))
140       return getChildren(node).length > 0;
141     return false;
142   }
143
144   public Object JavaDoc[] getChildren(Object JavaDoc node) {
145     if (dirty)
146       initialize();
147     return optimize(super.getChildren(node));
148   }
149
150   public Object JavaDoc getParent(Object JavaDoc node) {
151     return super.getParent(node);
152   }
153
154   /**
155    * if true, only significant leafs will be visible.
156    */

157   public void setOptimizeLeafs(boolean b) {
158     optimizeLeafs = b;
159     dirty = true;
160     fireModelChanged(false);
161   }
162
163   public boolean isOptimizeLeafs() {
164     return optimizeLeafs;
165   }
166
167   /**
168    * if true, insignificant parents are not shown.
169    */

170   public void setOptimizeRoot(boolean b) {
171     optimizeRoot = b;
172     dirty = true;
173     fireModelChanged(false);
174   }
175
176   public boolean isOptimizeRoot() {
177     return optimizeRoot;
178   }
179
180 }
181
Popular Tags