KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > debugger > jpda > ui > models > VariablesTreeModelFilter


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.debugger.jpda.ui.models;
21
22 import java.util.Collection JavaDoc;
23 import java.util.HashMap JavaDoc;
24 import java.util.HashSet JavaDoc;
25 import java.util.LinkedList JavaDoc;
26 import java.util.List JavaDoc;
27 import javax.security.auth.RefreshFailedException JavaDoc;
28 import javax.security.auth.Refreshable JavaDoc;
29 import javax.swing.Action JavaDoc;
30 import org.netbeans.api.debugger.jpda.ObjectVariable;
31 import org.netbeans.api.debugger.jpda.Variable;
32 import org.netbeans.spi.debugger.ContextProvider;
33 import org.netbeans.spi.debugger.jpda.VariablesFilter;
34 import org.netbeans.spi.viewmodel.ModelEvent;
35 import org.netbeans.spi.viewmodel.ModelListener;
36 import org.netbeans.spi.viewmodel.NodeActionsProvider;
37 import org.netbeans.spi.viewmodel.NodeActionsProviderFilter;
38 import org.netbeans.spi.viewmodel.NodeModel;
39 import org.netbeans.spi.viewmodel.NodeModelFilter;
40 import org.netbeans.spi.viewmodel.TableModel;
41 import org.netbeans.spi.viewmodel.TableModelFilter;
42 import org.netbeans.spi.viewmodel.TreeModel;
43 import org.netbeans.spi.viewmodel.TreeModelFilter;
44 import org.netbeans.spi.viewmodel.UnknownTypeException;
45 import org.openide.util.RequestProcessor;
46
47 /**
48  * Filters some original tree of nodes (represented by {@link TreeModel}).
49  *
50  * @author Jan Jancura
51  */

52 public class VariablesTreeModelFilter implements TreeModelFilter,
53 NodeModelFilter, TableModelFilter, NodeActionsProviderFilter, Runnable JavaDoc {
54     
55     private ContextProvider lookupProvider;
56     
57     private final Collection JavaDoc modelListeners = new HashSet JavaDoc();
58     
59     private RequestProcessor evaluationRP = new RequestProcessor();
60     
61     private RequestProcessor.Task evaluationTask;
62     
63     private LinkedList JavaDoc evaluationQueue = new LinkedList JavaDoc();
64     
65     
66     public VariablesTreeModelFilter (ContextProvider lookupProvider) {
67         this.lookupProvider = lookupProvider;
68     }
69
70     /**
71      * Returns filtered root of hierarchy.
72      *
73      * @param original the original tree model
74      * @return filtered root of hierarchy
75      */

76     public Object JavaDoc getRoot (TreeModel original) {
77         return original.getRoot ();
78     }
79     
80     static boolean isEvaluated(Object JavaDoc o) {
81         if (o instanceof Refreshable JavaDoc) {
82             return ((Refreshable JavaDoc) o).isCurrent();
83         }
84         return true;
85     }
86     
87     private static void waitToEvaluate(Object JavaDoc o) {
88         if (o instanceof Refreshable JavaDoc) {
89             // waits for the evaluation, the retrieval must already be initiated
90
try {
91                 ((Refreshable JavaDoc) o).refresh();
92             } catch (RefreshFailedException JavaDoc exc) {
93                 // Thrown when interrupted
94
Thread.currentThread().interrupt();
95             }
96         }
97     }
98     
99     private void postEvaluationMonitor(Object JavaDoc o, Runnable JavaDoc whenEvaluated) {
100         synchronized (evaluationQueue) {
101             if (evaluationQueue.contains(o) &&
102                 evaluationQueue.contains(whenEvaluated)) return ;
103             if (evaluationTask == null) {
104                 evaluationTask = evaluationRP.create(this);
105             }
106             evaluationQueue.add(o);
107             evaluationQueue.add(whenEvaluated);
108             evaluationTask.schedule(1);
109         }
110     }
111     
112     public void run() {
113         Object JavaDoc node;
114         do {
115             node = null;
116             Runnable JavaDoc whenEvaluated = null;
117             synchronized (evaluationQueue) {
118                 if (!evaluationQueue.isEmpty()) {
119                     node = evaluationQueue.removeFirst();
120                     whenEvaluated = (Runnable JavaDoc) evaluationQueue.removeFirst();
121                 }
122             }
123             if (node != null) {
124                 waitToEvaluate(node);
125                 if (whenEvaluated != null) {
126                     whenEvaluated.run();
127                 } else {
128                     fireModelChange(new ModelEvent.NodeChanged(this, node));
129                     //System.out.println("FIRE "+node+" evaluated, ID = "+node.hashCode());
130
}
131             }
132         } while (node != null);
133         evaluationTask = null;
134     }
135     
136     /**
137      * Returns filtered children for given parent on given indexes.
138      *
139      * @param original the original tree model
140      * @param parent a parent of returned nodes
141      * @throws NoInformationException if the set of children can not be
142      * resolved
143      * @throws ComputingException if the children resolving process
144      * is time consuming, and will be performed off-line
145      * @throws UnknownTypeException if this TreeModelFilter implementation is not
146      * able to resolve children for given node type
147      *
148      * @return children for given parent on given indexes
149      */

150     public Object JavaDoc[] getChildren (
151         final TreeModel original,
152         final Object JavaDoc parent,
153         final int from,
154         final int to
155     ) throws UnknownTypeException {
156         Object JavaDoc[] ch;
157         VariablesFilter vf = getFilter (parent, true, new Runnable JavaDoc() {
158             public void run() {
159                 fireModelChange(new ModelEvent.NodeChanged(VariablesTreeModelFilter.this,
160                                                            parent,
161                                                            ModelEvent.NodeChanged.CHILDREN_MASK));
162             }
163         });
164         if (vf == null)
165             ch = original.getChildren (parent, from, to);
166         else
167             ch = vf.getChildren (original, (Variable) parent, from, to);
168         return ch;
169     }
170     
171     /**
172      * Returns number of filtered children for given node.
173      *
174      * @param original the original tree model
175      * @param node the parent node
176      * @throws NoInformationException if the set of children can not be
177      * resolved
178      * @throws ComputingException if the children resolving process
179      * is time consuming, and will be performed off-line
180      * @throws UnknownTypeException if this TreeModel implementation is not
181      * able to resolve children for given node type
182      *
183      * @return true if node is leaf
184      */

185     public int getChildrenCount (
186         final TreeModel original,
187         final Object JavaDoc parent
188     ) throws UnknownTypeException {
189         VariablesFilter vf = getFilter (parent, true, new Runnable JavaDoc() {
190             public void run() {
191                 fireModelChange(new ModelEvent.NodeChanged(VariablesTreeModelFilter.this,
192                                                            parent,
193                                                            ModelEvent.NodeChanged.CHILDREN_MASK));
194             }
195         });
196         int count;
197         if (vf == null) {
198             count = original.getChildrenCount (parent);
199         } else {
200             count = vf.getChildrenCount (original, (Variable) parent);
201         }
202         return count;
203     }
204     
205     /**
206      * Returns true if node is leaf.
207      *
208      * @param original the original tree model
209      * @throws UnknownTypeException if this TreeModel implementation is not
210      * able to resolve children for given node type
211      * @return true if node is leaf
212      */

213     public boolean isLeaf (
214         TreeModel original,
215         Object JavaDoc node
216     ) throws UnknownTypeException {
217         VariablesFilter vf = getFilter (node, true, null);
218         if (vf == null)
219             return original.isLeaf (node);
220         return vf.isLeaf (original, (Variable) node);
221     }
222
223     public void addModelListener (ModelListener l) {
224         synchronized (modelListeners) {
225             modelListeners.add(l);
226         }
227     }
228
229     public void removeModelListener (ModelListener l) {
230         synchronized (modelListeners) {
231             modelListeners.remove(l);
232         }
233     }
234     
235     private void fireModelChange(ModelEvent me) {
236         Object JavaDoc[] listeners;
237         synchronized (modelListeners) {
238             listeners = modelListeners.toArray();
239         }
240         for (int i = 0; i < listeners.length; i++) {
241             ((ModelListener) listeners[i]).modelChanged(me);
242         }
243     }
244     
245     
246     // NodeModelFilter
247

248     public String JavaDoc getDisplayName (final NodeModel original, final Object JavaDoc node)
249     throws UnknownTypeException {
250         final String JavaDoc[] unfilteredDisplayName = new String JavaDoc[] { null };
251         VariablesFilter vf = getFilter (node, true, new Runnable JavaDoc() {
252             public void run() {
253                 VariablesFilter vf = getFilter (node, false, null);
254                 if (vf == null) return ;
255                 String JavaDoc filteredDisplayName;
256                 try {
257                     filteredDisplayName = vf.getDisplayName (original, (Variable) node);
258                 } catch (UnknownTypeException utex) {
259                     // still do fire
260
filteredDisplayName = utex.toString();
261                 }
262                 if (!filteredDisplayName.equals(unfilteredDisplayName[0])) {
263                     fireModelChange(new ModelEvent.NodeChanged(VariablesTreeModelFilter.this,
264                             node, ModelEvent.NodeChanged.DISPLAY_NAME_MASK));
265                 }
266             }
267         });
268         if (vf == null) {
269             String JavaDoc displayName = original.getDisplayName (node);
270             unfilteredDisplayName[0] = displayName;
271             return displayName;
272         } else {
273             return vf.getDisplayName (original, (Variable) node);
274         }
275     }
276     
277     public String JavaDoc getIconBase (final NodeModel original, final Object JavaDoc node)
278     throws UnknownTypeException {
279         final String JavaDoc[] unfilteredIconBase = new String JavaDoc[] { null };
280         VariablesFilter vf = getFilter (node, true, new Runnable JavaDoc() {
281             public void run() {
282                 VariablesFilter vf = getFilter (node, false, null);
283                 if (vf == null) return ;
284                 String JavaDoc filteredIconBase;
285                 try {
286                     filteredIconBase = vf.getIconBase (original, (Variable) node);
287                 } catch (UnknownTypeException utex) {
288                     // still do fire
289
filteredIconBase = utex.toString();
290                 }
291                 if (!filteredIconBase.equals(unfilteredIconBase[0])) {
292                     fireModelChange(new ModelEvent.NodeChanged(VariablesTreeModelFilter.this,
293                             node, ModelEvent.NodeChanged.ICON_MASK));
294                 }
295             }
296         });
297         if (vf == null) {
298             String JavaDoc iconBase = original.getIconBase (node);
299             unfilteredIconBase[0] = iconBase;
300             return iconBase;
301         } else {
302             return vf.getIconBase (original, (Variable) node);
303         }
304     }
305     
306     public String JavaDoc getShortDescription (final NodeModel original, final Object JavaDoc node)
307     throws UnknownTypeException {
308         final String JavaDoc[] unfilteredShortDescription = new String JavaDoc[] { null };
309         VariablesFilter vf = getFilter (node, true, new Runnable JavaDoc() {
310             public void run() {
311                 VariablesFilter vf = getFilter (node, false, null);
312                 if (vf == null) return ;
313                 String JavaDoc filteredShortDescription;
314                 try {
315                     filteredShortDescription = vf.getShortDescription (original, (Variable) node);
316                 } catch (UnknownTypeException utex) {
317                     // still do fire
318
filteredShortDescription = utex.toString();
319                 }
320                 if (!filteredShortDescription.equals(unfilteredShortDescription[0])) {
321                     fireModelChange(new ModelEvent.NodeChanged(VariablesTreeModelFilter.this,
322                             node, ModelEvent.NodeChanged.SHORT_DESCRIPTION_MASK));
323                 }
324             }
325         });
326         if (vf == null) {
327             return original.getShortDescription (node);
328         } else {
329             return vf.getShortDescription (original, (Variable) node);
330         }
331     }
332     
333     
334     // NodeActionsProviderFilter
335

336     public Action JavaDoc[] getActions (
337         NodeActionsProvider original,
338         Object JavaDoc node
339     ) throws UnknownTypeException {
340         VariablesFilter vf = getFilter (node, true, null);
341         if (vf == null)
342             return original.getActions (node);
343         return vf.getActions (original, (Variable) node);
344     }
345     
346     public void performDefaultAction (
347         NodeActionsProvider original,
348         Object JavaDoc node
349     ) throws UnknownTypeException {
350         VariablesFilter vf = getFilter (node, true, null);
351         if (vf == null)
352             original.performDefaultAction (node);
353         else
354             vf.performDefaultAction (original, (Variable) node);
355     }
356     
357     
358     // TableModelFilter
359

360     public Object JavaDoc getValueAt (
361         TableModel original,
362         Object JavaDoc row,
363         String JavaDoc columnID
364     ) throws UnknownTypeException {
365         Object JavaDoc value;
366         VariablesFilter vf = getFilter (row, false, null);
367         if (vf == null) {
368             value = original.getValueAt (row, columnID);
369         } else {
370             value = vf.getValueAt (original, (Variable) row, columnID);
371         }
372         return value;
373     }
374     
375     public boolean isReadOnly (
376         TableModel original,
377         Object JavaDoc row,
378         String JavaDoc columnID
379     ) throws UnknownTypeException {
380         VariablesFilter vf = getFilter (row, true, null);
381         if (vf == null)
382             return original.isReadOnly (row, columnID);
383         return vf.isReadOnly (original, (Variable) row, columnID);
384     }
385     
386     public void setValueAt (
387         TableModel original,
388         Object JavaDoc row,
389         String JavaDoc columnID,
390         Object JavaDoc value
391     ) throws UnknownTypeException {
392         VariablesFilter vf = getFilter (row, false, null);
393         if (vf == null)
394             original.setValueAt (row, columnID, value);
395         else
396             vf.setValueAt (original, (Variable) row, columnID, value);
397     }
398     
399     
400     // helper methods ..........................................................
401

402     private HashMap JavaDoc typeToFilter;
403     private HashMap JavaDoc ancestorToFilter;
404     
405     /**
406      * @param o The object to get the filter for
407      * @param checkEvaluated Whether we should check if the object was already evaluated
408      * @param whenEvaluated If the object is not yet evaluated, <code>null</code>
409      * will be returned and <code>whenEvaluated.run()<code>
410      * will be executed when the object becomes evaluated.
411      * @return The filter or <code>null</code>.
412      */

413     private VariablesFilter getFilter (Object JavaDoc o, boolean checkEvaluated, Runnable JavaDoc whenEvaluated) {
414         if (typeToFilter == null) {
415             typeToFilter = new HashMap JavaDoc ();
416             ancestorToFilter = new HashMap JavaDoc ();
417             List JavaDoc l = lookupProvider.lookup (null, VariablesFilter.class);
418             int i, k = l.size ();
419             for (i = 0; i < k; i++) {
420                 VariablesFilter f = (VariablesFilter) l.get (i);
421                 String JavaDoc[] types = f.getSupportedAncestors ();
422                 int j, jj = types.length;
423                 for (j = 0; j < jj; j++)
424                     ancestorToFilter.put (types [j], f);
425                 types = f.getSupportedTypes ();
426                 jj = types.length;
427                 for (j = 0; j < jj; j++)
428                     typeToFilter.put (types [j], f);
429             }
430         }
431         
432         if (typeToFilter.size() == 0) return null; // Optimization for corner case
433

434         if (!(o instanceof Variable)) return null;
435         
436         Variable v = (Variable) o;
437         
438         if (checkEvaluated) {
439             if (!isEvaluated(v)) {
440                 if (whenEvaluated != null) {
441                     postEvaluationMonitor(o, whenEvaluated);
442                 }
443                 return null;
444             }
445         }
446         
447         String JavaDoc type = v.getType ();
448         VariablesFilter vf = (VariablesFilter) typeToFilter.get (type);
449         if (vf != null) return vf;
450         
451         if (!(o instanceof ObjectVariable)) return null;
452         ObjectVariable ov = (ObjectVariable) o;
453         ov = ov.getSuper ();
454         while (ov != null) {
455             type = ov.getType ();
456             vf = (VariablesFilter) ancestorToFilter.get (type);
457             if (vf != null) return vf;
458             ov = ov.getSuper ();
459         }
460         return null;
461     }
462
463 }
464
Popular Tags