KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > registry > WizardsRegistryReader


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.internal.registry;
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.HashSet JavaDoc;
18 import java.util.Iterator JavaDoc;
19 import java.util.Set JavaDoc;
20 import java.util.StringTokenizer JavaDoc;
21
22 import org.eclipse.core.runtime.CoreException;
23 import org.eclipse.core.runtime.IConfigurationElement;
24 import org.eclipse.core.runtime.IExtensionRegistry;
25 import org.eclipse.core.runtime.Platform;
26 import org.eclipse.ui.internal.WorkbenchMessages;
27 import org.eclipse.ui.internal.WorkbenchPlugin;
28 import org.eclipse.ui.internal.dialogs.WizardCollectionElement;
29 import org.eclipse.ui.internal.dialogs.WorkbenchWizardElement;
30 import org.eclipse.ui.internal.util.Util;
31
32 import com.ibm.icu.text.Collator;
33
34 /**
35  * Instances access the registry that is provided at creation time
36  * in order to determine the contained Wizards
37  */

38 public class WizardsRegistryReader extends RegistryReader {
39
40     private String JavaDoc pluginPoint;
41     
42     private WizardCollectionElement wizardElements = null;
43
44     private ArrayList JavaDoc deferWizards = null;
45
46     private ArrayList JavaDoc deferCategories = null;
47
48     private Set JavaDoc deferPrimary;
49
50     // constants
51
/**
52      * Examples wizard category id
53      */

54     public final static String JavaDoc FULL_EXAMPLES_WIZARD_CATEGORY = "org.eclipse.ui.Examples";//$NON-NLS-1$
55
/**
56      * Other wizard category id
57      */

58     final public static String JavaDoc UNCATEGORIZED_WIZARD_CATEGORY = "org.eclipse.ui.Other";//$NON-NLS-1$
59
/**
60      * General wizard category id
61      */

62     final public static String JavaDoc GENERAL_WIZARD_CATEGORY = "org.eclipse.ui.Basic"; //$NON-NLS-1$
63

64     final private static String JavaDoc UNCATEGORIZED_WIZARD_CATEGORY_LABEL = WorkbenchMessages.NewWizardsRegistryReader_otherCategory;
65     
66     private final static String JavaDoc CATEGORY_SEPARATOR = "/";//$NON-NLS-1$
67

68     private WorkbenchWizardElement[] primaryWizards = new WorkbenchWizardElement[0];
69     
70     private class CategoryNode {
71         private Category category;
72
73         private String JavaDoc path;
74
75         CategoryNode(Category cat) {
76             category = cat;
77             path = ""; //$NON-NLS-1$
78
String JavaDoc[] categoryPath = category.getParentPath();
79             if (categoryPath != null) {
80                 for (int nX = 0; nX < categoryPath.length; nX++) {
81                     path += categoryPath[nX] + '/';
82                 }
83             }
84             path += cat.getId();
85         }
86
87         String JavaDoc getPath() {
88             return path;
89         }
90
91         Category getCategory() {
92             return category;
93         }
94     }
95
96     private static final Comparator JavaDoc comparer = new Comparator JavaDoc() {
97         private Collator collator = Collator.getInstance();
98
99         public int compare(Object JavaDoc arg0, Object JavaDoc arg1) {
100             String JavaDoc s1 = ((CategoryNode) arg0).getPath();
101             String JavaDoc s2 = ((CategoryNode) arg1).getPath();
102             return collator.compare(s1, s2);
103         }
104     };
105
106     private boolean readAll = true;
107
108     private String JavaDoc plugin;
109
110     /**
111      *Create an instance of this class.
112      *
113      * @param pluginId the plugin id
114      * @param pluginPointId java.lang.String
115      */

116     public WizardsRegistryReader(String JavaDoc pluginId, String JavaDoc pluginPointId) {
117         pluginPoint = pluginPointId;
118         plugin = pluginId;
119     }
120
121     /* (non-Javadoc)
122      * Method declared on WizardRegistryReader.
123      * <p>
124      * This implementation uses a defering strategy. For more info see
125      * <code>readWizards</code>.
126      * </p>
127      */

128     protected void addNewElementToResult(WorkbenchWizardElement element,
129             IConfigurationElement config) {
130         // TODO: can we remove the config parameter?
131
deferWizard(element);
132     }
133
134     /**
135      *
136      * @param parent
137      * @param element
138      * @since 3.1
139      */

140     private WizardCollectionElement createCollectionElement(WizardCollectionElement parent, IConfigurationElement element) {
141         WizardCollectionElement newElement = new WizardCollectionElement(
142                 element, parent);
143
144         parent.add(newElement);
145         return newElement;
146     }
147     /**
148      * Create and answer a new WizardCollectionElement, configured as a
149      * child of <code>parent</code>
150      *
151      * @return org.eclipse.ui.internal.model.WizardCollectionElement
152      * @param parent org.eclipse.ui.internal.model.WizardCollectionElement
153      * @param id the id of the new collection
154      * @param pluginId the originating plugin id of the collection, if any. <code>null</code> otherwise.
155      * @param label java.lang.String
156      */

157     protected WizardCollectionElement createCollectionElement(
158             WizardCollectionElement parent, String JavaDoc id, String JavaDoc pluginId,
159             String JavaDoc label) {
160         WizardCollectionElement newElement = new WizardCollectionElement(id,
161                 pluginId, label, parent);
162
163         parent.add(newElement);
164         return newElement;
165     }
166
167     /**
168      * Creates empty element collection. Overrider to fill
169      * initial elements, if needed.
170      */

171     protected void createEmptyWizardCollection() {
172         wizardElements = new WizardCollectionElement("root", null, "root", null);//$NON-NLS-2$//$NON-NLS-1$
173
}
174     
175     /**
176      * Set the initial wizard set for supplemental reading via dynamic plugin loading.
177      *
178      * @param wizards the wizards
179      * @since 3.1
180      */

181     public void setInitialCollection(WizardCollectionElement wizards) {
182         wizardElements = wizards;
183         readAll = false;
184     }
185
186     /**
187      * Stores a category element for deferred addition.
188      */

189     private void deferCategory(IConfigurationElement config) {
190         // Create category.
191
Category category = null;
192         try {
193             category = new Category(config);
194         } catch (CoreException e) {
195             WorkbenchPlugin.log("Cannot create category: ", e.getStatus());//$NON-NLS-1$
196
return;
197         }
198
199         // Defer for later processing.
200
if (deferCategories == null) {
201             deferCategories = new ArrayList JavaDoc(20);
202         }
203         deferCategories.add(category);
204     }
205
206
207     /**
208      * Stores a wizard element for deferred addition.
209      */

210     private void deferWizard(WorkbenchWizardElement element) {
211         if (deferWizards == null) {
212             deferWizards = new ArrayList JavaDoc(50);
213         }
214         deferWizards.add(element);
215     }
216
217     /**
218      * Finishes the addition of categories. The categories are sorted and
219      * added in a root to depth traversal.
220      */

221     private void finishCategories() {
222         // If no categories just return.
223
if (deferCategories == null) {
224             return;
225         }
226
227         // Sort categories by flattened name.
228
CategoryNode[] flatArray = new CategoryNode[deferCategories.size()];
229         for (int i = 0; i < deferCategories.size(); i++) {
230             flatArray[i] = new CategoryNode((Category) deferCategories.get(i));
231         }
232         Collections.sort(Arrays.asList(flatArray), comparer);
233
234         // Add each category.
235
for (int nX = 0; nX < flatArray.length; nX++) {
236             Category cat = flatArray[nX].getCategory();
237             finishCategory(cat);
238         }
239
240         // Cleanup.
241
deferCategories = null;
242     }
243
244     /**
245      * Save new category definition.
246      */

247     private void finishCategory(Category category) {
248         String JavaDoc[] categoryPath = category.getParentPath();
249         WizardCollectionElement parent = wizardElements; // ie.- root
250

251         // Traverse down into parent category.
252
if (categoryPath != null) {
253             for (int i = 0; i < categoryPath.length; i++) {
254                 WizardCollectionElement tempElement = getChildWithID(parent,
255                         categoryPath[i]);
256                 if (tempElement == null) {
257                     // The parent category is invalid. By returning here the
258
// category will be dropped and any wizard within the category
259
// will be added to the "Other" category.
260
return;
261                 }
262                 parent = tempElement;
263             }
264         }
265
266         // If another category already exists with the same id ignore this one.
267
Object JavaDoc test = getChildWithID(parent, category.getId());
268         if (test != null) {
269             return;
270         }
271
272         if (parent != null) {
273             createCollectionElement(parent, (IConfigurationElement) Util.getAdapter(category,
274                     IConfigurationElement.class));
275         }
276     }
277
278
279     /**
280      * Finishes the recognition of primary wizards.
281      */

282     private void finishPrimary() {
283         if (deferPrimary != null) {
284             ArrayList JavaDoc primary = new ArrayList JavaDoc();
285             for (Iterator JavaDoc i = deferPrimary.iterator(); i.hasNext();) {
286                 String JavaDoc id = (String JavaDoc) i.next();
287                 WorkbenchWizardElement element = getWizardElements()
288                         .findWizard(id, true);
289                 if (element != null) {
290                     primary.add(element);
291                 }
292             }
293
294             primaryWizards = (WorkbenchWizardElement[]) primary
295                     .toArray(new WorkbenchWizardElement[primary.size()]);
296
297             deferPrimary = null;
298         }
299     }
300
301
302     /**
303      * Insert the passed wizard element into the wizard collection appropriately
304      * based upon its defining extension's CATEGORY tag value
305      *
306      * @param element WorkbenchWizardElement
307      * @param config configuration element
308      */

309     private void finishWizard(WorkbenchWizardElement element,
310             IConfigurationElement config) {
311         StringTokenizer JavaDoc familyTokenizer = new StringTokenizer JavaDoc(
312                 getCategoryStringFor(config), CATEGORY_SEPARATOR);
313
314         // use the period-separated sections of the current Wizard's category
315
// to traverse through the NamedSolution "tree" that was previously created
316
WizardCollectionElement currentCollectionElement = wizardElements; // ie.- root
317
boolean moveToOther = false;
318
319         while (familyTokenizer.hasMoreElements()) {
320             WizardCollectionElement tempCollectionElement = getChildWithID(
321                     currentCollectionElement, familyTokenizer.nextToken());
322
323             if (tempCollectionElement == null) { // can't find the path; bump it to uncategorized
324
moveToOther = true;
325                 break;
326             }
327             currentCollectionElement = tempCollectionElement;
328         }
329
330         if (moveToOther) {
331             moveElementToUncategorizedCategory(wizardElements, element);
332         } else {
333             currentCollectionElement.add(element);
334             element.setParent(currentCollectionElement);
335         }
336     }
337
338     /**
339      * Finishes the addition of wizards. The wizards are processed and categorized.
340      */

341     private void finishWizards() {
342         if (deferWizards != null) {
343             Iterator JavaDoc iter = deferWizards.iterator();
344             while (iter.hasNext()) {
345                 WorkbenchWizardElement wizard = (WorkbenchWizardElement) iter
346                         .next();
347                 IConfigurationElement config = wizard.getConfigurationElement();
348                 finishWizard(wizard, config);
349             }
350             deferWizards = null;
351         }
352     }
353
354     /**
355      * Return the appropriate category (tree location) for this Wizard.
356      * If a category is not specified then return a default one.
357      */

358     protected String JavaDoc getCategoryStringFor(IConfigurationElement config) {
359         String JavaDoc result = config.getAttribute(IWorkbenchRegistryConstants.TAG_CATEGORY);
360         if (result == null) {
361             result = UNCATEGORIZED_WIZARD_CATEGORY;
362         }
363
364         return result;
365     }
366
367     /**
368      * Go through the children of the passed parent and answer the child
369      * with the passed name. If no such child is found then return null.
370      *
371      * @return org.eclipse.ui.internal.model.WizardCollectionElement
372      * @param parent org.eclipse.ui.internal.model.WizardCollectionElement
373      * @param id java.lang.String
374      */

375     protected WizardCollectionElement getChildWithID(
376             WizardCollectionElement parent, String JavaDoc id) {
377         Object JavaDoc[] children = parent.getChildren(null);
378         for (int i = 0; i < children.length; ++i) {
379             WizardCollectionElement currentChild = (WizardCollectionElement) children[i];
380             if (currentChild.getId().equals(id)) {
381                 return currentChild;
382             }
383         }
384         return null;
385     }
386
387     /**
388      * Moves given element to "Other" category, previously creating one if missing.
389      */

390     protected void moveElementToUncategorizedCategory(
391             WizardCollectionElement root, WorkbenchWizardElement element) {
392         WizardCollectionElement otherCategory = getChildWithID(root,
393                 UNCATEGORIZED_WIZARD_CATEGORY);
394
395         if (otherCategory == null) {
396             otherCategory = createCollectionElement(root,
397                     UNCATEGORIZED_WIZARD_CATEGORY, null,
398                     UNCATEGORIZED_WIZARD_CATEGORY_LABEL);
399         }
400
401         otherCategory.add(element);
402         element.setParent(otherCategory);
403     }
404
405     /**
406      * Removes the empty categories from a wizard collection.
407      */

408     private void pruneEmptyCategories(WizardCollectionElement parent) {
409         Object JavaDoc[] children = parent.getChildren(null);
410         for (int nX = 0; nX < children.length; nX++) {
411             WizardCollectionElement child = (WizardCollectionElement) children[nX];
412             pruneEmptyCategories(child);
413             boolean shouldPrune = child.getId().equals(FULL_EXAMPLES_WIZARD_CATEGORY);
414             if (child.isEmpty() && shouldPrune) {
415                 parent.remove(child);
416             }
417         }
418     }
419
420     /**
421      * Implement this method to read element attributes.
422      */

423     public boolean readElement(IConfigurationElement element) {
424         if (element.getName().equals(IWorkbenchRegistryConstants.TAG_CATEGORY)) {
425             deferCategory(element);
426             return true;
427         } else if (element.getName().equals(IWorkbenchRegistryConstants.TAG_PRIMARYWIZARD)) {
428             if (deferPrimary == null) {
429                 deferPrimary = new HashSet JavaDoc();
430             }
431             deferPrimary.add(element.getAttribute(IWorkbenchRegistryConstants.ATT_ID));
432
433             return true;
434         } else {
435             if (!element.getName().equals(IWorkbenchRegistryConstants.TAG_WIZARD)) {
436                 return false;
437             }
438             WorkbenchWizardElement wizard = createWizardElement(element);
439             if (wizard != null) {
440                 addNewElementToResult(wizard, element);
441             }
442             return true;
443         }
444     }
445
446     /**
447      * Reads the wizards in a registry.
448      * <p>
449      * This implementation uses a defering strategy. All of the elements
450      * (categories, wizards) are read. The categories are created as the read occurs.
451      * The wizards are just stored for later addition after the read completes.
452      * This ensures that wizard categorization is performed after all categories
453      * have been read.
454      * </p>
455      */

456     protected void readWizards() {
457         if (readAll) {
458                if (!areWizardsRead()) {
459                 createEmptyWizardCollection();
460                 IExtensionRegistry registry = Platform.getExtensionRegistry();
461                 readRegistry(registry, plugin, pluginPoint);
462             }
463         }
464         finishCategories();
465         finishWizards();
466         finishPrimary();
467         if (wizardElements != null) {
468             pruneEmptyCategories(wizardElements);
469         }
470     }
471
472     /**
473      * Returns the list of wizards that are considered 'primary'.
474      *
475      * The return value for this method is cached since computing its value
476      * requires non-trivial work.
477      *
478      * @return the primary wizards
479      */

480     public WorkbenchWizardElement [] getPrimaryWizards() {
481         if (!areWizardsRead()) {
482             readWizards();
483         }
484         return primaryWizards;
485     }
486
487
488     /**
489      * Returns whether the wizards have been read already
490      */

491     protected boolean areWizardsRead() {
492         return wizardElements != null && readAll;
493     }
494
495     /**
496      * Returns a list of wizards, project and not.
497      *
498      * The return value for this method is cached since computing its value
499      * requires non-trivial work.
500      *
501      * @return the wizard collection
502      */

503     public WizardCollectionElement getWizardElements() {
504         if (!areWizardsRead()) {
505             readWizards();
506         }
507         return wizardElements;
508     }
509
510     protected Object JavaDoc[] getWizardCollectionElements() {
511         if (!areWizardsRead()) {
512             readWizards();
513         }
514         return wizardElements.getChildren();
515     }
516     
517     /**
518      * Returns a new WorkbenchWizardElement configured according to the parameters
519      * contained in the passed Registry.
520      *
521      * May answer null if there was not enough information in the Extension to create
522      * an adequate wizard
523      */

524     protected WorkbenchWizardElement createWizardElement(
525             IConfigurationElement element) {
526         // WizardElements must have a name attribute
527
if (element.getAttribute(IWorkbenchRegistryConstants.ATT_NAME) == null) {
528             logMissingAttribute(element, IWorkbenchRegistryConstants.ATT_NAME);
529             return null;
530         }
531         
532         if (getClassValue(element, IWorkbenchRegistryConstants.ATT_CLASS) == null) {
533             logMissingAttribute(element, IWorkbenchRegistryConstants.ATT_CLASS);
534             return null;
535         }
536         return new WorkbenchWizardElement(element);
537     }
538
539     /**
540      * Returns the first wizard with a given id.
541      *
542      * @param id wizard id to search for
543      * @return WorkbenchWizardElement matching the given id, if found; null otherwise
544      */

545     public WorkbenchWizardElement findWizard(String JavaDoc id) {
546         Object JavaDoc[] wizards = getWizardCollectionElements();
547         for (int nX = 0; nX < wizards.length; nX++) {
548             WizardCollectionElement collection = (WizardCollectionElement) wizards[nX];
549             WorkbenchWizardElement element = collection.findWizard(id, true);
550             if (element != null) {
551                 return element;
552             }
553         }
554         return null;
555     }
556 }
557
Popular Tags