1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.log4j.lf5.viewer.categoryexplorer;
18
19 import org.apache.log4j.lf5.LogRecord;
20
21 import javax.swing.*;
22 import javax.swing.tree.DefaultTreeModel;
23 import javax.swing.tree.TreeNode;
24 import javax.swing.tree.TreePath;
25 import java.awt.*;
26 import java.awt.event.ActionEvent;
27 import java.awt.event.ActionListener;
28 import java.util.Enumeration;
29
30 /***
31 * CategoryExplorerModel
32 *
33 * @author Michael J. Sikorsky
34 * @author Robert Shaw
35 * @author Brent Sprecher
36 * @author Richard Hurst
37 */
38
39
40
41 public class CategoryExplorerModel extends DefaultTreeModel {
42 private static final long serialVersionUID = -3413887384316015901L;
43
44
45
46
47
48
49
50
51
52 protected boolean _renderFatal = true;
53 protected ActionListener _listener = null;
54 protected ActionEvent _event = new ActionEvent(this,
55 ActionEvent.ACTION_PERFORMED,
56 "Nodes Selection changed");
57
58
59
60
61
62
63
64
65
66 public CategoryExplorerModel(CategoryNode node) {
67 super(node);
68 }
69
70
71
72
73 public void addLogRecord(LogRecord lr) {
74 CategoryPath path = new CategoryPath(lr.getCategory());
75 addCategory(path);
76 CategoryNode node = getCategoryNode(path);
77 node.addRecord();
78 if (_renderFatal && lr.isFatal()) {
79 TreeNode[] nodes = getPathToRoot(node);
80 int len = nodes.length;
81 CategoryNode parent;
82
83
84
85 for (int i = 1; i < len - 1; i++) {
86 parent = (CategoryNode) nodes[i];
87 parent.setHasFatalChildren(true);
88 nodeChanged(parent);
89 }
90 node.setHasFatalRecords(true);
91 nodeChanged(node);
92 }
93 }
94
95 public CategoryNode getRootCategoryNode() {
96 return (CategoryNode) getRoot();
97 }
98
99 public CategoryNode getCategoryNode(String category) {
100 CategoryPath path = new CategoryPath(category);
101 return (getCategoryNode(path));
102 }
103
104 /***
105 * returns null if no CategoryNode exists.
106 */
107 public CategoryNode getCategoryNode(CategoryPath path) {
108 CategoryNode root = (CategoryNode) getRoot();
109 CategoryNode parent = root;
110
111 for (int i = 0; i < path.size(); i++) {
112 CategoryElement element = path.categoryElementAt(i);
113
114
115 Enumeration children = parent.children();
116
117 boolean categoryAlreadyExists = false;
118 while (children.hasMoreElements()) {
119 CategoryNode node = (CategoryNode) children.nextElement();
120 String title = node.getTitle().toLowerCase();
121
122 String pathLC = element.getTitle().toLowerCase();
123 if (title.equals(pathLC)) {
124 categoryAlreadyExists = true;
125
126 parent = node;
127 break;
128 }
129 }
130
131 if (categoryAlreadyExists == false) {
132 return null;
133 }
134 }
135
136 return (parent);
137 }
138
139 /***
140 * @return true if all the nodes in the specified CategoryPath are
141 * selected.
142 */
143 public boolean isCategoryPathActive(CategoryPath path) {
144 CategoryNode root = (CategoryNode) getRoot();
145 CategoryNode parent = root;
146 boolean active = false;
147
148 for (int i = 0; i < path.size(); i++) {
149 CategoryElement element = path.categoryElementAt(i);
150
151
152 Enumeration children = parent.children();
153
154 boolean categoryAlreadyExists = false;
155 active = false;
156
157 while (children.hasMoreElements()) {
158 CategoryNode node = (CategoryNode) children.nextElement();
159 String title = node.getTitle().toLowerCase();
160
161 String pathLC = element.getTitle().toLowerCase();
162 if (title.equals(pathLC)) {
163 categoryAlreadyExists = true;
164
165 parent = node;
166
167 if (parent.isSelected()) {
168 active = true;
169 }
170
171 break;
172 }
173 }
174
175 if (active == false || categoryAlreadyExists == false) {
176 return false;
177 }
178 }
179
180 return (active);
181 }
182
183
184 /***
185 * <p>Method altered by Richard Hurst such that it returns the CategoryNode
186 * corresponding to the CategoryPath</p>
187 *
188 * @param path category path.
189 * @return CategoryNode
190 */
191 public CategoryNode addCategory(CategoryPath path) {
192 CategoryNode root = (CategoryNode) getRoot();
193 CategoryNode parent = root;
194
195 for (int i = 0; i < path.size(); i++) {
196 CategoryElement element = path.categoryElementAt(i);
197
198
199 Enumeration children = parent.children();
200
201 boolean categoryAlreadyExists = false;
202 while (children.hasMoreElements()) {
203 CategoryNode node = (CategoryNode) children.nextElement();
204 String title = node.getTitle().toLowerCase();
205
206 String pathLC = element.getTitle().toLowerCase();
207 if (title.equals(pathLC)) {
208 categoryAlreadyExists = true;
209
210 parent = node;
211 break;
212 }
213 }
214
215 if (categoryAlreadyExists == false) {
216
217 CategoryNode newNode = new CategoryNode(element.getTitle());
218
219
220
221
222
223
224
225 insertNodeInto(newNode, parent, parent.getChildCount());
226 refresh(newNode);
227
228
229 parent = newNode;
230
231 }
232 }
233
234 return parent;
235 }
236
237 public void update(CategoryNode node, boolean selected) {
238 if (node.isSelected() == selected) {
239 return;
240 }
241
242 if (selected) {
243 setParentSelection(node, true);
244 } else {
245 setDescendantSelection(node, false);
246 }
247 }
248
249 public void setDescendantSelection(CategoryNode node, boolean selected) {
250 Enumeration descendants = node.depthFirstEnumeration();
251 CategoryNode current;
252 while (descendants.hasMoreElements()) {
253 current = (CategoryNode) descendants.nextElement();
254
255 if (current.isSelected() != selected) {
256 current.setSelected(selected);
257 nodeChanged(current);
258 }
259 }
260 notifyActionListeners();
261 }
262
263 public void setParentSelection(CategoryNode node, boolean selected) {
264 TreeNode[] nodes = getPathToRoot(node);
265 int len = nodes.length;
266 CategoryNode parent;
267
268
269
270 for (int i = 1; i < len; i++) {
271 parent = (CategoryNode) nodes[i];
272 if (parent.isSelected() != selected) {
273 parent.setSelected(selected);
274 nodeChanged(parent);
275 }
276 }
277 notifyActionListeners();
278 }
279
280
281 public synchronized void addActionListener(ActionListener l) {
282 _listener = AWTEventMulticaster.add(_listener, l);
283 }
284
285 public synchronized void removeActionListener(ActionListener l) {
286 _listener = AWTEventMulticaster.remove(_listener, l);
287 }
288
289 public void resetAllNodeCounts() {
290 Enumeration nodes = getRootCategoryNode().depthFirstEnumeration();
291 CategoryNode current;
292 while (nodes.hasMoreElements()) {
293 current = (CategoryNode) nodes.nextElement();
294 current.resetNumberOfContainedRecords();
295 nodeChanged(current);
296 }
297 }
298
299 /***
300 * <p>Returns the CategoryPath to the specified CategoryNode</p>
301 *
302 * @param node The target CategoryNode
303 * @return CategoryPath
304 */
305 public TreePath getTreePathToRoot(CategoryNode node) {
306 if (node == null) {
307 return null;
308 }
309 return (new TreePath(getPathToRoot(node)));
310 }
311
312
313
314
315 protected void notifyActionListeners() {
316 if (_listener != null) {
317 _listener.actionPerformed(_event);
318 }
319 }
320
321 /***
322 * Fires a nodechanged event on the SwingThread.
323 */
324 protected void refresh(final CategoryNode node) {
325 SwingUtilities.invokeLater(new Runnable() {
326 public void run() {
327 nodeChanged(node);
328 }
329 });
330 }
331
332
333
334
335
336
337
338
339
340 }
341
342
343
344
345
346