KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > texteditor > rulers > RulerColumnRegistry


1 /*******************************************************************************
2  * Copyright (c) 2000, 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 package org.eclipse.ui.texteditor.rulers;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Arrays JavaDoc;
15 import java.util.Collections JavaDoc;
16 import java.util.Comparator JavaDoc;
17 import java.util.HashMap JavaDoc;
18 import java.util.Iterator JavaDoc;
19 import java.util.List JavaDoc;
20 import java.util.ListIterator JavaDoc;
21 import java.util.Map JavaDoc;
22 import java.util.Set JavaDoc;
23
24 import com.ibm.icu.text.MessageFormat;
25
26 import org.eclipse.core.runtime.Assert;
27 import org.eclipse.core.runtime.IConfigurationElement;
28 import org.eclipse.core.runtime.IExtensionRegistry;
29 import org.eclipse.core.runtime.IStatus;
30 import org.eclipse.core.runtime.InvalidRegistryObjectException;
31 import org.eclipse.core.runtime.Platform;
32 import org.eclipse.core.runtime.Status;
33
34 import org.eclipse.ui.internal.texteditor.TextEditorPlugin;
35 import org.eclipse.ui.internal.texteditor.rulers.DAG;
36 import org.eclipse.ui.internal.texteditor.rulers.ExtensionPointHelper;
37 import org.eclipse.ui.internal.texteditor.rulers.RulerColumnMessages;
38 import org.eclipse.ui.internal.texteditor.rulers.RulerColumnPlacementConstraint;
39 import org.eclipse.ui.texteditor.ConfigurationElementSorter;
40
41 /**
42  * A registry for all extensions to the
43  * <code>rulerColumns</code> extension point.
44  *
45  * @since 3.3
46  */

47 public final class RulerColumnRegistry {
48
49     private static final String JavaDoc EXTENSION_POINT= "rulerColumns"; //$NON-NLS-1$
50
private static final String JavaDoc QUALIFIED_EXTENSION_POINT= TextEditorPlugin.PLUGIN_ID + '.' + EXTENSION_POINT;
51     
52     /** The singleton instance. */
53     private static RulerColumnRegistry fgSingleton= null;
54     
55     /**
56      * Returns the default computer registry.
57      * <p>
58      * TODO keep this or add some other singleton, e.g. TextEditorPlugin?
59      * </p>
60      *
61      * @return the singleton instance
62      */

63     public static synchronized RulerColumnRegistry getDefault() {
64         if (fgSingleton == null) {
65             fgSingleton= new RulerColumnRegistry();
66         }
67         
68         return fgSingleton;
69     }
70     
71     /**
72      * All descriptors (element type:
73      * {@link RulerColumnDescriptor}).
74      */

75     private List JavaDoc fDescriptors= null;
76     /**
77      * All descriptors by id (element type: {@link RulerColumnDescriptor}).
78      */

79     private Map JavaDoc fDescriptorMap= null;
80     
81     /**
82      * <code>true</code> if this registry has been loaded.
83      */

84     private boolean fLoaded= false;
85
86     /**
87      * Creates a new instance.
88      */

89     RulerColumnRegistry() {
90     }
91
92     /**
93      * Returns the list of {@link RulerColumnDescriptor}s describing all extensions to the
94      * <code>rulerColumns</code> extension point. The list's iterator traverses the descriptors in
95      * the ordering implied by the placement specifications of the contributions.
96      * <p>
97      * The returned list is unmodifiable and guaranteed to never change. Note that the set of
98      * descriptors may change over time due to dynamic plug-in removal or addition.
99      * </p>
100      *
101      * @return the sorted list of extensions to the <code>rulerColumns</code> extension point
102      * (element type: {@link RulerColumnDescriptor})
103      */

104     public List JavaDoc getColumnDescriptors() {
105         ensureExtensionPointRead();
106         return fDescriptors;
107     }
108     
109     /**
110      * Returns the {@link RulerColumnDescriptor} with the given identity, <code>null</code> if no
111      * such descriptor exists.
112      *
113      * @param id the identity of the ruler contribution as given in the extension point xml.
114      * @return the {@link RulerColumnDescriptor} with the given identity, <code>null</code> if no
115      * such descriptor exists
116      */

117     public RulerColumnDescriptor getColumnDescriptor(String JavaDoc id) {
118         Assert.isLegal(id != null);
119         ensureExtensionPointRead();
120         return (RulerColumnDescriptor) fDescriptorMap.get(id);
121     }
122
123     /**
124      * Ensures that the extensions are read and stored in
125      * <code>fDescriptorsByPartition</code>.
126      */

127     private void ensureExtensionPointRead() {
128         boolean reload;
129         synchronized (this) {
130             reload= !fLoaded;
131             fLoaded= true;
132         }
133         if (reload)
134             reload();
135     }
136
137     /**
138      * Reloads the extensions to the extension point.
139      * <p>
140      * This method can be called more than once in order to reload from
141      * a changed extension registry.
142      * </p>
143      */

144     public void reload() {
145         IExtensionRegistry registry= Platform.getExtensionRegistry();
146         List JavaDoc elements= new ArrayList JavaDoc(Arrays.asList(registry.getConfigurationElementsFor(TextEditorPlugin.PLUGIN_ID, EXTENSION_POINT)));
147         
148         List JavaDoc descriptors= new ArrayList JavaDoc();
149         Map JavaDoc descriptorMap= new HashMap JavaDoc();
150         
151         for (Iterator JavaDoc iter= elements.iterator(); iter.hasNext();) {
152             IConfigurationElement element= (IConfigurationElement) iter.next();
153             try {
154                 RulerColumnDescriptor desc= new RulerColumnDescriptor(element, this);
155                 String JavaDoc id= desc.getId();
156                 if (descriptorMap.containsKey(id)) {
157                     noteDuplicateId(desc);
158                     continue;
159                 }
160                     
161                 descriptors.add(desc);
162                 descriptorMap.put(id, desc);
163             } catch (InvalidRegistryObjectException x) {
164                 /*
165                  * Element is not valid any longer as the contributing plug-in was unloaded or for
166                  * some other reason. Do not include the extension in the list and inform the user
167                  * about it.
168                  */

169                 noteInvalidExtension(element, x);
170             }
171         }
172         
173         sort(descriptors);
174         
175         synchronized (this) {
176             fDescriptors= Collections.unmodifiableList(descriptors);
177             fDescriptorMap= Collections.unmodifiableMap(descriptorMap);
178         }
179     }
180
181     /**
182      * Sorts the column contributions.
183      *
184      * @param descriptors the descriptors to sort
185      */

186     private void sort(List JavaDoc descriptors) {
187         /*
188          * Topological sort of the DAG defined by the plug-in dependencies
189          * 1. TopoSort descriptors by plug-in dependency
190          * 2. Insert into Directed Acyclic Graph
191          * 3. TopoSort DAG: pick the source with the lowest gravity and remove from DAG
192          */

193         ConfigurationElementSorter sorter= new ConfigurationElementSorter() {
194             public IConfigurationElement getConfigurationElement(Object JavaDoc object) {
195                 return ((RulerColumnDescriptor) object).getConfigurationElement();
196             }
197         };
198         Object JavaDoc[] array= descriptors.toArray();
199         sorter.sort(array);
200         
201         Map JavaDoc descriptorsById= new HashMap JavaDoc();
202         for (int i= 0; i < array.length; i++) {
203             RulerColumnDescriptor desc= (RulerColumnDescriptor) array[i];
204             descriptorsById.put(desc.getId(), desc);
205         }
206         
207         DAG dag= new DAG();
208         for (int i= 0; i < array.length; i++) {
209             RulerColumnDescriptor desc= (RulerColumnDescriptor) array[i];
210             dag.addVertex(desc);
211             
212             Set JavaDoc before= desc.getPlacement().getConstraints();
213             for (Iterator JavaDoc it= before.iterator(); it.hasNext();) {
214                 RulerColumnPlacementConstraint constraint= (RulerColumnPlacementConstraint) it.next();
215                 String JavaDoc id= constraint.getId();
216                 RulerColumnDescriptor target= (RulerColumnDescriptor) descriptorsById.get(id);
217                 if (target == null) {
218                     noteUnknownTarget(desc, id);
219                 } else {
220                     boolean success;
221                     if (constraint.isBefore())
222                         success= dag.addEdge(desc, target);
223                     else
224                         success= dag.addEdge(target, desc);
225                     if (!success)
226                         noteCycle(desc, target);
227                 }
228             }
229         }
230         
231         Comparator JavaDoc gravityComp= new Comparator JavaDoc() {
232             public int compare(Object JavaDoc o1, Object JavaDoc o2) {
233                 float diff= ((RulerColumnDescriptor) o1).getPlacement().getGravity() - ((RulerColumnDescriptor) o2).getPlacement().getGravity();
234                 if (diff == 0)
235                     return 0;
236                 if (diff < 0)
237                     return -1;
238                 return 1;
239             }
240         };
241         
242         /* Topological sort - always select the source with the least gravity */
243         Set JavaDoc toProcess= dag.getSources();
244         int index= 0;
245         while (!toProcess.isEmpty()) {
246             Object JavaDoc next= Collections.min(toProcess, gravityComp);
247             array[index]= next;
248             index++;
249             dag.removeVertex(next);
250             toProcess= dag.getSources();
251         }
252         Assert.isTrue(index == array.length);
253         
254         ListIterator JavaDoc it= descriptors.listIterator();
255         for (int i= 0; i < index; i++) {
256             it.next();
257             it.set(array[i]);
258         }
259     }
260
261     private void noteInvalidExtension(IConfigurationElement element, InvalidRegistryObjectException x) {
262         String JavaDoc message= MessageFormat.format(RulerColumnMessages.RulerColumnRegistry_invalid_msg, new Object JavaDoc[] {ExtensionPointHelper.findId(element)});
263         warnUser(message, x);
264     }
265
266     private void noteUnknownTarget(RulerColumnDescriptor desc, String JavaDoc referencedId) {
267         String JavaDoc message= MessageFormat.format(RulerColumnMessages.RulerColumnRegistry_unresolved_placement_msg, new Object JavaDoc[] {QUALIFIED_EXTENSION_POINT, referencedId, desc.getName(), desc.getContributor()});
268         warnUser(message, null);
269     }
270
271     private void noteCycle(RulerColumnDescriptor desc, RulerColumnDescriptor target) {
272         String JavaDoc message= MessageFormat.format(RulerColumnMessages.RulerColumnRegistry_cyclic_placement_msg, new Object JavaDoc[] {QUALIFIED_EXTENSION_POINT, target.getName(), desc.getName(), desc.getContributor()});
273         warnUser(message, null);
274     }
275
276     private void noteDuplicateId(RulerColumnDescriptor desc) {
277         String JavaDoc message= MessageFormat.format(RulerColumnMessages.RulerColumnRegistry_duplicate_id_msg, new Object JavaDoc[] {QUALIFIED_EXTENSION_POINT, desc.getId(), desc.getContributor()});
278         warnUser(message, null);
279     }
280
281     private void warnUser(String JavaDoc message, Exception JavaDoc exception) {
282         IStatus status= new Status(IStatus.WARNING, TextEditorPlugin.PLUGIN_ID, IStatus.OK, message, exception);
283         TextEditorPlugin.getDefault().getLog().log(status);
284     }
285 }
286
Popular Tags