KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > debug > internal > ui > views > variables > VariablesViewContentProvider


1 /*******************************************************************************
2  * Copyright (c) 2000, 2004 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.debug.internal.ui.views.variables;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.HashMap JavaDoc;
15 import java.util.Iterator JavaDoc;
16 import java.util.List JavaDoc;
17
18 import org.eclipse.core.runtime.CoreException;
19 import org.eclipse.debug.core.DebugException;
20 import org.eclipse.debug.core.DebugPlugin;
21 import org.eclipse.debug.core.ILogicalStructureType;
22 import org.eclipse.debug.core.model.IDebugElement;
23 import org.eclipse.debug.core.model.IIndexedValue;
24 import org.eclipse.debug.core.model.IStackFrame;
25 import org.eclipse.debug.core.model.IValue;
26 import org.eclipse.debug.core.model.IVariable;
27 import org.eclipse.debug.internal.ui.DebugUIPlugin;
28 import org.eclipse.debug.internal.ui.views.IDebugExceptionHandler;
29 import org.eclipse.debug.ui.IDebugView;
30 import org.eclipse.jface.preference.IPreferenceStore;
31 import org.eclipse.jface.viewers.ITreeContentProvider;
32 import org.eclipse.jface.viewers.Viewer;
33
34 /**
35  * Provide the contents for a variables viewer.
36  */

37 public class VariablesViewContentProvider implements ITreeContentProvider {
38     
39     /**
40      * The view that owns this content provider.
41      */

42     private IDebugView fDebugView;
43     
44     /**
45      * A table that maps children to their parent element
46      * such that this content provider can walk back up the
47      * parent chain (since values do not know their
48      * parent).
49      * Map of <code>IVariable</code> (child) -> <code>IVariable</code> (parent).
50      */

51     private HashMap JavaDoc fParentCache;
52     
53     /**
54      * Handler for exceptions as content is retrieved
55      */

56     private IDebugExceptionHandler fExceptionHandler = null;
57     
58     /**
59      * Flag indicating whether contributed content providers should be used or not.
60      */

61     private boolean fUseObjectBrowsers;
62     
63     /**
64      * Constructs a new provider
65      */

66     public VariablesViewContentProvider(IDebugView view) {
67         fParentCache = new HashMap JavaDoc(10);
68         setDebugView(view);
69     }
70
71     /**
72      * Returns the <code>IVariable</code>s for the given <code>IDebugElement</code>.
73      */

74     public Object JavaDoc[] getElements(Object JavaDoc parent) {
75         return getChildren(parent);
76     }
77
78     /**
79      * @see ITreeContentProvider#getChildren(Object)
80      */

81     public Object JavaDoc[] getChildren(Object JavaDoc parent) {
82         Object JavaDoc[] children= null;
83         try {
84             if (parent instanceof IStackFrame) {
85                 children = ((IStackFrame)parent).getVariables();
86             } else if (parent instanceof IVariable) {
87                 IVariable variable = (IVariable)parent;
88                 IValue value = variable.getValue();
89                 children = getModelSpecificChildren(variable, value);
90             }
91             if (children != null) {
92                 cache(parent, children);
93                 return children;
94             }
95         } catch (DebugException de) {
96             if (getExceptionHandler() != null) {
97                 getExceptionHandler().handleException(de);
98             } else {
99                 DebugUIPlugin.log(de);
100             }
101         }
102         return new Object JavaDoc[0];
103     }
104     
105     protected IVariable[] getModelSpecificChildren(IDebugElement parent, IValue value) throws DebugException {
106         if (value== null) {
107             return new IVariable[0];
108         }
109         return getValueChildren(parent, value);
110     }
111     
112     /**
113      * Returns children for the given value, creating array paritions if required
114      *
115      * @param parent expression or variable containing the given value
116      * @param value the value to retrieve children for
117      * @return children for the given value, creating array paritions if required
118      * @throws DebugException
119      */

120     protected IVariable[] getValueChildren(IDebugElement parent, IValue value) throws DebugException {
121         if (value == null) {
122             return null;
123         }
124         IValue logicalValue = getLogicalValue(value);
125         if (logicalValue instanceof IIndexedValue) {
126             IIndexedValue indexedValue = (IIndexedValue)logicalValue;
127             int partitionSize = computeParitionSize(indexedValue);
128             if (partitionSize > 1) {
129                 int offset = indexedValue.getInitialOffset();
130                 int length = indexedValue.getSize();
131                 int numPartitions = length / partitionSize;
132                 int remainder = length % partitionSize;
133                 if (remainder > 0) {
134                     numPartitions++;
135                 }
136                 IVariable[] partitions = new IVariable[numPartitions];
137                 for (int i = 0; i < (numPartitions - 1); i++) {
138                     partitions[i] = new IndexedVariablePartition(parent, indexedValue, offset, partitionSize);
139                     offset = offset + partitionSize;
140                 }
141                 if (remainder == 0) {
142                     remainder = partitionSize;
143                 }
144                 partitions[numPartitions - 1] = new IndexedVariablePartition(parent, indexedValue, offset, remainder);
145                 return partitions;
146             }
147         }
148         if (logicalValue == null) {
149             // safeguard against an structure type returning null
150
logicalValue = value;
151         }
152         return logicalValue.getVariables();
153     }
154     
155     /**
156      * Returns the partition size to use for the given indexed value.
157      * The partition size is computed by determining the number of levels
158      * that an indexed collection must be nested in order to partition
159      * the collection sub-collections of the preferred partition size.
160      *
161      * @param value indexed value
162      * @return size of paritions the value should be subdivided into
163      */

164     private int computeParitionSize(IIndexedValue value) {
165         int partitionSize = 1;
166         try {
167             int length = value.getSize();
168             int partitionDepth = 0;
169             int preferredSize = getArrayPartitionSize();
170             int remainder = length % preferredSize;
171             length = length / preferredSize;
172             while (length > 0) {
173                 if (remainder == 0 && length == 1) {
174                     break;
175                 }
176                 partitionDepth++;
177                 remainder = length % preferredSize;
178                 length = length / preferredSize;
179             }
180             for (int i = 0; i < partitionDepth; i++) {
181                 partitionSize = partitionSize * preferredSize;
182             }
183         } catch (DebugException e) {
184         }
185         return partitionSize;
186     }
187
188     /**
189      * Returns any logical value for the raw value.
190      *
191      * @param value
192      * @return
193      */

194     private IValue getLogicalValue(IValue value) {
195         if (isShowLogicalStructure()) {
196             ILogicalStructureType[] types = DebugPlugin.getLogicalStructureTypes(value);
197             if (types.length > 0) {
198                 IPreferenceStore store = DebugUIPlugin.getDefault().getPreferenceStore();
199                 ILogicalStructureType type = null;
200                 boolean exist = false;
201                 for (int i = 0; i < types.length; i++) {
202                     String JavaDoc key = VariablesView.LOGICAL_STRUCTURE_TYPE_PREFIX + types[i].getId();
203                     int setting = store.getInt(key);
204                     // 0 = never used, 1 = on, -1 = off
205
if (setting != 0) {
206                         exist = true;
207                         if (setting == 1) {
208                             type = types[i];
209                             break;
210                         }
211                     } else {
212                         store.setValue(types[i].getId(), -1);
213                     }
214                 }
215                 if (type == null && !exist) {
216                     type = types[0];
217                     // choose first by default
218
store.setValue(VariablesView.LOGICAL_STRUCTURE_TYPE_PREFIX + type.getId(), 1);
219                 }
220                 if (type != null) {
221                     try {
222                         return type.getLogicalStructure(value);
223                     } catch (CoreException e) {
224                         // unable to display logical structure
225
}
226                 }
227             }
228         }
229         return value;
230     }
231
232     /**
233      * Caches the given elememts as children of the given
234      * parent.
235      *
236      * @param parent parent element
237      * @param children children elements
238      */

239     protected void cache(Object JavaDoc parent, Object JavaDoc[] children) {
240         for (int i = 0; i < children.length; i++) {
241             Object JavaDoc child = children[i];
242             // avoid cycles in the cache, which can happen for
243
// recursive data structures
244
if (!fParentCache.containsKey(child)) {
245                 fParentCache.put(child, parent);
246             }
247         }
248     }
249     
250     /**
251      * @see ITreeContentProvider#getParent(Object)
252      */

253     public Object JavaDoc getParent(Object JavaDoc item) {
254         return fParentCache.get(item);
255     }
256
257     /**
258      * Unregisters this content provider from the debug plugin so that
259      * this object can be garbage-collected.
260      */

261     public void dispose() {
262         fParentCache= null;
263         setExceptionHandler(null);
264     }
265     
266     protected void clearCache() {
267         if (fParentCache != null) {
268             fParentCache.clear();
269         }
270     }
271     
272     /**
273      * Remove the cached parent for the given children
274      *
275      * @param children for which to remove cached parents
276      */

277     public void removeCache(Object JavaDoc[] children) {
278         if (fParentCache == null) {
279             return;
280         }
281         for (int i = 0; i < children.length; i++) {
282             fParentCache.remove(children[i]);
283         }
284     }
285     
286     /**
287      * @see ITreeContentProvider#hasChildren(Object)
288      */

289     public boolean hasChildren(Object JavaDoc element) {
290         try {
291             if (element instanceof IVariable) {
292                 if (element instanceof IndexedVariablePartition) {
293                     return true;
294                 }
295                 element = ((IVariable)element).getValue();
296             }
297             if (element instanceof IValue) {
298                 return ((IValue)element).hasVariables();
299             }
300             if (element instanceof IStackFrame) {
301                 return ((IStackFrame)element).hasVariables();
302             }
303         } catch (DebugException de) {
304             DebugUIPlugin.log(de);
305             return false;
306         }
307         return false;
308     }
309         
310     /**
311      * @see IContentProvider#inputChanged(Viewer, Object, Object)
312      */

313     public void inputChanged(Viewer viewer, Object JavaDoc oldInput, Object JavaDoc newInput) {
314         clearCache();
315     }
316     
317     /**
318      * Return all cached decendants of the given parent.
319      *
320      * @param parent the element whose decendants are to be calculated
321      * @return list of decendants that have been cached for
322      * the given parent
323      */

324     public List JavaDoc getCachedDecendants(Object JavaDoc parent) {
325         Iterator JavaDoc children = fParentCache.keySet().iterator();
326         List JavaDoc cachedChildren = new ArrayList JavaDoc(10);
327         while (children.hasNext()) {
328             Object JavaDoc child = children.next();
329             if (isCachedDecendant(child, parent)) {
330                 cachedChildren.add(child);
331             }
332         }
333         return cachedChildren;
334     }
335     
336     /**
337      * Returns whether the given child is a cached descendant
338      * of the given parent.
339      *
340      * @return whether the given child is a cached descendant
341      * of the given parent
342      */

343     protected boolean isCachedDecendant(Object JavaDoc child, Object JavaDoc parent) {
344         Object JavaDoc p = getParent(child);
345         while (p != null) {
346             if (p.equals(parent)) {
347                 return true;
348             }
349             p = getParent(p);
350         }
351         return false;
352     }
353     
354     /**
355      * Extract the debug model id from the specified <code>IDebugElement</code>
356      * and return it.
357      */

358     protected String JavaDoc getDebugModelId(IDebugElement debugElement) {
359         return debugElement.getModelIdentifier();
360     }
361
362     /**
363      * Sets an exception handler for this content provider.
364      *
365      * @param handler debug exception handler or <code>null</code>
366      */

367     protected void setExceptionHandler(IDebugExceptionHandler handler) {
368         fExceptionHandler = handler;
369     }
370     
371     /**
372      * Returns the exception handler for this content provider.
373      *
374      * @return debug exception handler or <code>null</code>
375      */

376     protected IDebugExceptionHandler getExceptionHandler() {
377         return fExceptionHandler;
378     }
379     
380     /**
381      * Show logical structure of values
382      */

383     public void setShowLogicalStructure(boolean flag) {
384         fUseObjectBrowsers = flag;
385     }
386     
387     public boolean isShowLogicalStructure() {
388         return fUseObjectBrowsers;
389     }
390     
391     private void setDebugView(IDebugView view) {
392         fDebugView = view;
393     }
394
395     protected IDebugView getDebugView() {
396         return fDebugView;
397     }
398     
399     /**
400      * Returns the number of entries that should be displayed in each
401      * partition of an indexed collection.
402      *
403      * @return the number of entries that should be displayed in each
404      * partition of an indexed collection
405      */

406     protected int getArrayPartitionSize() {
407         if (getDebugView() == null) {
408             // TODO: should fix this with a user pref
409
return 100;
410         }
411         return ((VariablesView)getDebugView()).getArrayPartitionSize();
412     }
413     
414 }
415
416
Popular Tags