Package org.eclipse.ui.internal

Source Code of org.eclipse.ui.internal.ObjectContributorManager

/*******************************************************************************
* Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.internal;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IAdapterManager;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler;
import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.util.Util;

/**
* 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>
* </ul>
*
* @see IObjectContributor
*/
public abstract class ObjectContributorManager implements IExtensionChangeHandler {
 
  /**
   * @since 3.1
   */
  private class ContributorRecord {
    /**
     * @param contributor
     * @param targetType
     */
    public ContributorRecord(IObjectContributor contributor, String targetType) {
      this.contributor = contributor;
      this.objectClassName = targetType;
    }
   
    String objectClassName;
    IObjectContributor contributor;
  }

    /** Table of contributors. */
    protected Map contributors;

    /** 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 adaptable class contributor search paths; <code>null</code> if none. */
    protected Map adaptableLookup;
   
    protected Set contributorRecordSet;

    /**
     * Constructs a new contributor manager.
     */
    public ObjectContributorManager() {
        contributors = new Hashtable(5);
        contributorRecordSet = new HashSet(5);
        objectLookup = null;
        resourceAdapterLookup = null;
        adaptableLookup = null;
        if(canHandleExtensionTracking()){
          IExtensionTracker tracker = PlatformUI.getWorkbench().getExtensionTracker();
          tracker.registerHandler(this, null);
        }
    }

    /**
     * Return whether or not the receiver handles extension
     * tracking. Default is <code>true</code>. Subclasses may override.
     * @return boolean <code>true</code> if it should be registered
     * as an extension handler.
     */
    protected boolean canHandleExtensionTracking() {
    return true;
  }

  /**
     * 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) {
      resourceAdapterLookup = new HashMap();
    }
        resourceAdapterLookup.put(adapterClass, results);
    }
   
    /**
     * 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);
    }

    /**
     * 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 (int i = 0; i < interfaces.length; i++) {
            Class interfac = interfaces[i];
            if (seen.get(interfac) == null) {
                result.add(interfac);
                seen.put(interfac, interfac);
                newInterfaces.add(interfac);
            }
        }
        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
   * @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) {
        return false;
      }
        }
        return true;
    }

    /**
   * Return whether the given contributor is applicable to all elements in the
   * list.
   *
   * @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) {
        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 = (IConfigurationElement) Util.getAdapter(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) {
      return;
    }
        contributorList.remove(contributor);
        if (contributorList.isEmpty()) {
      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)
     
      // 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();
       
        // 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();) {
        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) {
    List objectList = null;
    // Lookup the results in the cache first.
    if (objectLookup != null) {
      objectList = (List) objectLookup.get(objectClass);
    }
    if (objectList == null) {
      objectList = addContributorsFor(objectClass);
      if (objectList.size() == 0) {
        objectList = Collections.EMPTY_LIST;
      }
      else {
        objectList = Collections.unmodifiableList(objectList);
      }
      cacheObjectLookup(objectClass, objectList);
    }
    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
     */
  protected List getResourceContributors(Class resourceClass) {
    List resourceList = null;
    if (resourceAdapterLookup != null) {
      resourceList = (List) resourceAdapterLookup.get(resourceClass);
    }
    if (resourceList == null) {
      resourceList = addContributorsFor(resourceClass);
      if (resourceList.size() == 0) {
        resourceList = Collections.EMPTY_LIST;
      } else {
        resourceList = Collections.unmodifiableList(filterOnlyAdaptableContributors(resourceList));
      }
      cacheResourceAdapterLookup(resourceClass, resourceList);
    }
    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
     */
  protected List getAdaptableContributors(String adapterType) {
    List adaptableList = null;
    // Lookup the results in the cache first, there are two caches
    // one that stores non-adapter contributions and the other
    // contains adapter contributions.
    if (adaptableLookup != null) {
      adaptableList = (List) adaptableLookup.get(adapterType);
    }
    if (adaptableList == null) {
      // ignore resource adapters because these must be adapted via the
      // IContributorResourceAdapter.
      if (LegacyResourceSupport.isResourceType(adapterType) || LegacyResourceSupport.isResourceMappingType(adapterType)) {
        adaptableList = Collections.EMPTY_LIST;
      }
      else {
        adaptableList = (List) contributors.get(adapterType);
        if (adaptableList == null || adaptableList.size() == 0) {
          adaptableList = Collections.EMPTY_LIST;
        } else {
          adaptableList = Collections.unmodifiableList(filterOnlyAdaptableContributors(adaptableList));
        }
      }
      cacheAdaptableLookup(adapterType, adaptableList);
    }
    return adaptableList;
  }
 
  /**
   * 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();) {
      Class clazz = ((Class) it.next());
      List commonTypes = computeCombinedOrder(clazz);
      for (Iterator it2 = commonTypes.iterator(); it2.hasNext();) {
        Class type = (Class) it2.next();
        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 (int i = 0; i < interfaces.length; i++) {
                result.add(interfaces[i]);
            }
            // 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) {
          adaptableContributors = new ArrayList();
        }
        adaptableContributors.add(c);
      }
    }
    return adaptableContributors == null ? Collections.EMPTY_LIST : adaptableContributors;
  }
 
    /* (non-Javadoc)
     * @see org.eclipse.core.runtime.dynamicHelpers.IExtensionChangeHandler#removeExtension(org.eclipse.core.runtime.IExtension, java.lang.Object[])
     */
    public void removeExtension(IExtension source, Object[] objects) {
        for (int i = 0; i < objects.length; i++) {
            if (objects[i] instanceof ContributorRecord) {
                ContributorRecord contributorRecord = (ContributorRecord) objects[i];
                unregisterContributor((contributorRecord).contributor, (contributorRecord).objectClassName);
                contributorRecordSet.remove(contributorRecord);
            }
        }
    }

    /**
     * Remove listeners and dispose of this manager.
     *
     * @since 3.1
     */
    public void dispose() {
      if(canHandleExtensionTracking()) {
      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.
   */
  private static void addAll(Collection collection, List toAdd) {
    for (int i = 0, size = toAdd.size(); i < size; ++i) {
      collection.add(toAdd.get(i));
    }
  }

    /**
     * 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.size() == 0) {
      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) {
        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()) {
            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.
   */
  private boolean allSameClass(List objects) {
    int size = objects.size();
    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)) {
        return false;
      }
    }
    return true;
  }

  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)) {
          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());
            String[] adapters = adapterMgr.computeAdapterTypes(clazz);
            for (int i = 0; i < adapters.length; i++) {
                String adapter = adapters[i];
                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.size() == 0) {
            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.size() == 0) {
            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.size() == 0) {
      return null;
    }
        Class commonClass = objects.get(0).getClass();
        // try easy
        if (objects.size() == 1) {
      return commonClass;
        // 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)) {
        continue;
      }
            // 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 candidate1;
        }
            }
        }
        // no common class
        return null;
    }
}
TOP

Related Classes of org.eclipse.ui.internal.ObjectContributorManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.