blob: c1ec6e7577e74db2d0275940a336b4466011a82a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2008 IBM Corporation and others.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
* 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;
}
}