KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > services > ExpressionAuthority


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

11
12 package org.eclipse.ui.internal.services;
13
14 import java.util.ArrayList JavaDoc;
15 import java.util.Collection JavaDoc;
16 import java.util.Collections JavaDoc;
17 import java.util.Iterator JavaDoc;
18 import java.util.Map JavaDoc;
19
20 import org.eclipse.core.expressions.EvaluationContext;
21 import org.eclipse.core.expressions.Expression;
22 import org.eclipse.core.expressions.IEvaluationContext;
23 import org.eclipse.jface.viewers.ISelection;
24 import org.eclipse.jface.viewers.IStructuredSelection;
25 import org.eclipse.ui.ISourceProvider;
26 import org.eclipse.ui.ISourceProviderListener;
27 import org.eclipse.ui.ISources;
28
29 /**
30  * <p>
31  * Provides common functionality for evaluating expressions and listening to
32  * {@link ISourceProvider} (i.e., the common event framework for commands).
33  * </p>
34  * <p>
35  * This class is not intended for use outside of the
36  * <code>org.eclipse.ui.workbench</code> plug-in.
37  * </p>
38  *
39  * @since 3.2
40  * @see ISourceProvider
41  * @see ISources
42  * @see Expression
43  * @see IEvaluationContext
44  */

45 public abstract class ExpressionAuthority implements ISourceProviderListener {
46
47     /**
48      * The evaluation context instance to use when evaluating expression. This
49      * context is shared, and so all calls into <code>sourceChanged</code>
50      * must happen on the event thread.
51      */

52     private final IEvaluationContext context;
53
54     /**
55      * The current state of this authority. This is a child of the
56      * {@link #context} that has been given the selection as the default
57      * variable. This value is cleared to <code>null</code> whenever the
58      * selection changes.
59      */

60     private IEvaluationContext currentState = null;
61
62     /**
63      * The collection of source providers used by this authority. This
64      * collection is consulted whenever a contribution is made. This collection
65      * only contains instances of <code>ISourceProvider</code>.
66      */

67     private final Collection JavaDoc providers = new ArrayList JavaDoc();
68
69     /**
70      * Constructs a new instance of <code>ExpressionAuthority</code>.
71      */

72     protected ExpressionAuthority() {
73         context = new EvaluationContext(null, this);
74         context.setAllowPluginActivation(true);
75     }
76
77     /**
78      * Adds a source provider to a list of providers to check when updating.
79      * This also attaches this authority as a listener to the provider.
80      *
81      * @param provider
82      * The provider to add; must not be <code>null</code>.
83      */

84     public final void addSourceProvider(final ISourceProvider provider) {
85         provider.addSourceProviderListener(this);
86         providers.add(provider);
87
88         // Update the current state.
89
final Map JavaDoc currentState = provider.getCurrentState();
90         final Iterator JavaDoc variableItr = currentState.entrySet().iterator();
91         while (variableItr.hasNext()) {
92             final Map.Entry JavaDoc entry = (Map.Entry JavaDoc) variableItr.next();
93             final String JavaDoc variableName = (String JavaDoc) entry.getKey();
94             final Object JavaDoc variableValue = entry.getValue();
95
96             /*
97              * Bug 84056. If we update the active workbench window, then we risk
98              * falling back to that shell when the active shell has registered
99              * as "none".
100              */

101             if ((variableName != null)
102                     && (!ISources.ACTIVE_WORKBENCH_WINDOW_SHELL_NAME
103                             .equals(variableName))) {
104                 changeVariable(variableName, variableValue);
105             }
106         }
107     }
108
109     /**
110      * Removes all of the source provider listeners. Subclasses may extend, but
111      * must not override.
112      */

113     public void dispose() {
114         final Iterator JavaDoc providerItr = providers.iterator();
115         while (providerItr.hasNext()) {
116             final ISourceProvider provider = (ISourceProvider) providerItr
117                     .next();
118             provider.removeSourceProviderListener(this);
119         }
120
121         providers.clear();
122     }
123
124     /**
125      * Returns whether at least one of the <code>IEvaluationResultCache</code>
126      * instances in <code>collection</code> evaluates to <code>true</code>.
127      *
128      * @param collection
129      * The evaluation result caches to check; must not be
130      * <code>null</code>, but may be empty.
131      * @return <code>true</code> if there is at least one expression that
132      * evaluates to <code>true</code>; <code>false</code>
133      * otherwise.
134      */

135     protected final boolean evaluate(final Collection JavaDoc collection) {
136         final Iterator JavaDoc iterator = collection.iterator();
137         while (iterator.hasNext()) {
138             final IEvaluationResultCache cache = (IEvaluationResultCache) iterator
139                     .next();
140             if (evaluate(cache)) {
141                 return true;
142             }
143         }
144
145         return false;
146     }
147
148     /**
149      * Returns whether the <code>IEvaluationResultCache</code> evaluates to
150      * <code>true</code>.
151      *
152      * @param expression
153      * The evaluation result cache to check; must not be
154      * <code>null</code>.
155      * @return <code>true</code> if the expression evaluates to
156      * <code>true</code>; <code>false</code> otherwise.
157      */

158     protected final boolean evaluate(final IEvaluationResultCache expression) {
159         final IEvaluationContext contextWithDefaultVariable = getCurrentState();
160         return expression.evaluate(contextWithDefaultVariable);
161     }
162
163     /**
164      * Creates a new evaluation context based on the current evaluation context
165      * (i.e., the current state), and places the current selection as the
166      * default variable.
167      *
168      * @return An evaluation context that can be used for evaluating
169      * expressions; never <code>null</code>.
170      */

171     public final IEvaluationContext getCurrentState() {
172         if (currentState == null) {
173             final Object JavaDoc defaultVariable = context
174                     .getVariable(ISources.ACTIVE_CURRENT_SELECTION_NAME);
175             final IEvaluationContext contextWithDefaultVariable;
176             if (defaultVariable instanceof IStructuredSelection) {
177                 final IStructuredSelection selection = (IStructuredSelection) defaultVariable;
178                 contextWithDefaultVariable = new EvaluationContext(context,
179                         selection.toList());
180             } else if ((defaultVariable instanceof ISelection)
181                     && (!((ISelection) defaultVariable).isEmpty())) {
182                 contextWithDefaultVariable = new EvaluationContext(context,
183                         Collections.singleton(defaultVariable));
184             } else {
185                 contextWithDefaultVariable = new EvaluationContext(context,
186                         Collections.EMPTY_LIST);
187             }
188             currentState = contextWithDefaultVariable;
189         }
190
191         return currentState;
192     }
193
194     /**
195      * Returns the variable of the given name.
196      *
197      * @param name
198      * The name of the variable to get; must not be <code>null</code>.
199      * @return The variable of the given name; <code>null</code> if none.
200      */

201     protected final Object JavaDoc getVariable(final String JavaDoc name) {
202         return context.getVariable(name);
203     }
204
205     /**
206      * Removes this source provider from the list, and detaches this authority
207      * as a listener.
208      *
209      * @param provider
210      * The provider to remove; must not be <code>null</code>.
211      */

212     public final void removeSourceProvider(final ISourceProvider provider) {
213         provider.removeSourceProviderListener(this);
214         providers.remove(provider);
215
216         final Map JavaDoc currentState = provider.getCurrentState();
217         final Iterator JavaDoc variableItr = currentState.entrySet().iterator();
218         while (variableItr.hasNext()) {
219             final Map.Entry JavaDoc entry = (Map.Entry JavaDoc) variableItr.next();
220             final String JavaDoc variableName = (String JavaDoc) entry.getKey();
221             changeVariable(variableName, null);
222         }
223     }
224
225     /**
226      * Changes the variable of the given name. If the <code>value</code> is
227      * <code>null</code>, then the variable is removed.
228      *
229      * @param name
230      * The name of the variable to change; must not be
231      * <code>null</code>.
232      * @param value
233      * The new value; the variable should be removed if this is
234      * <code>null</code>.
235      */

236     protected final void changeVariable(final String JavaDoc name, final Object JavaDoc value) {
237         if (value == null) {
238             context.removeVariable(name);
239         } else {
240             context.addVariable(name, value);
241         }
242     }
243
244     /**
245      * Carries out the actual source change notification. It assumed that by the
246      * time this method is called, <code>getEvaluationContext()</code> is
247      * up-to-date with the current state of the application.
248      *
249      * @param sourcePriority
250      * A bit mask of all the source priorities that have changed.
251      */

252     protected abstract void sourceChanged(final int sourcePriority);
253
254     /**
255      * Similar to sourceChanged(int) this notifies the subclass about the
256      * change, but using the array of source names that changed instead of the
257      * priority ... int based.
258      * <p>
259      * Clients may override this method.
260      * </p>
261      *
262      * @param sourceNames
263      * The array of names that changed.
264      * @since 3.3
265      */

266     protected void sourceChanged(final String JavaDoc[] sourceNames) {
267         // this is a no-op, since we're late in the game
268
}
269
270     public final void sourceChanged(final int sourcePriority,
271             final Map JavaDoc sourceValuesByName) {
272         // If the selection has changed, invalidate the current state.
273
if (sourceValuesByName
274                 .containsKey(ISources.ACTIVE_CURRENT_SELECTION_NAME)) {
275             currentState = null;
276         }
277
278         final Iterator JavaDoc entryItr = sourceValuesByName.entrySet().iterator();
279         while (entryItr.hasNext()) {
280             final Map.Entry JavaDoc entry = (Map.Entry JavaDoc) entryItr.next();
281             final String JavaDoc sourceName = (String JavaDoc) entry.getKey();
282             final Object JavaDoc sourceValue = entry.getValue();
283             updateEvaluationContext(sourceName, sourceValue);
284         }
285         sourceChanged(sourcePriority, (String JavaDoc[]) sourceValuesByName.keySet()
286                 .toArray(new String JavaDoc[0]));
287     }
288
289     public final void sourceChanged(final int sourcePriority,
290             final String JavaDoc sourceName, final Object JavaDoc sourceValue) {
291         // If the selection has changed, invalidate the current state.
292
if (ISources.ACTIVE_CURRENT_SELECTION_NAME.equals(sourceName)) {
293             currentState = null;
294         }
295
296         updateEvaluationContext(sourceName, sourceValue);
297         sourceChanged(sourcePriority, new String JavaDoc[] { sourceName });
298     }
299
300     /**
301      * @param sourcePriority
302      * @param strings
303      */

304     private void sourceChanged(int sourcePriority, String JavaDoc[] sourceNames) {
305         sourceChanged(sourcePriority);
306         sourceChanged(sourceNames);
307     }
308
309     /**
310      * Updates the evaluation context with the current state from all of the
311      * source providers.
312      */

313     protected final void updateCurrentState() {
314         final Iterator JavaDoc providerItr = providers.iterator();
315         while (providerItr.hasNext()) {
316             final ISourceProvider provider = (ISourceProvider) providerItr
317                     .next();
318             final Map JavaDoc currentState = provider.getCurrentState();
319             final Iterator JavaDoc variableItr = currentState.entrySet().iterator();
320             while (variableItr.hasNext()) {
321                 final Map.Entry JavaDoc entry = (Map.Entry JavaDoc) variableItr.next();
322                 final String JavaDoc variableName = (String JavaDoc) entry.getKey();
323                 final Object JavaDoc variableValue = entry.getValue();
324                 /*
325                  * Bug 84056. If we update the active workbench window, then we
326                  * risk falling back to that shell when the active shell has
327                  * registered as "none".
328                  */

329                 if ((variableName != null)
330                         && (!ISources.ACTIVE_WORKBENCH_WINDOW_SHELL_NAME
331                                 .equals(variableName))) {
332                     changeVariable(variableName, variableValue);
333                 }
334             }
335         }
336     }
337
338     /**
339      * Updates this authority's evaluation context.
340      *
341      * @param name
342      * The name of the variable to update; must not be
343      * <code>null</code>.
344      * @param value
345      * The new value of the variable. If this value is
346      * <code>null</code>, then the variable is removed.
347      */

348     protected void updateEvaluationContext(final String JavaDoc name, final Object JavaDoc value) {
349         if (name != null) {
350             changeVariable(name, value);
351         }
352     }
353 }
354
Popular Tags