View Javadoc
1   package net.logAnalyzer.gui.messages;
2   
3   import java.awt.BorderLayout;
4   import java.awt.Dimension;
5   import java.awt.GridLayout;
6   import java.awt.event.ActionEvent;
7   import java.awt.event.ActionListener;
8   import java.util.Hashtable;
9   
10  import javax.swing.JButton;
11  import javax.swing.JComboBox;
12  import javax.swing.JPanel;
13  import javax.swing.JScrollPane;
14  import javax.swing.JSeparator;
15  import javax.swing.JTextField;
16  import javax.swing.JToolBar;
17  import javax.swing.JTree;
18  import javax.swing.event.TreeSelectionEvent;
19  import javax.swing.event.TreeSelectionListener;
20  import javax.swing.tree.DefaultMutableTreeNode;
21  import javax.swing.tree.DefaultTreeModel;
22  import javax.swing.tree.TreeNode;
23  
24  import net.logAnalyzer.converters.LAConverter;
25  import net.logAnalyzer.gui.messages.filters.AndFilter;
26  import net.logAnalyzer.gui.messages.filters.ContainsFilter;
27  import net.logAnalyzer.gui.messages.filters.EqualFilter;
28  import net.logAnalyzer.gui.messages.filters.GreaterFilter;
29  import net.logAnalyzer.gui.messages.filters.LAMessagesFilter;
30  import net.logAnalyzer.gui.messages.filters.LowerFilter;
31  import net.logAnalyzer.gui.messages.filters.NotFilter;
32  import net.logAnalyzer.gui.messages.filters.OperatorFilter;
33  import net.logAnalyzer.gui.messages.filters.OrFilter;
34  import net.logAnalyzer.gui.messages.filters.StartWithFilter;
35  import net.logAnalyzer.gui.messages.filters.UnaryFilter;
36  import net.logAnalyzer.gui.messages.filters.YesFilter;
37  import net.logAnalyzer.handlers.LALogHandler;
38  import net.logAnalyzer.handlers.LALogHandlerListener;
39  import net.logAnalyzer.resources.LAResourceBundle;
40  
41  public class FiltersManager extends JPanel implements ActionListener,
42          TreeSelectionListener, LALogHandlerListener {
43      private static final long serialVersionUID = 1L;
44  
45      /***
46       * View displaying the tree.
47       */
48      private FilteredMessagesView view;
49  
50      /***
51       * View attributes.
52       */
53      private Hashtable attributes;
54  
55      /***
56       * Filters tree.
57       */
58      private JTree filtersTree;
59  
60      /***
61       * Converters list.
62       */
63      private JComboBox convertersList;
64  
65      private static final String FILTER_TYPE_EQUAL = "x = y";
66  
67      private static final String FILTER_TYPE_GREATER = "x > y";
68  
69      private static final String FILTER_TYPE_LOWER = "x < y";
70  
71      private static final String FILTER_TYPE_START = "START WITH";
72  
73      private static final String FILTER_TYPE_CONTAINS = "CONTAINS";
74  
75      private static final String FILTER_TYPE_AND = "AND";
76  
77      private static final String FILTER_TYPE_OR = "OR";
78  
79      private static final String FILTER_TYPE_NOT = "NOT";
80  
81      /***
82       * Filters types list.
83       */
84      private JComboBox filtersList = new JComboBox(new String[] {
85              FILTER_TYPE_EQUAL, FILTER_TYPE_GREATER, FILTER_TYPE_LOWER,
86              FILTER_TYPE_START, FILTER_TYPE_CONTAINS, FILTER_TYPE_AND,
87              FILTER_TYPE_OR, FILTER_TYPE_NOT });
88  
89      /***
90       * Input for filters check value.
91       */
92      private JTextField checkValue;
93  
94      /***
95       * Tree model.
96       */
97      private DefaultTreeModel treeModel;
98  
99      /***
100      * New filter button.
101      */
102     private JButton newFilterButton;
103 
104     /***
105      * Delete filter button.
106      */
107     private JButton deleteFilterButton;
108 
109     /***
110      * Start filtering button.
111      */
112     private JButton startFilteringButton;
113 
114     /***
115      * Start filtering button.
116      */
117     private JButton stopFilteringButton;
118 
119     /***
120      * Root node containing the filter.
121      */
122     private DefaultMutableTreeNode rootFilter;
123 
124     /***
125      * Constructs a new filters manager with the specified attributes.
126      * 
127      * @param view
128      *            View displaying the componenet.
129      * @param attributes
130      *            Component attributes.
131      */
132     public FiltersManager(FilteredMessagesView view, Hashtable attributes) {
133         super(new BorderLayout());
134         this.view = view;
135         this.attributes = attributes;
136         setPreferredSize(new Dimension(250, 200));
137         addComponents();
138     }
139 
140     /***
141      * Returns the filer manager attributes.
142      * 
143      * @return Attributes.
144      */
145     protected Hashtable getAttributes() {
146         return attributes;
147     }
148 
149     /***
150      * Adds components.
151      */
152     public void addComponents() {
153         // Add commands panel
154         JPanel commandPanel = new JPanel(new BorderLayout());
155         add(commandPanel, BorderLayout.NORTH);
156         // Add toolbar
157         JToolBar toolbar = new JToolBar(JToolBar.HORIZONTAL);
158         toolbar.setFloatable(false);
159         toolbar.setRollover(true);
160         toolbar.setFocusable(false);
161         commandPanel.add(toolbar, BorderLayout.NORTH);
162         // New filter button
163         newFilterButton = new JButton(LAResourceBundle
164                 .getIcon("FilteredMessagesView.filters.newfilter.icon"));
165         newFilterButton.setToolTipText(LAResourceBundle
166                 .getLocalizedString("FilteredMessagesView.filters.newfilter"));
167         newFilterButton.addActionListener(this);
168         toolbar.add(newFilterButton);
169         // Delete filter button
170         deleteFilterButton = new JButton(LAResourceBundle
171                 .getIcon("FilteredMessagesView.filters.deletefilter.icon"));
172         deleteFilterButton
173                 .setToolTipText(LAResourceBundle
174                         .getLocalizedString("FilteredMessagesView.filters.deletefilter"));
175         deleteFilterButton.setEnabled(false);
176         deleteFilterButton.addActionListener(this);
177         toolbar.add(deleteFilterButton);
178         // Separator
179         toolbar.add(new JSeparator(JSeparator.VERTICAL));
180         // Start filtering button
181         startFilteringButton = new JButton(LAResourceBundle
182                 .getIcon("FilteredMessagesView.filters.startfiltering.icon"));
183         startFilteringButton
184                 .setToolTipText(LAResourceBundle
185                         .getLocalizedString("FilteredMessagesView.filters.startfiltering"));
186         startFilteringButton.setEnabled(false);
187         startFilteringButton.addActionListener(this);
188         toolbar.add(startFilteringButton);
189         // Stop filtering button
190         stopFilteringButton = new JButton(LAResourceBundle
191                 .getIcon("FilteredMessagesView.filters.stopfiltering.icon"));
192         stopFilteringButton
193                 .setToolTipText(LAResourceBundle
194                         .getLocalizedString("FilteredMessagesView.filters.stopfiltering"));
195         stopFilteringButton.setEnabled(false);
196         stopFilteringButton.setVisible(false);
197         stopFilteringButton.addActionListener(this);
198         toolbar.add(stopFilteringButton);
199 
200         // Add filter fields
201         JPanel fieldsPanel = new JPanel(new GridLayout(0, 1));
202         commandPanel.add(fieldsPanel, BorderLayout.CENTER);
203         // Converters list
204         convertersList = new JComboBox();
205         LAConverter[] converters = view.getFilteredLogHandler().getConverters();
206         for (int i = 0; i < converters.length; i++) {
207             if (!converters[i].isLiteral()) {
208                 convertersList.addItem(converters[i]);
209             }
210         }
211         convertersList
212                 .setToolTipText(LAResourceBundle
213                         .getLocalizedString("FilteredMessagesView.filters.converterslist"));
214         fieldsPanel.add(convertersList);
215         // Filters list
216         filtersList
217                 .setToolTipText(LAResourceBundle
218                         .getLocalizedString("FilteredMessagesView.filters.filterslist"));
219         fieldsPanel.add(filtersList);
220         // Check value
221         checkValue = new JTextField();
222         checkValue.setToolTipText(LAResourceBundle
223                 .getLocalizedString("FilteredMessagesView.filters.checkvalue"));
224         fieldsPanel.add(checkValue);
225 
226         // Add filters tree
227         filtersTree = new JTree();
228         JScrollPane treeScrollPane = new JScrollPane(filtersTree);
229         add(treeScrollPane, BorderLayout.CENTER);
230         // Add root to tree
231         filtersTree.addTreeSelectionListener(this);
232         setFilter(null);
233     }
234 
235     /***
236      * Creates a new filter from the selected item in the filters tree.
237      * 
238      * @return New filter.
239      */
240     private LAMessagesFilter createFilter() {
241         LAMessagesFilter newfilter = null;
242         if (view.getFilteredLogHandler() != null) {
243             if (FILTER_TYPE_AND.equals(filtersList.getSelectedItem())) {
244                 newfilter = new AndFilter(new YesFilter(), new YesFilter());
245             } else if (FILTER_TYPE_OR.equals(filtersList.getSelectedItem())) {
246                 newfilter = new OrFilter(new YesFilter(), new YesFilter());
247             } else if (FILTER_TYPE_NOT.equals(filtersList.getSelectedItem())) {
248                 newfilter = new NotFilter(new YesFilter());
249             } else if (FILTER_TYPE_EQUAL.equals(filtersList.getSelectedItem())) {
250                 newfilter = new EqualFilter(((LAConverter) convertersList
251                         .getSelectedItem()), checkValue.getText());
252             } else if (FILTER_TYPE_GREATER
253                     .equals(filtersList.getSelectedItem())) {
254                 newfilter = new GreaterFilter(((LAConverter) convertersList
255                         .getSelectedItem()), checkValue.getText());
256             } else if (FILTER_TYPE_LOWER.equals(filtersList.getSelectedItem())) {
257                 newfilter = new LowerFilter(((LAConverter) convertersList
258                         .getSelectedItem()), checkValue.getText());
259             } else if (FILTER_TYPE_START.equals(filtersList.getSelectedItem())) {
260                 newfilter = new StartWithFilter(((LAConverter) convertersList
261                         .getSelectedItem()), checkValue.getText());
262             } else if (FILTER_TYPE_CONTAINS.equals(filtersList
263                     .getSelectedItem())) {
264                 newfilter = new ContainsFilter(((LAConverter) convertersList
265                         .getSelectedItem()), checkValue.getText());
266             }
267         }
268         return newfilter;
269     }
270 
271     /***
272      * Sets a new filter as tree root.
273      * 
274      * @param filter
275      *            New root filter.
276      */
277     public void setFilter(LAMessagesFilter filter) {
278         filtersTree.removeAll();
279         rootFilter = null;
280         if (filter != null) {
281             rootFilter = filterToNode(filter);
282         } else {
283             rootFilter = new DefaultMutableTreeNode(
284                     LAResourceBundle
285                             .getLocalizedString("FilteredMessagesView.filters.nofilter"));
286         }
287         treeModel = new DefaultTreeModel(rootFilter);
288         filtersTree.setModel(treeModel);
289     }
290 
291     /***
292      * Recursivelly creates a node from a filter.
293      * 
294      * @param filter
295      *            Filter to convert as node.
296      * @return New node.
297      */
298     private DefaultMutableTreeNode filterToNode(LAMessagesFilter filter) {
299         return filterToNode(filter, null);
300     }
301 
302     /***
303      * Recursivelly creates a node from a filter. If an existing node is
304      * specified, it is modified and returned.
305      * 
306      * @param filter
307      *            Filter to convert as node.
308      * @param existingNode
309      *            Node to modify and return if not <tt>null</tt>.
310      * @return New node or modified node if specified.
311      */
312     private DefaultMutableTreeNode filterToNode(LAMessagesFilter filter,
313             DefaultMutableTreeNode existingNode) {
314         DefaultMutableTreeNode node = existingNode;
315         if (node == null) {
316             node = new DefaultMutableTreeNode();
317         }
318         node.setUserObject(filter);
319         if (filter instanceof UnaryFilter) {
320             setChildren(node, filterToNode(((UnaryFilter) filter).getFilter()));
321             treeModel.nodesWereInserted(node, new int[] { 0 });
322         } else if (filter instanceof OperatorFilter) {
323             DefaultMutableTreeNode[] children = new DefaultMutableTreeNode[] {
324                     filterToNode(((OperatorFilter) filter).getLeft()),
325                     filterToNode(((OperatorFilter) filter).getRight()) };
326             setChildren(node, children);
327         } else if (node.getChildCount() > 0) {
328             removeChildren(node, 0);
329         }
330         return node;
331     }
332 
333     private void setChildren(DefaultMutableTreeNode node,
334             DefaultMutableTreeNode child) {
335         setChildren(node, new DefaultMutableTreeNode[] { child });
336     }
337 
338     private void setChildren(DefaultMutableTreeNode node,
339             DefaultMutableTreeNode[] children) {
340         int countChildren = node.getChildCount();
341         if (children.length < countChildren) {
342             removeChildren(node, children.length);
343         } else if (children.length > countChildren) {
344             int[] indices = new int[children.length - countChildren];
345             for (int i = countChildren; i < children.length; i++) {
346                 indices[i - countChildren] = i;
347                 node.add(children[i]);
348             }
349             treeModel.nodesWereInserted(node, indices);
350         }
351     }
352 
353     /***
354      * Removes node children from the specified index.
355      * 
356      * @param node
357      *            Node to modify
358      * @param fromIndex
359      *            Index of the first child to remove.
360      */
361     private void removeChildren(DefaultMutableTreeNode node, int fromIndex) {
362         TreeNode[] removedChildren = new TreeNode[node.getChildCount()
363                 - fromIndex];
364         int[] childIndices = new int[removedChildren.length];
365         for (int i = 0; i < removedChildren.length; i++) {
366             removedChildren[i] = node.getChildAt(fromIndex);
367             node.remove(fromIndex);
368         }
369         treeModel.nodesWereRemoved(node, childIndices, removedChildren);
370     }
371 
372     /***
373      * Recursively creates a filter from a node tree.
374      * 
375      * @param node
376      * @return New filter
377      */
378     private LAMessagesFilter nodeToFilter(DefaultMutableTreeNode node) {
379         LAMessagesFilter filter = (LAMessagesFilter) node.getUserObject();
380         if (filter instanceof UnaryFilter) {
381             ((UnaryFilter) filter)
382                     .setFilter(nodeToFilter((DefaultMutableTreeNode) node
383                             .getChildAt(0)));
384         } else if (filter instanceof OperatorFilter) {
385             ((OperatorFilter) filter)
386                     .setLeft(nodeToFilter((DefaultMutableTreeNode) node
387                             .getChildAt(0)));
388             ((OperatorFilter) filter)
389                     .setRight(nodeToFilter((DefaultMutableTreeNode) node
390                             .getChildAt(1)));
391         }
392         return filter;
393     }
394 
395     /***
396      * Returns the root filter.
397      * 
398      * @return Root filter.
399      */
400     public LAMessagesFilter getFilter() {
401         if (!hasFilter()) {
402             return null;
403         } else {
404             return nodeToFilter(rootFilter);
405         }
406     }
407 
408     /***
409      * Returns <tt>true</tt> if there is one or more filters.
410      * 
411      * @return <tt>true</tt> if there is a filter.
412      */
413     public boolean hasFilter() {
414         return rootFilter != null
415                 && rootFilter.getUserObject() instanceof LAMessagesFilter
416                 && !(rootFilter.getUserObject() instanceof YesFilter);
417     }
418 
419     /***
420      * Filters action.
421      * 
422      * @param e
423      *            Action event.
424      * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
425      */
426     public void actionPerformed(ActionEvent e) {
427         DefaultMutableTreeNode node = (DefaultMutableTreeNode) filtersTree
428                 .getLastSelectedPathComponent();
429         if (newFilterButton.equals(e.getSource())) {
430             if (rootFilter == null
431                     || (rootFilter.equals(node) && !(rootFilter.getUserObject() instanceof LAMessagesFilter))) {
432                 // Adds root filter
433                 setFilter(createFilter());
434             } else if (rootFilter.equals(node)) {
435                 // Modifies the root filter
436                 setFilter(createFilter());
437             } else if (node != null) {
438                 // Adds a filter to the current node
439                 filterToNode(createFilter(), node);
440                 treeModel.nodeChanged(node);
441                 // setFilter(getFilter());
442             }
443         } else if (node != null && deleteFilterButton.equals((e.getSource()))) {
444             // Deletes the selected node
445             if (rootFilter.equals(node)
446                     && rootFilter.getUserObject() instanceof LAMessagesFilter) {
447                 // Deletes all filters
448                 setFilter(null);
449             } else if (!(node.getUserObject() instanceof YesFilter)) {
450                 // Deletes the selected node
451                 filterToNode(new YesFilter(), node);
452                 treeModel.nodeChanged(node);
453                 // setFilter(getFilter());
454             }
455         } else if (startFilteringButton.equals((e.getSource()))) {
456             // Starts filtering
457             view.startFiltering(getFilter());
458         } else if (stopFilteringButton.equals((e.getSource()))) {
459             // Starts filtering
460             view.stopFiltering();
461         }
462     }
463 
464     /***
465      * Enables or disables filters buttons regarding to the selected node.
466      * 
467      * @param e
468      *            Tree selection event.
469      * @see javax.swing.event.TreeSelectionListener#valueChanged(javax.swing.event.TreeSelectionEvent)
470      */
471     public void valueChanged(TreeSelectionEvent e) {
472         DefaultMutableTreeNode node = (DefaultMutableTreeNode) filtersTree
473                 .getLastSelectedPathComponent();
474 
475         newFilterButton.setEnabled(true);
476         if (node != null && node.getUserObject() != null
477                 && node.getUserObject() instanceof LAMessagesFilter) {
478             deleteFilterButton.setEnabled(true);
479         } else {
480             deleteFilterButton.setEnabled(false);
481         }
482         startFilteringButton.setEnabled(true);
483     }
484 
485     /*
486      * (non-Javadoc)
487      * 
488      * @see net.logAnalyzer.handlers.LALogHandlerListener#startParsing(net.logAnalyzer.handlers.LALogHandler)
489      */
490     public void startParsing(LALogHandler logHandler) {
491         stopFilteringButton.setEnabled(false);
492         startFilteringButton.setVisible(false);
493         stopFilteringButton.setVisible(true);
494         stopFilteringButton.setEnabled(true);
495     }
496 
497     /*
498      * (non-Javadoc)
499      * 
500      * @see net.logAnalyzer.handlers.LALogHandlerListener#stepParsing(net.logAnalyzer.handlers.LALogHandler)
501      */
502     public void stepParsing(LALogHandler logHandler) {
503     }
504 
505     /*
506      * (non-Javadoc)
507      * 
508      * @see net.logAnalyzer.handlers.LALogHandlerListener#endParsing(net.logAnalyzer.handlers.LALogHandler)
509      */
510     public void endParsing(LALogHandler logHandler) {
511         stopFilteringButton.setEnabled(false);
512         stopFilteringButton.setVisible(false);
513         startFilteringButton.setVisible(true);
514         stopFilteringButton.setEnabled(true);
515     }
516 
517 }