diff options
Diffstat (limited to 'bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/ObjectContributorManager.java')
-rw-r--r-- | bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/ObjectContributorManager.java | 1491 |
1 files changed, 738 insertions, 753 deletions
diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/ObjectContributorManager.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/ObjectContributorManager.java index ff53d763d0c..aa642213a63 100644 --- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/ObjectContributorManager.java +++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/ObjectContributorManager.java @@ -38,20 +38,19 @@ import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.ui.PlatformUI; /** - * This class is a default implementation of <code>IObjectContributorManager</code>. - * It provides fast merging of contributions with the following semantics: + * This class is a default implementation of + * <code>IObjectContributorManager</code>. It provides fast merging of + * contributions with the following semantics: * <ul> - * <li> All of the matching contributors will be invoked per property lookup - * <li> The search order from a class with the definition<br> - * <code>class X extends Y implements A, B</code><br> - * is as follows: - * <il> - * <li>the target's class: X - * <li>X's superclasses in order to <code>Object</code> - * <li>a depth-first traversal of the target class's interaces in the order - * returned by <code>getInterfaces()</code> (in the example, A and - * its superinterfaces then B and its superinterfaces) - * </il> + * <li>All of the matching contributors will be invoked per property lookup + * <li>The search order from a class with the definition<br> + * <code>class X extends Y implements A, B</code><br> + * is as follows: <il> + * <li>the target's class: X + * <li>X's superclasses in order to <code>Object</code> + * <li>a depth-first traversal of the target class's interaces in the order + * returned by <code>getInterfaces()</code> (in the example, A and its + * superinterfaces then B and its superinterfaces) </il> * </ul> * * @see IObjectContributor @@ -75,43 +74,48 @@ public abstract class ObjectContributorManager implements IExtensionChangeHandle IObjectContributor contributor; } - /** Table of contributors. */ - protected Map contributors; + /** Table of contributors. */ + protected Map contributors; - /** Cache of object class contributor search paths; <code>null</code> if none. */ - protected Map objectLookup; + /** + * Cache of object class contributor search paths; <code>null</code> if none. + */ + protected Map objectLookup; - /** Cache of resource adapter class contributor search paths; <code>null</code> if none. */ - protected Map resourceAdapterLookup; + /** + * Cache of resource adapter class contributor search paths; <code>null</code> + * if none. + */ + protected Map resourceAdapterLookup; - /** Cache of adaptable class contributor search paths; <code>null</code> if none. */ - protected Map adaptableLookup; + /** + * Cache of adaptable class contributor search paths; <code>null</code> if none. + */ + protected Map adaptableLookup; - protected Set contributorRecordSet; + protected Set contributorRecordSet; - /** - * Constructs a new contributor manager. - */ - public ObjectContributorManager() { - contributors = new Hashtable(5); - contributorRecordSet = new HashSet(5); - objectLookup = null; - resourceAdapterLookup = null; - adaptableLookup = null; - String extensionPointId = getExtensionPointFilter(); - if (extensionPointId != null) { - IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint( - PlatformUI.PLUGIN_ID, extensionPointId); - IExtensionTracker tracker = PlatformUI.getWorkbench() - .getExtensionTracker(); - tracker.registerHandler(this, ExtensionTracker - .createExtensionPointFilter(extensionPoint)); + /** + * Constructs a new contributor manager. + */ + public ObjectContributorManager() { + contributors = new Hashtable(5); + contributorRecordSet = new HashSet(5); + objectLookup = null; + resourceAdapterLookup = null; + adaptableLookup = null; + String extensionPointId = getExtensionPointFilter(); + if (extensionPointId != null) { + IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(PlatformUI.PLUGIN_ID, + extensionPointId); + IExtensionTracker tracker = PlatformUI.getWorkbench().getExtensionTracker(); + tracker.registerHandler(this, ExtensionTracker.createExtensionPointFilter(extensionPoint)); } - } + } - /** - * Return the extension point id (local to org.eclipse.ui) that this manager - * is associated with. Default implementation returns null, which implies no + /** + * Return the extension point id (local to org.eclipse.ui) that this manager is + * associated with. Default implementation returns null, which implies no * relationship with a particular extension. * * @return the extension point id @@ -122,300 +126,287 @@ public abstract class ObjectContributorManager implements IExtensionChangeHandle } /** - * Adds contributors for the given types to the result list. - */ - private void addContributorsFor(List types, List result) { - for (Iterator classes = types.iterator(); classes.hasNext();) { - Class clazz = (Class) classes.next(); - List contributorList = (List) contributors.get(clazz.getName()); - if (contributorList != null) { + * Adds contributors for the given types to the result list. + */ + private void addContributorsFor(List types, List result) { + for (Iterator classes = types.iterator(); classes.hasNext();) { + Class clazz = (Class) classes.next(); + List contributorList = (List) contributors.get(clazz.getName()); + if (contributorList != null) { result.addAll(contributorList); } - } - } - - /** - * Returns the class search order starting with <code>extensibleClass</code>. - * The search order is defined in this class' comment. - */ - protected final List computeClassOrder(Class extensibleClass) { - ArrayList result = new ArrayList(4); - Class clazz = extensibleClass; - while (clazz != null) { - result.add(clazz); - clazz = clazz.getSuperclass(); - } - return result; - } - - /** - * Returns the interface search order for the class hierarchy described - * by <code>classList</code>. - * The search order is defined in this class' comment. - */ - protected final List computeInterfaceOrder(List classList) { - ArrayList result = new ArrayList(4); - Map seen = new HashMap(4); - for (Iterator list = classList.iterator(); list.hasNext();) { - Class[] interfaces = ((Class) list.next()).getInterfaces(); - internalComputeInterfaceOrder(interfaces, result, seen); - } - return result; - } - - /** - * Flushes the cache of contributor search paths. This is generally required - * whenever a contributor is added or removed. - * <p> - * It is likely easier to just toss the whole cache rather than trying to be - * smart and remove only those entries affected. - */ - public void flushLookup() { - objectLookup = null; - resourceAdapterLookup = null; - adaptableLookup = null; - } - - /** - * Cache the real adapter class contributor search path. - */ - private void cacheResourceAdapterLookup(Class adapterClass, List results) { - if (resourceAdapterLookup == null) { + } + } + + /** + * Returns the class search order starting with <code>extensibleClass</code>. + * The search order is defined in this class' comment. + */ + protected final List computeClassOrder(Class extensibleClass) { + ArrayList result = new ArrayList(4); + Class clazz = extensibleClass; + while (clazz != null) { + result.add(clazz); + clazz = clazz.getSuperclass(); + } + return result; + } + + /** + * Returns the interface search order for the class hierarchy described by + * <code>classList</code>. The search order is defined in this class' comment. + */ + protected final List computeInterfaceOrder(List classList) { + ArrayList result = new ArrayList(4); + Map seen = new HashMap(4); + for (Iterator list = classList.iterator(); list.hasNext();) { + Class[] interfaces = ((Class) list.next()).getInterfaces(); + internalComputeInterfaceOrder(interfaces, result, seen); + } + return result; + } + + /** + * Flushes the cache of contributor search paths. This is generally required + * whenever a contributor is added or removed. + * <p> + * It is likely easier to just toss the whole cache rather than trying to be + * smart and remove only those entries affected. + */ + public void flushLookup() { + objectLookup = null; + resourceAdapterLookup = null; + adaptableLookup = null; + } + + /** + * Cache the real adapter class contributor search path. + */ + private void cacheResourceAdapterLookup(Class adapterClass, List results) { + if (resourceAdapterLookup == null) { resourceAdapterLookup = new HashMap(); } - resourceAdapterLookup.put(adapterClass, results); - } + resourceAdapterLookup.put(adapterClass, results); + } - /** - * Cache the real adapter class contributor search path. - */ - private void cacheAdaptableLookup(String adapterClass, List results) { - if (adaptableLookup == null) { + /** + * Cache the real adapter class contributor search path. + */ + private void cacheAdaptableLookup(String adapterClass, List results) { + if (adaptableLookup == null) { adaptableLookup = new HashMap(); } - adaptableLookup.put(adapterClass, results); - } + adaptableLookup.put(adapterClass, results); + } - /** - * Cache the object class contributor search path. - */ - private void cacheObjectLookup(Class objectClass, List results) { - if (objectLookup == null) { + /** + * Cache the object class contributor search path. + */ + private void cacheObjectLookup(Class objectClass, List results) { + if (objectLookup == null) { objectLookup = new HashMap(); } - objectLookup.put(objectClass, results); - } - - /** - * Get the contributions registered to this manager. - * - * @return an unmodifiable <code>Collection</code> containing all registered - * contributions. The objects in this <code>Collection</code> will be - * <code>List</code>s containing the actual contributions. - * @since 3.0 - */ - public Collection getContributors() { - return Collections.unmodifiableCollection(contributors.values()); - } - - /** - * Return the list of contributors for the supplied class. - */ - protected List addContributorsFor(Class objectClass) { - - List classList = computeClassOrder(objectClass); - List result = new ArrayList(); - addContributorsFor(classList, result); - classList = computeInterfaceOrder(classList); // interfaces - addContributorsFor(classList, result); - return result; - } - - /** - * Returns true if contributors exist in the manager for - * this object and any of it's super classes, interfaces, or - * adapters. - * - * @param object the object to test - * @return whether the object has contributors - */ - public boolean hasContributorsFor(Object object) { - - List contributors = getContributors(object); - return contributors.size() > 0; - } - - /** - * Add interface Class objects to the result list based - * on the class hierarchy. Interfaces will be searched - * based on their position in the result list. - */ - private void internalComputeInterfaceOrder(Class[] interfaces, List result, - Map seen) { - List newInterfaces = new ArrayList(seen.size()); - for (Class currentInterface : interfaces) { - if (seen.get(currentInterface) == null) { - result.add(currentInterface); - seen.put(currentInterface, currentInterface); - newInterfaces.add(currentInterface); - } - } - for (Iterator newList = newInterfaces.iterator(); newList.hasNext();) { - internalComputeInterfaceOrder(((Class) newList.next()) - .getInterfaces(), result, seen); - } - } - - /** + objectLookup.put(objectClass, results); + } + + /** + * Get the contributions registered to this manager. + * + * @return an unmodifiable <code>Collection</code> containing all registered + * contributions. The objects in this <code>Collection</code> will be + * <code>List</code>s containing the actual contributions. + * @since 3.0 + */ + public Collection getContributors() { + return Collections.unmodifiableCollection(contributors.values()); + } + + /** + * Return the list of contributors for the supplied class. + */ + protected List addContributorsFor(Class objectClass) { + + List classList = computeClassOrder(objectClass); + List result = new ArrayList(); + addContributorsFor(classList, result); + classList = computeInterfaceOrder(classList); // interfaces + addContributorsFor(classList, result); + return result; + } + + /** + * Returns true if contributors exist in the manager for this object and any of + * it's super classes, interfaces, or adapters. + * + * @param object the object to test + * @return whether the object has contributors + */ + public boolean hasContributorsFor(Object object) { + + List contributors = getContributors(object); + return contributors.size() > 0; + } + + /** + * Add interface Class objects to the result list based on the class hierarchy. + * Interfaces will be searched based on their position in the result list. + */ + private void internalComputeInterfaceOrder(Class[] interfaces, List result, Map seen) { + List newInterfaces = new ArrayList(seen.size()); + for (Class currentInterface : interfaces) { + if (seen.get(currentInterface) == null) { + result.add(currentInterface); + seen.put(currentInterface, currentInterface); + newInterfaces.add(currentInterface); + } + } + for (Iterator newList = newInterfaces.iterator(); newList.hasNext();) { + internalComputeInterfaceOrder(((Class) newList.next()).getInterfaces(), result, seen); + } + } + + /** * Return whether the given contributor is applicable to all elements in the * selection. * - * @param selection - * the selection - * @param contributor - * the contributor + * @param selection the selection + * @param contributor the contributor * @return whether it is applicable */ - public boolean isApplicableTo(IStructuredSelection selection, - IObjectContributor contributor) { - Iterator elements = selection.iterator(); - while (elements.hasNext()) { - if (contributor.isApplicableTo(elements.next()) == false) { + public boolean isApplicableTo(IStructuredSelection selection, IObjectContributor contributor) { + Iterator elements = selection.iterator(); + while (elements.hasNext()) { + if (contributor.isApplicableTo(elements.next()) == false) { return false; } - } - return true; - } + } + return true; + } - /** + /** * Return whether the given contributor is applicable to all elements in the * list. * - * @param list - * the selection - * @param contributor - * the contributor + * @param list the selection + * @param contributor the contributor * @return whether it is applicable */ - public boolean isApplicableTo(List list, IObjectContributor contributor) { - Iterator elements = list.iterator(); - while (elements.hasNext()) { - if (contributor.isApplicableTo(elements.next()) == false) { + public boolean isApplicableTo(List list, IObjectContributor contributor) { + Iterator elements = list.iterator(); + while (elements.hasNext()) { + if (contributor.isApplicableTo(elements.next()) == false) { return false; } - } - return true; - } - - /** - * Register a contributor. - * - * @param contributor the contributor - * @param targetType the target type - */ - public void registerContributor(IObjectContributor contributor, - String targetType) { - List contributorList = (List) contributors.get(targetType); - if (contributorList == null) { - contributorList = new ArrayList(5); - contributors.put(targetType, contributorList); - } - contributorList.add(contributor); - flushLookup(); - - IConfigurationElement element = Adapters.adapt(contributor, IConfigurationElement.class); - - //hook the object listener - if (element != null) { - ContributorRecord contributorRecord = new ContributorRecord( - contributor, targetType); + } + return true; + } + + /** + * Register a contributor. + * + * @param contributor the contributor + * @param targetType the target type + */ + public void registerContributor(IObjectContributor contributor, String targetType) { + List contributorList = (List) contributors.get(targetType); + if (contributorList == null) { + contributorList = new ArrayList(5); + contributors.put(targetType, contributorList); + } + contributorList.add(contributor); + flushLookup(); + + IConfigurationElement element = Adapters.adapt(contributor, IConfigurationElement.class); + + // hook the object listener + if (element != null) { + ContributorRecord contributorRecord = new ContributorRecord(contributor, targetType); contributorRecordSet.add(contributorRecord); - PlatformUI.getWorkbench().getExtensionTracker().registerObject( - element.getDeclaringExtension(), contributorRecord, - IExtensionTracker.REF_WEAK); - } - } - - /** - * Unregister all contributors. - */ - public void unregisterAllContributors() { - contributors = new Hashtable(5); - flushLookup(); - } - - /** - * Unregister a contributor from the target type. - * - * @param contributor the contributor - * @param targetType the target type - */ - public void unregisterContributor(IObjectContributor contributor, - String targetType) { - List contributorList = (List) contributors.get(targetType); - if (contributorList == null) { + PlatformUI.getWorkbench().getExtensionTracker().registerObject(element.getDeclaringExtension(), + contributorRecord, IExtensionTracker.REF_WEAK); + } + } + + /** + * Unregister all contributors. + */ + public void unregisterAllContributors() { + contributors = new Hashtable(5); + flushLookup(); + } + + /** + * Unregister a contributor from the target type. + * + * @param contributor the contributor + * @param targetType the target type + */ + public void unregisterContributor(IObjectContributor contributor, String targetType) { + List contributorList = (List) contributors.get(targetType); + if (contributorList == null) { return; } - contributorList.remove(contributor); - if (contributorList.isEmpty()) { + contributorList.remove(contributor); + if (contributorList.isEmpty()) { contributors.remove(targetType); } - flushLookup(); - } - + flushLookup(); + } - /** - * Unregister all contributors for the target type. - * - * @param targetType the target type - */ - public void unregisterContributors(String targetType) { - contributors.remove(targetType); - flushLookup(); - } + /** + * Unregister all contributors for the target type. + * + * @param targetType the target type + */ + public void unregisterContributors(String targetType) { + contributors.remove(targetType); + flushLookup(); + } - protected List getContributors(Object object) { - // Determine is the object is a resource - Object resource = LegacyResourceSupport.getAdaptedContributorResource(object); + protected List getContributors(Object object) { + // Determine is the object is a resource + Object resource = LegacyResourceSupport.getAdaptedContributorResource(object); - // Fetch the unique adapters - List adapters = new ArrayList(Arrays.asList(Platform.getAdapterManager().computeAdapterTypes(object.getClass()))); - removeCommonAdapters(adapters, Arrays.asList(new Class[] {object.getClass()})); + // Fetch the unique adapters + List adapters = new ArrayList( + Arrays.asList(Platform.getAdapterManager().computeAdapterTypes(object.getClass()))); + removeCommonAdapters(adapters, Arrays.asList(new Class[] { object.getClass() })); - List contributors = new ArrayList(); + List contributors = new ArrayList(); - // Calculate the contributors for this object class - addAll(contributors, getObjectContributors(object.getClass())); - // Calculate the contributors for resource classes - if(resource != null) { + // Calculate the contributors for this object class + addAll(contributors, getObjectContributors(object.getClass())); + // Calculate the contributors for resource classes + if (resource != null) { addAll(contributors, getResourceContributors(resource.getClass())); } - // Calculate the contributors for each adapter type - if(adapters != null) { - for (Iterator it = adapters.iterator(); it.hasNext();) { + // Calculate the contributors for each adapter type + if (adapters != null) { + for (Iterator it = adapters.iterator(); it.hasNext();) { String adapter = (String) it.next(); addAll(contributors, getAdaptableContributors(adapter)); } - } - - // Remove duplicates. Note: this -must- maintain the element order to preserve menu order. - contributors = removeDups(contributors); - - return contributors.isEmpty() ? Collections.EMPTY_LIST : new ArrayList(contributors); - } - - /** - * Returns the contributions for the given class. This considers - * contributors on any super classes and interfaces. - * - * @param objectClass the class to search for contributions. - * @return the contributions for the given class. This considers - * contributors on any super classes and interfaces. - * - * @since 3.1 - */ - protected List getObjectContributors(Class objectClass) { + } + + // Remove duplicates. Note: this -must- maintain the element order to preserve + // menu order. + contributors = removeDups(contributors); + + return contributors.isEmpty() ? Collections.EMPTY_LIST : new ArrayList(contributors); + } + + /** + * Returns the contributions for the given class. This considers contributors on + * any super classes and interfaces. + * + * @param objectClass the class to search for contributions. + * @return the contributions for the given class. This considers contributors on + * any super classes and interfaces. + * + * @since 3.1 + */ + protected List getObjectContributors(Class objectClass) { List objectList = null; // Lookup the results in the cache first. if (objectLookup != null) { @@ -425,8 +416,7 @@ public abstract class ObjectContributorManager implements IExtensionChangeHandle objectList = addContributorsFor(objectClass); if (objectList.isEmpty()) { objectList = Collections.EMPTY_LIST; - } - else { + } else { objectList = Collections.unmodifiableList(objectList); } cacheObjectLookup(objectClass, objectList); @@ -434,17 +424,17 @@ public abstract class ObjectContributorManager implements IExtensionChangeHandle return objectList; } - /** - * Returns the contributions for the given <code>IResource</code>class. - * This considers contributors on any super classes and interfaces. This - * will only return contributions that are adaptable. - * - * @param resourceClass the class to search for contributions. - * @return the contributions for the given class. This considers - * adaptable contributors on any super classes and interfaces. - * - * @since 3.1 - */ + /** + * Returns the contributions for the given <code>IResource</code>class. This + * considers contributors on any super classes and interfaces. This will only + * return contributions that are adaptable. + * + * @param resourceClass the class to search for contributions. + * @return the contributions for the given class. This considers adaptable + * contributors on any super classes and interfaces. + * + * @since 3.1 + */ protected List getResourceContributors(Class resourceClass) { List resourceList = null; if (resourceAdapterLookup != null) { @@ -462,15 +452,15 @@ public abstract class ObjectContributorManager implements IExtensionChangeHandle return resourceList; } - /** - * Returns the contributions for the given type name. - * - * @param adapterType the class to search for contributions. - * @return the contributions for the given class. This considers - * contributors to this specific type. - * - * @since 3.1 - */ + /** + * Returns the contributions for the given type name. + * + * @param adapterType the class to search for contributions. + * @return the contributions for the given class. This considers contributors to + * this specific type. + * + * @since 3.1 + */ protected List getAdaptableContributors(String adapterType) { List adaptableList = null; // Lookup the results in the cache first, there are two caches @@ -482,10 +472,10 @@ public abstract class ObjectContributorManager implements IExtensionChangeHandle if (adaptableList == null) { // ignore resource adapters because these must be adapted via the // IContributorResourceAdapter. - if (LegacyResourceSupport.isResourceType(adapterType) || LegacyResourceSupport.isResourceMappingType(adapterType)) { + if (LegacyResourceSupport.isResourceType(adapterType) + || LegacyResourceSupport.isResourceMappingType(adapterType)) { adaptableList = Collections.EMPTY_LIST; - } - else { + } else { adaptableList = (List) contributors.get(adapterType); if (adaptableList == null || adaptableList.isEmpty()) { adaptableList = Collections.EMPTY_LIST; @@ -499,14 +489,15 @@ public abstract class ObjectContributorManager implements IExtensionChangeHandle } /** - * Prunes from the list of adapters type names that are in the class - * search order of every class in <code>results</code>. + * Prunes from the list of adapters type names that are in the class search + * order of every class in <code>results</code>. + * * @param adapters * @param results * @since 3.1 */ protected void removeCommonAdapters(List adapters, List results) { - for (Iterator it = results.iterator(); it.hasNext();) { + for (Iterator it = results.iterator(); it.hasNext();) { Class clazz = ((Class) it.next()); List commonTypes = computeCombinedOrder(clazz); for (Iterator it2 = commonTypes.iterator(); it2.hasNext();) { @@ -514,35 +505,35 @@ public abstract class ObjectContributorManager implements IExtensionChangeHandle adapters.remove(type.getName()); } } - } - - /** - * Returns the class search order starting with <code>extensibleClass</code>. - * The search order is defined in this class' comment. - */ - protected List computeCombinedOrder(Class inputClass) { - List result = new ArrayList(4); - Class clazz = inputClass; - while (clazz != null) { - // add the class - result.add(clazz); - // add all the interfaces it implements - Class[] interfaces = clazz.getInterfaces(); - for (Class currentInterface : interfaces) { - result.add(currentInterface); - } - // get the superclass - clazz = clazz.getSuperclass(); - } - return result; - } + } + + /** + * Returns the class search order starting with <code>extensibleClass</code>. + * The search order is defined in this class' comment. + */ + protected List computeCombinedOrder(Class inputClass) { + List result = new ArrayList(4); + Class clazz = inputClass; + while (clazz != null) { + // add the class + result.add(clazz); + // add all the interfaces it implements + Class[] interfaces = clazz.getInterfaces(); + for (Class currentInterface : interfaces) { + result.add(currentInterface); + } + // get the superclass + clazz = clazz.getSuperclass(); + } + return result; + } private List filterOnlyAdaptableContributors(List contributors) { List adaptableContributors = null; for (Iterator it = contributors.iterator(); it.hasNext();) { IObjectContributor c = (IObjectContributor) it.next(); - if(c.canAdapt()) { - if(adaptableContributors == null) { + if (c.canAdapt()) { + if (adaptableContributors == null) { adaptableContributors = new ArrayList(); } adaptableContributors.add(c); @@ -551,91 +542,91 @@ public abstract class ObjectContributorManager implements IExtensionChangeHandle return adaptableContributors == null ? Collections.EMPTY_LIST : adaptableContributors; } - @Override + @Override public void removeExtension(IExtension source, Object[] objects) { - for (Object object : objects) { - if (object instanceof ContributorRecord) { - ContributorRecord contributorRecord = (ContributorRecord) object; - unregisterContributor((contributorRecord).contributor, (contributorRecord).objectClassName); - contributorRecordSet.remove(contributorRecord); - } - } - } - - /** - * Remove listeners and dispose of this manager. - * - * @since 3.1 - */ - public void dispose() { - if(getExtensionPointFilter() != null) { + for (Object object : objects) { + if (object instanceof ContributorRecord) { + ContributorRecord contributorRecord = (ContributorRecord) object; + unregisterContributor((contributorRecord).contributor, (contributorRecord).objectClassName); + contributorRecordSet.remove(contributorRecord); + } + } + } + + /** + * Remove listeners and dispose of this manager. + * + * @since 3.1 + */ + public void dispose() { + if (getExtensionPointFilter() != null) { PlatformUI.getWorkbench().getExtensionTracker().unregisterHandler(this); } - } - - /** - * Returns the list of contributors that are interested in the - * given list of model elements. - * @param elements a list of model elements (<code>Object</code>) - * @return the list of interested contributors (<code>IObjectContributor</code>) - */ - protected List getContributors(List elements) { - // Calculate the common class, interfaces, and adapters registered - // via the IAdapterManager. - List commonAdapters = new ArrayList(); - List commonClasses = getCommonClasses(elements, commonAdapters); - - // Get the resource class. It will be null if any of the - // elements are resources themselves or do not adapt to - // IResource. - Class resourceClass = getCommonResourceClass(elements); - Class resourceMappingClass = getResourceMappingClass(elements); - - // Get the contributors. - - List contributors = new ArrayList(); - - // Add the resource contributions to avoid duplication - if (resourceClass != null) { - addAll(contributors, getResourceContributors(resourceClass)); - } - if (commonClasses != null && !commonClasses.isEmpty()) { - for (int i = 0; i < commonClasses.size(); i++) { - List results = getObjectContributors((Class) commonClasses - .get(i)); - addAll(contributors, results); - } - } - // Add the resource mappings explicitly to avoid possible duplication - if (resourceMappingClass == null) { - // Still show the menus if the object is not adaptable but the adapter manager - // has an entry for it - resourceMappingClass = LegacyResourceSupport - .getResourceMappingClass(); - if (resourceMappingClass != null - && commonAdapters.contains(resourceMappingClass.getName())) { - addAll(contributors, getResourceContributors(resourceMappingClass)); - } - } else { - contributors.addAll(getResourceContributors(resourceMappingClass)); - } - if (!commonAdapters.isEmpty()) { - for (Iterator it = commonAdapters.iterator(); it.hasNext();) { - String adapter = (String) it.next(); - addAll(contributors, getAdaptableContributors(adapter)); - } - } - - // Remove duplicates. Note: this -must- maintain the element order to preserve menu order. - contributors = removeDups(contributors); - - return contributors.isEmpty() ? Collections.EMPTY_LIST : new ArrayList(contributors); - } - - /** - * Adds all items in toAdd to the given collection. Optimized to avoid creating an iterator. - * This assumes that toAdd is efficient to index (i.e. it's an ArrayList or some other RandomAccessList), - * which is the case for all uses in this class. + } + + /** + * Returns the list of contributors that are interested in the given list of + * model elements. + * + * @param elements a list of model elements (<code>Object</code>) + * @return the list of interested contributors (<code>IObjectContributor</code>) + */ + protected List getContributors(List elements) { + // Calculate the common class, interfaces, and adapters registered + // via the IAdapterManager. + List commonAdapters = new ArrayList(); + List commonClasses = getCommonClasses(elements, commonAdapters); + + // Get the resource class. It will be null if any of the + // elements are resources themselves or do not adapt to + // IResource. + Class resourceClass = getCommonResourceClass(elements); + Class resourceMappingClass = getResourceMappingClass(elements); + + // Get the contributors. + + List contributors = new ArrayList(); + + // Add the resource contributions to avoid duplication + if (resourceClass != null) { + addAll(contributors, getResourceContributors(resourceClass)); + } + if (commonClasses != null && !commonClasses.isEmpty()) { + for (int i = 0; i < commonClasses.size(); i++) { + List results = getObjectContributors((Class) commonClasses.get(i)); + addAll(contributors, results); + } + } + // Add the resource mappings explicitly to avoid possible duplication + if (resourceMappingClass == null) { + // Still show the menus if the object is not adaptable but the adapter manager + // has an entry for it + resourceMappingClass = LegacyResourceSupport.getResourceMappingClass(); + if (resourceMappingClass != null && commonAdapters.contains(resourceMappingClass.getName())) { + addAll(contributors, getResourceContributors(resourceMappingClass)); + } + } else { + contributors.addAll(getResourceContributors(resourceMappingClass)); + } + if (!commonAdapters.isEmpty()) { + for (Iterator it = commonAdapters.iterator(); it.hasNext();) { + String adapter = (String) it.next(); + addAll(contributors, getAdaptableContributors(adapter)); + } + } + + // Remove duplicates. Note: this -must- maintain the element order to preserve + // menu order. + contributors = removeDups(contributors); + + return contributors.isEmpty() ? Collections.EMPTY_LIST : new ArrayList(contributors); + } + + /** + * Adds all items in toAdd to the given collection. Optimized to avoid creating + * an iterator. This assumes that toAdd is efficient to index (i.e. it's an + * ArrayList or some other RandomAccessList), which is the case for all uses in + * this class. */ private static void addAll(Collection collection, List toAdd) { for (int i = 0, size = toAdd.size(); i < size; ++i) { @@ -643,158 +634,160 @@ public abstract class ObjectContributorManager implements IExtensionChangeHandle } } - /** - * Removes duplicates from the given list, preserving order. - */ - private static List removeDups(List list) { - if (list.size() <= 1) { - return list; - } - HashSet set = new HashSet(list); - if (set.size() == list.size()) { - return list; - } - ArrayList result = new ArrayList(set.size()); - for (Iterator i = list.iterator(); i.hasNext();) { - Object o = i.next(); - if (set.remove(o)) { - result.add(o); - } - } - return result; - } - - /** - * Returns the common denominator class, interfaces, and adapters - * for the given collection of objects. - */ - private List getCommonClasses(List objects, List commonAdapters) { - if (objects == null || objects.isEmpty()) { + /** + * Removes duplicates from the given list, preserving order. + */ + private static List removeDups(List list) { + if (list.size() <= 1) { + return list; + } + HashSet set = new HashSet(list); + if (set.size() == list.size()) { + return list; + } + ArrayList result = new ArrayList(set.size()); + for (Iterator i = list.iterator(); i.hasNext();) { + Object o = i.next(); + if (set.remove(o)) { + result.add(o); + } + } + return result; + } + + /** + * Returns the common denominator class, interfaces, and adapters for the given + * collection of objects. + */ + private List getCommonClasses(List objects, List commonAdapters) { + if (objects == null || objects.isEmpty()) { return null; } - // Optimization: if n==1 (or if all objects are of the same class), then the common class is the object's class, - // and the common adapters are the adapters cached for that class in the adapter manager - // See bug 177592 for more details. - if (allSameClass(objects)) { - - Class clazz = objects.get(0).getClass(); - commonAdapters.addAll(Arrays.asList(Platform.getAdapterManager().computeAdapterTypes(clazz))); - List result = new ArrayList(1); - result.add(clazz); - return result; - } - - // Compute all the super classes, interfaces, and adapters - // for the first element. - List classes = computeClassOrder(objects.get(0).getClass()); - List adapters = computeAdapterOrder(classes); - List interfaces = computeInterfaceOrder(classes); - - // Cache of all types found in the selection - this is needed - // to compute common adapters. - List lastCommonTypes = new ArrayList(); - - boolean classesEmpty = classes.isEmpty(); - boolean interfacesEmpty = interfaces.isEmpty(); - - // Traverse the selection if there is more than one element selected. - for (int i = 1; i < objects.size(); i++) { - // Compute all the super classes for the current element - List otherClasses = computeClassOrder(objects.get(i).getClass()); - if (!classesEmpty) { - classesEmpty = extractCommonClasses(classes, otherClasses); - } - - // Compute all the interfaces for the current element - // and all of its super classes. - List otherInterfaces = computeInterfaceOrder(otherClasses); - if (!interfacesEmpty) { - interfacesEmpty = extractCommonClasses(interfaces, - otherInterfaces); - } - - // Compute all the adapters provided for the calculated - // classes and interfaces for this element. - List classesAndInterfaces = new ArrayList(otherClasses); - if (otherInterfaces != null) { + // Optimization: if n==1 (or if all objects are of the same class), then the + // common class is the object's class, + // and the common adapters are the adapters cached for that class in the adapter + // manager + // See bug 177592 for more details. + if (allSameClass(objects)) { + + Class clazz = objects.get(0).getClass(); + commonAdapters.addAll(Arrays.asList(Platform.getAdapterManager().computeAdapterTypes(clazz))); + List result = new ArrayList(1); + result.add(clazz); + return result; + } + + // Compute all the super classes, interfaces, and adapters + // for the first element. + List classes = computeClassOrder(objects.get(0).getClass()); + List adapters = computeAdapterOrder(classes); + List interfaces = computeInterfaceOrder(classes); + + // Cache of all types found in the selection - this is needed + // to compute common adapters. + List lastCommonTypes = new ArrayList(); + + boolean classesEmpty = classes.isEmpty(); + boolean interfacesEmpty = interfaces.isEmpty(); + + // Traverse the selection if there is more than one element selected. + for (int i = 1; i < objects.size(); i++) { + // Compute all the super classes for the current element + List otherClasses = computeClassOrder(objects.get(i).getClass()); + if (!classesEmpty) { + classesEmpty = extractCommonClasses(classes, otherClasses); + } + + // Compute all the interfaces for the current element + // and all of its super classes. + List otherInterfaces = computeInterfaceOrder(otherClasses); + if (!interfacesEmpty) { + interfacesEmpty = extractCommonClasses(interfaces, otherInterfaces); + } + + // Compute all the adapters provided for the calculated + // classes and interfaces for this element. + List classesAndInterfaces = new ArrayList(otherClasses); + if (otherInterfaces != null) { classesAndInterfaces.addAll(otherInterfaces); } - List otherAdapters = computeAdapterOrder(classesAndInterfaces); - - // Compute common adapters - // Note here that an adapter can match a class or interface, that is - // that an element in the selection may not adapt to a type but instead - // be of that type. - // If the selected classes doesn't have adapters, keep - // adapters that match the given classes types (classes and interfaces). - if (otherAdapters.isEmpty() && !adapters.isEmpty()) { - removeNonCommonAdapters(adapters, classesAndInterfaces); - } else { - if (adapters.isEmpty()) { - removeNonCommonAdapters(otherAdapters, lastCommonTypes); - if (!otherAdapters.isEmpty()) { + List otherAdapters = computeAdapterOrder(classesAndInterfaces); + + // Compute common adapters + // Note here that an adapter can match a class or interface, that is + // that an element in the selection may not adapt to a type but instead + // be of that type. + // If the selected classes doesn't have adapters, keep + // adapters that match the given classes types (classes and interfaces). + if (otherAdapters.isEmpty() && !adapters.isEmpty()) { + removeNonCommonAdapters(adapters, classesAndInterfaces); + } else { + if (adapters.isEmpty()) { + removeNonCommonAdapters(otherAdapters, lastCommonTypes); + if (!otherAdapters.isEmpty()) { adapters.addAll(otherAdapters); } - } else { - // Remove any adapters of the first element that - // are not in the current element's adapter list. - for (Iterator it = adapters.iterator(); it.hasNext();) { - String adapter = (String) it.next(); - if (!otherAdapters.contains(adapter)) { - it.remove(); - } - } - } - } - - // Remember the common search order up to now, this is - // used to match adapters against common classes or interfaces. - lastCommonTypes.clear(); - lastCommonTypes.addAll(classes); - lastCommonTypes.addAll(interfaces); - - if (interfacesEmpty && classesEmpty && adapters.isEmpty()) { - // As soon as we detect nothing in common, just exit. - return null; - } - } - - // Once the common classes, interfaces, and adapters are - // calculated, let's prune the lists to remove duplicates. - ArrayList results = new ArrayList(4); - ArrayList superClasses = new ArrayList(4); - if (!classesEmpty) { - for (int j = 0; j < classes.size(); j++) { - if (classes.get(j) != null) { - superClasses.add(classes.get(j)); - } - } - // Just keep the first super class - if (!superClasses.isEmpty()) { - results.add(superClasses.get(0)); - } - } - - if (!interfacesEmpty) { - removeCommonInterfaces(superClasses, interfaces, results); - } - - // Remove adapters already included as common classes - if (!adapters.isEmpty()) { - removeCommonAdapters(adapters, results); - commonAdapters.addAll(adapters); - } - return results; - } - - /** - * Returns <code>true</code> if all objects in the given list are of the same class, - * <code>false</code> otherwise. + } else { + // Remove any adapters of the first element that + // are not in the current element's adapter list. + for (Iterator it = adapters.iterator(); it.hasNext();) { + String adapter = (String) it.next(); + if (!otherAdapters.contains(adapter)) { + it.remove(); + } + } + } + } + + // Remember the common search order up to now, this is + // used to match adapters against common classes or interfaces. + lastCommonTypes.clear(); + lastCommonTypes.addAll(classes); + lastCommonTypes.addAll(interfaces); + + if (interfacesEmpty && classesEmpty && adapters.isEmpty()) { + // As soon as we detect nothing in common, just exit. + return null; + } + } + + // Once the common classes, interfaces, and adapters are + // calculated, let's prune the lists to remove duplicates. + ArrayList results = new ArrayList(4); + ArrayList superClasses = new ArrayList(4); + if (!classesEmpty) { + for (int j = 0; j < classes.size(); j++) { + if (classes.get(j) != null) { + superClasses.add(classes.get(j)); + } + } + // Just keep the first super class + if (!superClasses.isEmpty()) { + results.add(superClasses.get(0)); + } + } + + if (!interfacesEmpty) { + removeCommonInterfaces(superClasses, interfaces, results); + } + + // Remove adapters already included as common classes + if (!adapters.isEmpty()) { + removeCommonAdapters(adapters, results); + commonAdapters.addAll(adapters); + } + return results; + } + + /** + * Returns <code>true</code> if all objects in the given list are of the same + * class, <code>false</code> otherwise. */ private boolean allSameClass(List objects) { int size = objects.size(); - if (size <= 1) return true; + if (size <= 1) + return true; Class clazz = objects.get(0).getClass(); for (int i = 1; i < size; ++i) { if (!objects.get(i).getClass().equals(clazz)) { @@ -805,199 +798,191 @@ public abstract class ObjectContributorManager implements IExtensionChangeHandle } private boolean extractCommonClasses(List classes, List otherClasses) { - boolean classesEmpty = true; - if (otherClasses.isEmpty()) { - // When no super classes, then it is obvious there - // are no common super classes with the first element - // so clear its list. - classes.clear(); - } else { - // Remove any super classes of the first element that - // are not in the current element's super classes list. - for (int j = 0; j < classes.size(); j++) { - if (classes.get(j) != null) { - classesEmpty = false; // TODO: should this only be set if item not nulled out? - if (!otherClasses.contains(classes.get(j))) { - classes.set(j, null); - } - } - } - } - return classesEmpty; - } - - private void removeNonCommonAdapters(List adapters, List classes) { - for (int i = 0; i < classes.size(); i++) { - Object o = classes.get(i); - if (o != null) { - Class clazz = (Class) o; - String name = clazz.getName(); - if (adapters.contains(name)) { + boolean classesEmpty = true; + if (otherClasses.isEmpty()) { + // When no super classes, then it is obvious there + // are no common super classes with the first element + // so clear its list. + classes.clear(); + } else { + // Remove any super classes of the first element that + // are not in the current element's super classes list. + for (int j = 0; j < classes.size(); j++) { + if (classes.get(j) != null) { + classesEmpty = false; // TODO: should this only be set if item not nulled out? + if (!otherClasses.contains(classes.get(j))) { + classes.set(j, null); + } + } + } + } + return classesEmpty; + } + + private void removeNonCommonAdapters(List adapters, List classes) { + for (int i = 0; i < classes.size(); i++) { + Object o = classes.get(i); + if (o != null) { + Class clazz = (Class) o; + String name = clazz.getName(); + if (adapters.contains(name)) { return; } - } - } - adapters.clear(); - } - - private void removeCommonInterfaces(List superClasses, List types, - List results) { - List dropInterfaces = null; - if (!superClasses.isEmpty()) { - dropInterfaces = computeInterfaceOrder(superClasses); - } - for (int j = 0; j < types.size(); j++) { - if (types.get(j) != null) { - if (dropInterfaces != null - && !dropInterfaces.contains(types.get(j))) { - results.add(types.get(j)); - } - } - } - } - - private List computeAdapterOrder(List classList) { - Set result = new HashSet(4); - IAdapterManager adapterMgr = Platform.getAdapterManager(); - for (Iterator list = classList.iterator(); list.hasNext();) { - Class clazz = ((Class) list.next()); + } + } + adapters.clear(); + } + + private void removeCommonInterfaces(List superClasses, List types, List results) { + List dropInterfaces = null; + if (!superClasses.isEmpty()) { + dropInterfaces = computeInterfaceOrder(superClasses); + } + for (int j = 0; j < types.size(); j++) { + if (types.get(j) != null) { + if (dropInterfaces != null && !dropInterfaces.contains(types.get(j))) { + results.add(types.get(j)); + } + } + } + } + + private List computeAdapterOrder(List classList) { + Set result = new HashSet(4); + IAdapterManager adapterMgr = Platform.getAdapterManager(); + for (Iterator list = classList.iterator(); list.hasNext();) { + Class clazz = ((Class) list.next()); for (String adapter : adapterMgr.computeAdapterTypes(clazz)) { - if (!result.contains(adapter)) { - result.add(adapter); - } - } - } - return new ArrayList(result); - } - - /** - * Returns the common denominator resource class for the given - * collection of objects. - * Do not return a resource class if the objects are resources - * themselves so as to prevent double registration of actions. - */ - private Class getCommonResourceClass(List objects) { - if (objects == null || objects.isEmpty()) { - return null; - } - Class resourceClass = LegacyResourceSupport.getResourceClass(); - if (resourceClass == null) { - // resources plug-in not loaded - no resources. period. - return null; - } - - List testList = new ArrayList(objects.size()); - - for (int i = 0; i < objects.size(); i++) { - Object object = objects.get(i); - - if (object instanceof IAdaptable) { - if (resourceClass.isInstance(object)) { - continue; - } - - Object resource = LegacyResourceSupport - .getAdaptedContributorResource(object); - - if (resource == null) { - //Not a resource and does not adapt. No common resource class - return null; - } - testList.add(resource); - } else { - return null; - } - } - - return getCommonClass(testList); - } - - /** - * Return the ResourceMapping class if the elements all adapt to it. - */ - private Class getResourceMappingClass(List objects) { - if (objects == null || objects.isEmpty()) { - return null; - } - Class resourceMappingClass = LegacyResourceSupport - .getResourceMappingClass(); - if (resourceMappingClass == null) { - // resources plug-in not loaded - no resources. period. - return null; - } - - for (int i = 0; i < objects.size(); i++) { - Object object = objects.get(i); - - if (object instanceof IAdaptable) { - if (resourceMappingClass.isInstance(object)) { - continue; - } - - Object resourceMapping = LegacyResourceSupport - .getAdaptedContributorResourceMapping(object); - - if (resourceMapping == null) { - //Not a resource and does not adapt. No common resource class - return null; - } - } else { - return null; - } - } - // If we get here then all objects adapt to ResourceMapping - return resourceMappingClass; - } - - /** - * Returns the common denominator class for the given - * collection of objects. - */ - private Class getCommonClass(List objects) { - if (objects == null || objects.isEmpty()) { + if (!result.contains(adapter)) { + result.add(adapter); + } + } + } + return new ArrayList(result); + } + + /** + * Returns the common denominator resource class for the given collection of + * objects. Do not return a resource class if the objects are resources + * themselves so as to prevent double registration of actions. + */ + private Class getCommonResourceClass(List objects) { + if (objects == null || objects.isEmpty()) { + return null; + } + Class resourceClass = LegacyResourceSupport.getResourceClass(); + if (resourceClass == null) { + // resources plug-in not loaded - no resources. period. return null; } - Class commonClass = objects.get(0).getClass(); - // try easy - if (objects.size() == 1) { + + List testList = new ArrayList(objects.size()); + + for (int i = 0; i < objects.size(); i++) { + Object object = objects.get(i); + + if (object instanceof IAdaptable) { + if (resourceClass.isInstance(object)) { + continue; + } + + Object resource = LegacyResourceSupport.getAdaptedContributorResource(object); + + if (resource == null) { + // Not a resource and does not adapt. No common resource class + return null; + } + testList.add(resource); + } else { + return null; + } + } + + return getCommonClass(testList); + } + + /** + * Return the ResourceMapping class if the elements all adapt to it. + */ + private Class getResourceMappingClass(List objects) { + if (objects == null || objects.isEmpty()) { + return null; + } + Class resourceMappingClass = LegacyResourceSupport.getResourceMappingClass(); + if (resourceMappingClass == null) { + // resources plug-in not loaded - no resources. period. + return null; + } + + for (int i = 0; i < objects.size(); i++) { + Object object = objects.get(i); + + if (object instanceof IAdaptable) { + if (resourceMappingClass.isInstance(object)) { + continue; + } + + Object resourceMapping = LegacyResourceSupport.getAdaptedContributorResourceMapping(object); + + if (resourceMapping == null) { + // Not a resource and does not adapt. No common resource class + return null; + } + } else { + return null; + } + } + // If we get here then all objects adapt to ResourceMapping + return resourceMappingClass; + } + + /** + * Returns the common denominator class for the given collection of objects. + */ + private Class getCommonClass(List objects) { + if (objects == null || objects.isEmpty()) { + return null; + } + Class commonClass = objects.get(0).getClass(); + // try easy + if (objects.size() == 1) { return commonClass; - // try harder + // try harder } - for (int i = 1; i < objects.size(); i++) { - Object object = objects.get(i); - Class newClass = object.getClass(); - // try the short cut - if (newClass.equals(commonClass)) { + for (int i = 1; i < objects.size(); i++) { + Object object = objects.get(i); + Class newClass = object.getClass(); + // try the short cut + if (newClass.equals(commonClass)) { continue; } - // compute common class - commonClass = getCommonClass(commonClass, newClass); - // give up - if (commonClass == null) { + // compute common class + commonClass = getCommonClass(commonClass, newClass); + // give up + if (commonClass == null) { return null; } - } - return commonClass; - } - - /** - * Returns the common denominator class for - * two input classes. - */ - private Class getCommonClass(Class class1, Class class2) { - List list1 = computeCombinedOrder(class1); - List list2 = computeCombinedOrder(class2); - for (int i = 0; i < list1.size(); i++) { - for (int j = 0; j < list2.size(); j++) { - Class candidate1 = (Class) list1.get(i); - Class candidate2 = (Class) list2.get(j); - if (candidate1.equals(candidate2)) { + } + return commonClass; + } + + /** + * Returns the common denominator class for two input classes. + */ + private Class getCommonClass(Class class1, Class class2) { + List list1 = computeCombinedOrder(class1); + List list2 = computeCombinedOrder(class2); + for (int i = 0; i < list1.size(); i++) { + for (int j = 0; j < list2.size(); j++) { + Class candidate1 = (Class) list1.get(i); + Class candidate2 = (Class) list2.get(j); + if (candidate1.equals(candidate2)) { return candidate1; } - } - } - // no common class - return null; - } + } + } + // no common class + return null; + } } |