blob: bb0dff0edfe8e5d281df97445a617cacbf8b01cc [file] [log] [blame]
/*******************************************************************************
* 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.registry;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.eclipse.core.commands.contexts.Context;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.dynamichelpers.ExtensionTracker;
import org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler;
import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.contexts.IContextService;
import org.eclipse.ui.internal.WorkbenchPlugin;
/**
* The registry of action set extensions.
*/
public class ActionSetRegistry implements IExtensionChangeHandler {
/**
* @since 3.1
*/
private class ActionSetPartAssociation {
/**
* @param partId
* @param actionSetId
*/
public ActionSetPartAssociation(String partId, String actionSetId) {
this.partId = partId;
this.actionSetId = actionSetId;
}
String partId;
String actionSetId;
}
private ArrayList children = new ArrayList();
private Map mapPartToActionSetIds = new HashMap();
private Map mapPartToActionSets = new HashMap();
private IContextService contextService;
/**
* Creates the action set registry.
*/
public ActionSetRegistry() {
contextService = (IContextService) PlatformUI
.getWorkbench().getService(IContextService.class);
PlatformUI.getWorkbench().getExtensionTracker().registerHandler(
this,
ExtensionTracker
.createExtensionPointFilter(new IExtensionPoint[] {
getActionSetExtensionPoint(),
getActionSetPartAssociationExtensionPoint() }));
readFromRegistry();
}
/**
* Return the action set part association extension point.
*
* @return the action set part association extension point
* @since 3.1
*/
private IExtensionPoint getActionSetPartAssociationExtensionPoint() {
return Platform
.getExtensionRegistry().getExtensionPoint(
PlatformUI.PLUGIN_ID,
IWorkbenchRegistryConstants.PL_ACTION_SET_PART_ASSOCIATIONS);
}
/**
* Return the action set extension point.
*
* @return the action set extension point
* @since 3.1
*/
private IExtensionPoint getActionSetExtensionPoint() {
return Platform
.getExtensionRegistry().getExtensionPoint(
PlatformUI.PLUGIN_ID,
IWorkbenchRegistryConstants.PL_ACTION_SETS);
}
/**
* Adds an action set.
* @param desc
*/
private void addActionSet(ActionSetDescriptor desc) {
children.add(desc);
Context actionSetContext = contextService.getContext(desc.getId());
if (!actionSetContext.isDefined()) {
actionSetContext.define(desc.getLabel(), desc.getDescription(),
"org.eclipse.ui.contexts.actionSet"); //$NON-NLS-1$
}
}
/**
* Remove the action set.
*
* @param desc
*/
private void removeActionSet(IActionSetDescriptor desc) {
Context actionSetContext = contextService.getContext(desc.getId());
if (actionSetContext.isDefined()) {
actionSetContext.undefine();
}
children.remove(desc);
}
/**
* Adds an association between an action set an a part.
*/
private Object addAssociation(String actionSetId, String partId) {
// get the action set ids for this part
ArrayList actionSets = (ArrayList) mapPartToActionSetIds.get(partId);
if (actionSets == null) {
actionSets = new ArrayList();
mapPartToActionSetIds.put(partId, actionSets);
}
actionSets.add(actionSetId);
ActionSetPartAssociation association = new ActionSetPartAssociation(partId, actionSetId);
return association;
}
/**
* Finds and returns the registered action set with the given id.
*
* @param id the action set id
* @return the action set, or <code>null</code> if none
* @see IActionSetDescriptor#getId
*/
public IActionSetDescriptor findActionSet(String id) {
Iterator i = children.iterator();
while (i.hasNext()) {
IActionSetDescriptor desc = (IActionSetDescriptor) i.next();
if (desc.getId().equals(id)) {
return desc;
}
}
return null;
}
/**
* Returns a list of the action sets known to the workbench.
*
* @return a list of action sets
*/
public IActionSetDescriptor[] getActionSets() {
return (IActionSetDescriptor []) children.toArray(new IActionSetDescriptor [children.size()]);
}
/**
* Returns a list of the action sets associated with the given part id.
*
* @param partId the part id
* @return a list of action sets
*/
public IActionSetDescriptor[] getActionSetsFor(String partId) {
// check the resolved map first
ArrayList actionSets = (ArrayList) mapPartToActionSets.get(partId);
if (actionSets != null) {
return (IActionSetDescriptor[]) actionSets
.toArray(new IActionSetDescriptor[actionSets.size()]);
}
// get the action set ids for this part
ArrayList actionSetIds = (ArrayList) mapPartToActionSetIds.get(partId);
if (actionSetIds == null) {
return new IActionSetDescriptor[0];
}
// resolve to action sets
actionSets = new ArrayList(actionSetIds.size());
for (Iterator i = actionSetIds.iterator(); i.hasNext();) {
String actionSetId = (String) i.next();
IActionSetDescriptor actionSet = findActionSet(actionSetId);
if (actionSet != null) {
actionSets.add(actionSet);
} else {
WorkbenchPlugin.log("Unable to associate action set with part: " + //$NON-NLS-1$
partId + ". Action set " + actionSetId + " not found."); //$NON-NLS-2$ //$NON-NLS-1$
}
}
mapPartToActionSets.put(partId, actionSets);
return (IActionSetDescriptor[]) actionSets
.toArray(new IActionSetDescriptor[actionSets.size()]);
}
/**
* Reads the registry.
*/
private void readFromRegistry() {
IExtension[] extensions = getActionSetExtensionPoint().getExtensions();
for (int i = 0; i < extensions.length; i++) {
addActionSets(PlatformUI.getWorkbench().getExtensionTracker(),
extensions[i]);
}
extensions = getActionSetPartAssociationExtensionPoint()
.getExtensions();
for (int i = 0; i < extensions.length; i++) {
addActionSetPartAssociations(PlatformUI.getWorkbench()
.getExtensionTracker(), extensions[i]);
}
}
/* (non-Javadoc)
* @see org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler#addExtension(org.eclipse.core.runtime.dynamichelpers.IExtensionTracker, org.eclipse.core.runtime.IExtension)
*/
public void addExtension(IExtensionTracker tracker, IExtension extension) {
String extensionPointUniqueIdentifier = extension.getExtensionPointUniqueIdentifier();
if (extensionPointUniqueIdentifier.equals(getActionSetExtensionPoint().getUniqueIdentifier())) {
addActionSets(tracker, extension);
}
else if (extensionPointUniqueIdentifier.equals(getActionSetPartAssociationExtensionPoint().getUniqueIdentifier())){
addActionSetPartAssociations(tracker, extension);
}
}
/**
* @param tracker
* @param extension
*/
private void addActionSetPartAssociations(IExtensionTracker tracker, IExtension extension) {
IConfigurationElement [] elements = extension.getConfigurationElements();
for (int i = 0; i < elements.length; i++) {
IConfigurationElement element = elements[i];
if (element.getName().equals(IWorkbenchRegistryConstants.TAG_ACTION_SET_PART_ASSOCIATION)) {
String actionSetId = element.getAttribute(IWorkbenchRegistryConstants.ATT_TARGET_ID);
IConfigurationElement[] children = element.getChildren();
for (int j = 0; j < children.length; j++) {
IConfigurationElement child = children[j];
if (child.getName().equals(IWorkbenchRegistryConstants.TAG_PART)) {
String partId = child.getAttribute(IWorkbenchRegistryConstants.ATT_ID);
if (partId != null) {
Object trackingObject = addAssociation(actionSetId, partId);
if (trackingObject != null) {
tracker.registerObject(extension,
trackingObject,
IExtensionTracker.REF_STRONG);
}
}
} else {
WorkbenchPlugin.log("Unable to process element: " + //$NON-NLS-1$
child.getName() + " in action set part associations extension: " + //$NON-NLS-1$
extension.getUniqueIdentifier());
}
}
}
}
// TODO: optimize
mapPartToActionSets.clear();
}
/**
* @param tracker
* @param extension
*/
private void addActionSets(IExtensionTracker tracker, IExtension extension) {
IConfigurationElement [] elements = extension.getConfigurationElements();
for (int i = 0; i < elements.length; i++) {
IConfigurationElement element = elements[i];
if (element.getName().equals(IWorkbenchRegistryConstants.TAG_ACTION_SET)) {
try {
ActionSetDescriptor desc = new ActionSetDescriptor(element);
addActionSet(desc);
tracker.registerObject(extension, desc, IExtensionTracker.REF_WEAK);
} catch (CoreException e) {
// log an error since its not safe to open a dialog here
WorkbenchPlugin
.log(
"Unable to create action set descriptor.", e.getStatus());//$NON-NLS-1$
}
}
}
// TODO: optimize
mapPartToActionSets.clear();
}
/* (non-Javadoc)
* @see org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler#removeExtension(org.eclipse.core.runtime.IExtension, java.lang.Object[])
*/
public void removeExtension(IExtension extension, Object[] objects) {
String extensionPointUniqueIdentifier = extension.getExtensionPointUniqueIdentifier();
if (extensionPointUniqueIdentifier.equals(getActionSetExtensionPoint().getUniqueIdentifier())) {
removeActionSets(objects);
}
else if (extensionPointUniqueIdentifier.equals(getActionSetPartAssociationExtensionPoint().getUniqueIdentifier())){
removeActionSetPartAssociations(objects);
}
}
/**
* @param objects
*/
private void removeActionSetPartAssociations(Object[] objects) {
for (int i = 0; i < objects.length; i++) {
Object object = objects[i];
if (object instanceof ActionSetPartAssociation) {
ActionSetPartAssociation association = (ActionSetPartAssociation) object;
String actionSetId = association.actionSetId;
ArrayList actionSets = (ArrayList) mapPartToActionSetIds.get(association.partId);
if (actionSets == null) {
return;
}
actionSets.remove(actionSetId);
if (actionSets.isEmpty()) {
mapPartToActionSetIds.remove(association.partId);
}
}
}
// TODO: optimize
mapPartToActionSets.clear();
}
/**
* @param objects
*/
private void removeActionSets(Object[] objects) {
for (int i = 0; i < objects.length; i++) {
Object object = objects[i];
if (object instanceof IActionSetDescriptor) {
IActionSetDescriptor desc = (IActionSetDescriptor) object;
removeActionSet(desc);
// now clean up the part associations
// TODO: this is expensive. We should consider another map from
// actionsets
// to parts.
for (Iterator j = mapPartToActionSetIds.values().iterator(); j
.hasNext();) {
ArrayList list = (ArrayList) j.next();
list.remove(desc.getId());
if (list.isEmpty()) {
j.remove();
}
}
}
}
// TODO: optimize
mapPartToActionSets.clear();
}
}