| /******************************************************************************* |
| * Copyright (c) 2005, 2008 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.dltk.core; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IConfigurationElement; |
| import org.eclipse.core.runtime.IExtension; |
| import org.eclipse.core.runtime.IExtensionRegistry; |
| import org.eclipse.core.runtime.Platform; |
| |
| /** |
| * Abstract base class that can be used to manage extension point contributions |
| * that may have more then one implementation. |
| * |
| * <p> |
| * Examples: |
| * <ul> |
| * <li>Source Parsers |
| * <li>Debugging Engines |
| * </ul> |
| * </p> |
| */ |
| public abstract class DLTKContributionExtensionManager { |
| private static final String NATURE_ID = "natureId"; //$NON-NLS-1$ |
| |
| private static final String SELECTOR_TAG = "selector"; //$NON-NLS-1$ |
| public static final String CLASS_TAG = "class"; //$NON-NLS-1$ |
| |
| private IDLTKContributionSelector defaultSelector; |
| |
| private Map natureToContribMap = new HashMap(); |
| private Map natureToSelectorMap = new HashMap(); |
| |
| protected DLTKContributionExtensionManager() { |
| this.defaultSelector = new DLTKPriorityContributionSelector(); |
| |
| loadExtensionPoints(); |
| } |
| |
| public IDLTKContributedExtension[] getContributions(String natureId) { |
| List contributions = getContributionsByNature(natureId); |
| return (IDLTKContributedExtension[]) contributions |
| .toArray(new IDLTKContributedExtension[contributions.size()]); |
| } |
| |
| public IDLTKContributedExtension getSelectedContribution(IProject project, |
| String natureId) { |
| |
| IDLTKContributedExtension[] contributions = getContributions(natureId); |
| |
| if (contributions.length > 0) { |
| |
| IDLTKContributionSelector selector = getSelector(natureId); |
| if (selector == null) { |
| selector = defaultSelector; |
| } |
| |
| return selector.select(contributions, project); |
| } |
| |
| return null; |
| } |
| |
| /** |
| * Retrieves a registered contribution based upon its priority. |
| * |
| * @param project |
| * project |
| * @param natureId |
| * nature id |
| */ |
| public IDLTKContributedExtension getPriorityContribution(IProject project, |
| String natureId) { |
| IDLTKContributedExtension[] contributions = getContributions(natureId); |
| return defaultSelector.select(contributions, project); |
| } |
| |
| /** |
| * Get the contributions registered for the given nature id |
| * |
| * @param natureId |
| * nature id |
| * |
| * @return list of avaiable contributions or |
| * <code>Collections.EMPTY_LIST</code> if no contributions have been |
| * registered by the plugin |
| */ |
| protected final List getContributionsByNature(String natureId) { |
| if (!hasContributions(natureId)) { |
| return Collections.EMPTY_LIST; |
| } |
| |
| return (List) natureToContribMap.get(natureId); |
| } |
| |
| protected final IDLTKContributionSelector getSelector(String natureId) { |
| return (IDLTKContributionSelector) natureToSelectorMap.get(natureId); |
| } |
| |
| /** |
| * Checks if any contributions have been created for the given nature id |
| * |
| * @param natureId |
| * nature id |
| * |
| * @return true if there are contributions, false otherwise |
| */ |
| protected final boolean hasContributions(String natureId) { |
| if (natureToContribMap.containsKey(natureId)) { |
| List list = (List) natureToContribMap.get(natureId); |
| return !list.isEmpty(); |
| } |
| |
| return false; |
| } |
| |
| /** |
| * Has a selector been configured for the contribution |
| * |
| * @param natureId |
| * nature id |
| * |
| * @return true if a selector has been configured, false otherwise |
| */ |
| public final boolean hasSelector(String natureId) { |
| return natureToSelectorMap.containsKey(natureId); |
| } |
| |
| /** |
| * Returns a contributed extension implementation based on id. |
| * |
| * @param id |
| * contribution id |
| * |
| * @return contribution implementation |
| */ |
| public final IDLTKContributedExtension getContributionById(String id) { |
| Iterator keys = natureToContribMap.keySet().iterator(); |
| while (keys.hasNext()) { |
| List list = (List) natureToContribMap.get(keys.next()); |
| |
| for (Iterator iter = list.iterator(); iter.hasNext();) { |
| IDLTKContributedExtension contrib = (IDLTKContributedExtension) iter |
| .next(); |
| if (contrib.getId().equals(id)) { |
| return contrib; |
| } |
| } |
| } |
| |
| return null; |
| } |
| |
| /** |
| * Returns the name of the contribution xml element |
| */ |
| protected abstract String getContributionElementName(); |
| |
| /** |
| * Returns the name of the extension point to load |
| */ |
| protected abstract String getExtensionPoint(); |
| |
| /** |
| * Checks if the passed object is valid for the given contribution. |
| * |
| * <p> |
| * The passed object will have been created via a call to |
| * {@link IConfigurationElement#createExecutableExtension(String)} |
| * </p> |
| * |
| * @param object |
| * contribution implementation class |
| * |
| * @return true if valid, false otherwise |
| */ |
| protected abstract boolean isValidContribution(Object object); |
| |
| /** |
| * Configure the object being contributed with any configuration data it may |
| * need. |
| * |
| * <p> |
| * Sub-classes should override this method if the input object was not |
| * configured using |
| * {@link org.eclipse.core.runtime.IExecutableExtension#setInitializationData(IConfigurationElement, String, Object)} |
| * </p> |
| */ |
| protected Object configureContribution(Object object, |
| IConfigurationElement config) { |
| return object; |
| } |
| |
| protected final void addContribution(String natureId, |
| IConfigurationElement element) { |
| try { |
| Object object = element.createExecutableExtension(CLASS_TAG); |
| |
| if (isValidContribution(object)) { |
| /* |
| * handle the case where the contribution is not the object that |
| * was just created. |
| */ |
| Object contrib = configureContribution(object, element); |
| |
| List list = (List) natureToContribMap.get(natureId); |
| if (list == null) { |
| list = new ArrayList(); |
| natureToContribMap.put(natureId, list); |
| } |
| |
| list.add(contrib); |
| } |
| } catch (CoreException e) { |
| e.printStackTrace(); |
| } |
| |
| } |
| |
| protected final void addSelector(String natureId, |
| IConfigurationElement element) { |
| try { |
| Object object = element.createExecutableExtension(CLASS_TAG); |
| if (object instanceof IDLTKContributionSelector) { |
| // XXX: what if multiple extensions define a selector |
| natureToSelectorMap.put(natureId, object); |
| } |
| } catch (CoreException e) { |
| e.printStackTrace(); |
| } |
| } |
| |
| private void loadChildren(String natureId, |
| IConfigurationElement[] innerElements) { |
| for (int j = 0; j < innerElements.length; j++) { |
| IConfigurationElement innerElement = innerElements[j]; |
| String name = innerElement.getName(); |
| |
| if (name.equals(getContributionElementName())) { |
| addContribution(natureId, innerElement); |
| } else if (name.equals(SELECTOR_TAG)) { |
| addSelector(natureId, innerElement); |
| } |
| } |
| } |
| |
| private void loadExtensionPoints() { |
| IExtensionRegistry registry = Platform.getExtensionRegistry(); |
| IExtension[] extensions = registry.getExtensionPoint( |
| getExtensionPoint()).getExtensions(); |
| |
| for (int i = 0; i < extensions.length; i++) { |
| IExtension extension = extensions[i]; |
| IConfigurationElement[] elements = extension |
| .getConfigurationElements(); |
| for (IConfigurationElement main : elements) { |
| if (isNatureContribution(main)) { |
| String natureId = main.getAttribute(NATURE_ID); |
| IConfigurationElement[] innerElements = main.getChildren(); |
| loadChildren(natureId, innerElements); |
| } |
| } |
| } |
| } |
| |
| /** |
| * @param main |
| * @return |
| * @since 2.0 |
| */ |
| protected boolean isNatureContribution(IConfigurationElement main) { |
| return true; |
| } |
| |
| } |