KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > contexts > MutableContextManager


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
12 package org.eclipse.ui.internal.contexts;
13
14 import java.util.ArrayList JavaDoc;
15 import java.util.Collection JavaDoc;
16 import java.util.Comparator JavaDoc;
17 import java.util.HashMap JavaDoc;
18 import java.util.HashSet JavaDoc;
19 import java.util.Iterator JavaDoc;
20 import java.util.Map JavaDoc;
21 import java.util.Set JavaDoc;
22 import java.util.SortedSet JavaDoc;
23 import java.util.TreeMap JavaDoc;
24 import java.util.TreeSet JavaDoc;
25 import java.util.WeakHashMap JavaDoc;
26
27 import org.eclipse.core.runtime.Platform;
28 import org.eclipse.ui.contexts.ContextEvent;
29 import org.eclipse.ui.contexts.ContextManagerEvent;
30 import org.eclipse.ui.contexts.IContext;
31 import org.eclipse.ui.contexts.NotDefinedException;
32 import org.eclipse.ui.internal.util.Util;
33
34 public final class MutableContextManager extends AbstractContextManager
35         implements IMutableContextManager {
36
37     /**
38      * A comparator between context identifiers, that sorts them based on depth
39      * within the tree. Context identifiers representing deeper items (i.e.,
40      * items with more ancestors), have lesser values (i.e., would appear
41      * earlier in a set).
42      *
43      * @since 3.0
44      */

45     private class ContextIdDepthComparator implements Comparator JavaDoc {
46
47         /**
48          * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
49          */

50         public final int compare(final Object JavaDoc object1, final Object JavaDoc object2) {
51             final String JavaDoc contextId1 = (String JavaDoc) object1;
52             final String JavaDoc contextId2 = (String JavaDoc) object2;
53             IContext context;
54             String JavaDoc parentId;
55
56             // Get the depth of the first context.
57
int depth1 = 0;
58             context = getContext(contextId1);
59             try {
60                 parentId = context.getParentId();
61                 while (parentId != null) {
62                     depth1++;
63                     context = getContext(parentId);
64                     parentId = context.getParentId();
65                 }
66             } catch (final NotDefinedException e) {
67                 // Do nothing. Stop ascending the ancestry.
68
}
69
70             // Get the depth of the second context.
71
int depth2 = 0;
72             context = getContext(contextId2);
73             try {
74                 parentId = context.getParentId();
75                 while (parentId != null) {
76                     depth2++;
77                     context = getContext(parentId);
78                     parentId = context.getParentId();
79                 }
80             } catch (final NotDefinedException e) {
81                 // Do nothing. Stop ascending the ancestry.
82
}
83
84             // If the contexts are equal depth, then use their identifier.
85
int compare = depth2 - depth1;
86             if (compare == 0) {
87                 compare = contextId1.compareTo(contextId2);
88             }
89             
90             return compare;
91         }
92     }
93
94     /**
95      * A set that contains context identifiers (strings). The set is sorted
96      * based on how many ancestors the corresponding contexts have. Contexts
97      * with no parents appear last, while contexts with the most ancestors
98      * appear first.
99      *
100      * @since 3.0
101      */

102     private class DepthSortedContextIdSet extends TreeSet JavaDoc {
103
104         /**
105          * Constructs a new instance of <code>DepthSortedContextIdSet</code>
106          * with the set to be sorted.
107          *
108          * @param contextIds
109          * A set of context identifiers (strings); this may contain
110          * <code>null</code> values. The set may not be
111          * <code>null</code>, but may be empty.
112          */

113         private DepthSortedContextIdSet(final Set JavaDoc contextIds) {
114             super(new ContextIdDepthComparator());
115             addAll(contextIds);
116         }
117     }
118     
119     static boolean isContextDefinitionChildOf(String JavaDoc ancestor, String JavaDoc id,
120             Map JavaDoc contextDefinitionsById) {
121         Collection JavaDoc visited = new HashSet JavaDoc();
122
123         while (id != null && !visited.contains(id)) {
124             ContextDefinition contextDefinition = (ContextDefinition) contextDefinitionsById
125                     .get(id);
126             visited.add(id);
127
128             if (contextDefinition != null
129                     && Util.equals(id = contextDefinition.getParentId(),
130                             ancestor)) return true;
131         }
132
133         return false;
134     }
135
136     private Map JavaDoc contextContextBindingsByParentContextId = new HashMap JavaDoc();
137
138     private Map JavaDoc contextDefinitionsById = new HashMap JavaDoc();
139
140     private IContextRegistry contextRegistry;
141
142     private Map JavaDoc contextsById = new WeakHashMap JavaDoc();
143
144     private Set JavaDoc definedContextIds = new HashSet JavaDoc();
145
146     private Set JavaDoc enabledContextIds = new HashSet JavaDoc();
147
148     public MutableContextManager() {
149         this(new ExtensionContextRegistry(Platform.getExtensionRegistry()));
150     }
151
152     public MutableContextManager(IContextRegistry contextRegistry) {
153         if (contextRegistry == null) throw new NullPointerException JavaDoc();
154
155         this.contextRegistry = contextRegistry;
156
157         this.contextRegistry
158                 .addContextRegistryListener(new IContextRegistryListener() {
159
160                     public void contextRegistryChanged(
161                             ContextRegistryEvent contextRegistryEvent) {
162                         readRegistry();
163                     }
164                 });
165
166         readRegistry();
167     }
168
169     public IContext getContext(String JavaDoc contextId) {
170         if (contextId == null) throw new NullPointerException JavaDoc();
171
172         Context context = (Context) contextsById.get(contextId);
173
174         if (context == null) {
175             context = new Context(contextId);
176             updateContext(context);
177             contextsById.put(contextId, context);
178         }
179
180         return context;
181     }
182
183     public SortedSet JavaDoc getDefinedContextIds() {
184         return new DepthSortedContextIdSet(definedContextIds);
185     }
186
187     public SortedSet JavaDoc getEnabledContextIds() {
188         return new DepthSortedContextIdSet(enabledContextIds);
189     }
190
191     private void notifyContexts(Map JavaDoc contextEventsByContextId) {
192         for (Iterator JavaDoc iterator = contextEventsByContextId.entrySet().iterator(); iterator
193                 .hasNext();) {
194             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) iterator.next();
195             String JavaDoc contextId = (String JavaDoc) entry.getKey();
196             ContextEvent contextEvent = (ContextEvent) entry.getValue();
197             Context context = (Context) contextsById.get(contextId);
198
199             if (context != null) context.fireContextChanged(contextEvent);
200         }
201     }
202
203     private void readRegistry() {
204         Collection JavaDoc contextDefinitions = new ArrayList JavaDoc();
205         contextDefinitions.addAll(contextRegistry.getContextDefinitions());
206         Map JavaDoc contextDefinitionsById = new HashMap JavaDoc(ContextDefinition
207                 .contextDefinitionsById(contextDefinitions, false));
208
209         for (Iterator JavaDoc iterator = contextDefinitionsById.values().iterator(); iterator
210                 .hasNext();) {
211             ContextDefinition contextDefinition = (ContextDefinition) iterator
212                     .next();
213             String JavaDoc name = contextDefinition.getName();
214
215             if (name == null || name.length() == 0) iterator.remove();
216         }
217
218         for (Iterator JavaDoc iterator = contextDefinitionsById.keySet().iterator(); iterator
219                 .hasNext();)
220             if (!isContextDefinitionChildOf(null, (String JavaDoc) iterator.next(),
221                     contextDefinitionsById)) iterator.remove();
222         this.contextDefinitionsById = contextDefinitionsById;
223         boolean definedContextIdsChanged = false;
224         Set JavaDoc definedContextIds = new HashSet JavaDoc(contextDefinitionsById.keySet());
225         Set JavaDoc previouslyDefinedContextIds = null;
226
227         if (!definedContextIds.equals(this.definedContextIds)) {
228             previouslyDefinedContextIds = this.definedContextIds;
229             this.definedContextIds = definedContextIds;
230             definedContextIdsChanged = true;
231         }
232
233         Map JavaDoc contextEventsByContextId = updateContexts(contextsById.keySet());
234
235         if (definedContextIdsChanged)
236                 fireContextManagerChanged(new ContextManagerEvent(this,
237                         definedContextIdsChanged, false,
238                         previouslyDefinedContextIds, null));
239
240         if (contextEventsByContextId != null)
241                 notifyContexts(contextEventsByContextId);
242     }
243
244     public void setEnabledContextIds(Set JavaDoc enabledContextIds) {
245         enabledContextIds = Util.safeCopy(enabledContextIds, String JavaDoc.class);
246         boolean contextManagerChanged = false;
247         Map JavaDoc contextEventsByContextId = null;
248         Set JavaDoc previouslyEnabledContextIds = null;
249
250         if (!this.enabledContextIds.equals(enabledContextIds)) {
251             previouslyEnabledContextIds = this.enabledContextIds;
252             this.enabledContextIds = enabledContextIds;
253             contextManagerChanged = true;
254             contextEventsByContextId = updateContexts(contextsById.keySet());
255         }
256
257         if (contextEventsByContextId != null)
258                 notifyContexts(contextEventsByContextId);
259
260         if (contextManagerChanged)
261                 fireContextManagerChanged(new ContextManagerEvent(this, false,
262                         true, null, previouslyEnabledContextIds));
263     }
264
265     private ContextEvent updateContext(Context context) {
266         Set JavaDoc contextContextBindings = (Set JavaDoc) contextContextBindingsByParentContextId
267                 .get(context.getId());
268         ContextDefinition contextDefinition = (ContextDefinition) contextDefinitionsById
269                 .get(context.getId());
270         boolean definedChanged = context.setDefined(contextDefinition != null);
271         boolean enabledChanged = context.setEnabled(enabledContextIds
272                 .contains(context.getId()));
273         boolean nameChanged = context
274                 .setName(contextDefinition != null ? contextDefinition
275                         .getName() : null);
276         boolean parentIdChanged = context
277                 .setParentId(contextDefinition != null ? contextDefinition
278                         .getParentId() : null);
279
280         if (definedChanged || enabledChanged || nameChanged || parentIdChanged)
281             return new ContextEvent(context, definedChanged, enabledChanged,
282                     nameChanged, parentIdChanged);
283         else
284             return null;
285     }
286
287     private Map JavaDoc updateContexts(Collection JavaDoc contextIds) {
288         Map JavaDoc contextEventsByContextId = new TreeMap JavaDoc();
289
290         for (Iterator JavaDoc iterator = contextIds.iterator(); iterator.hasNext();) {
291             String JavaDoc contextId = (String JavaDoc) iterator.next();
292             Context context = (Context) contextsById.get(contextId);
293
294             if (context != null) {
295                 ContextEvent contextEvent = updateContext(context);
296
297                 if (contextEvent != null)
298                         contextEventsByContextId.put(contextId, contextEvent);
299             }
300         }
301
302         return contextEventsByContextId;
303     }
304 }
305
Popular Tags