001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.internal.registry;
011:
012: import java.util.ArrayList;
013: import java.util.HashMap;
014: import java.util.Iterator;
015: import java.util.Map;
016:
017: import org.eclipse.core.commands.contexts.Context;
018: import org.eclipse.core.runtime.CoreException;
019: import org.eclipse.core.runtime.IConfigurationElement;
020: import org.eclipse.core.runtime.IExtension;
021: import org.eclipse.core.runtime.IExtensionPoint;
022: import org.eclipse.core.runtime.Platform;
023: import org.eclipse.core.runtime.dynamichelpers.ExtensionTracker;
024: import org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler;
025: import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker;
026: import org.eclipse.ui.PlatformUI;
027: import org.eclipse.ui.contexts.IContextService;
028: import org.eclipse.ui.internal.WorkbenchPlugin;
029:
030: /**
031: * The registry of action set extensions.
032: */
033: public class ActionSetRegistry implements IExtensionChangeHandler {
034:
035: /**
036: * @since 3.1
037: */
038: private class ActionSetPartAssociation {
039: /**
040: * @param partId
041: * @param actionSetId
042: */
043: public ActionSetPartAssociation(String partId,
044: String actionSetId) {
045: this .partId = partId;
046: this .actionSetId = actionSetId;
047: }
048:
049: String partId;
050: String actionSetId;
051: }
052:
053: private ArrayList children = new ArrayList();
054:
055: private Map mapPartToActionSetIds = new HashMap();
056:
057: private Map mapPartToActionSets = new HashMap();
058:
059: private IContextService contextService;
060:
061: /**
062: * Creates the action set registry.
063: */
064: public ActionSetRegistry() {
065: contextService = (IContextService) PlatformUI.getWorkbench()
066: .getService(IContextService.class);
067: PlatformUI
068: .getWorkbench()
069: .getExtensionTracker()
070: .registerHandler(
071: this ,
072: ExtensionTracker
073: .createExtensionPointFilter(new IExtensionPoint[] {
074: getActionSetExtensionPoint(),
075: getActionSetPartAssociationExtensionPoint() }));
076: readFromRegistry();
077: }
078:
079: /**
080: * Return the action set part association extension point.
081: *
082: * @return the action set part association extension point
083: * @since 3.1
084: */
085: private IExtensionPoint getActionSetPartAssociationExtensionPoint() {
086: return Platform
087: .getExtensionRegistry()
088: .getExtensionPoint(
089: PlatformUI.PLUGIN_ID,
090: IWorkbenchRegistryConstants.PL_ACTION_SET_PART_ASSOCIATIONS);
091: }
092:
093: /**
094: * Return the action set extension point.
095: *
096: * @return the action set extension point
097: * @since 3.1
098: */
099: private IExtensionPoint getActionSetExtensionPoint() {
100: return Platform.getExtensionRegistry().getExtensionPoint(
101: PlatformUI.PLUGIN_ID,
102: IWorkbenchRegistryConstants.PL_ACTION_SETS);
103: }
104:
105: /**
106: * Adds an action set.
107: * @param desc
108: */
109: private void addActionSet(ActionSetDescriptor desc) {
110: children.add(desc);
111: Context actionSetContext = contextService.getContext(desc
112: .getId());
113: if (!actionSetContext.isDefined()) {
114: actionSetContext.define(desc.getLabel(), desc
115: .getDescription(),
116: "org.eclipse.ui.contexts.actionSet"); //$NON-NLS-1$
117: }
118: }
119:
120: /**
121: * Remove the action set.
122: *
123: * @param desc
124: */
125: private void removeActionSet(IActionSetDescriptor desc) {
126: Context actionSetContext = contextService.getContext(desc
127: .getId());
128: if (actionSetContext.isDefined()) {
129: actionSetContext.undefine();
130: }
131: children.remove(desc);
132: }
133:
134: /**
135: * Adds an association between an action set an a part.
136: */
137: private Object addAssociation(String actionSetId, String partId) {
138: // get the action set ids for this part
139: ArrayList actionSets = (ArrayList) mapPartToActionSetIds
140: .get(partId);
141: if (actionSets == null) {
142: actionSets = new ArrayList();
143: mapPartToActionSetIds.put(partId, actionSets);
144: }
145: actionSets.add(actionSetId);
146:
147: ActionSetPartAssociation association = new ActionSetPartAssociation(
148: partId, actionSetId);
149: return association;
150: }
151:
152: /**
153: * Finds and returns the registered action set with the given id.
154: *
155: * @param id the action set id
156: * @return the action set, or <code>null</code> if none
157: * @see IActionSetDescriptor#getId
158: */
159: public IActionSetDescriptor findActionSet(String id) {
160: Iterator i = children.iterator();
161: while (i.hasNext()) {
162: IActionSetDescriptor desc = (IActionSetDescriptor) i.next();
163: if (desc.getId().equals(id)) {
164: return desc;
165: }
166: }
167: return null;
168: }
169:
170: /**
171: * Returns a list of the action sets known to the workbench.
172: *
173: * @return a list of action sets
174: */
175: public IActionSetDescriptor[] getActionSets() {
176: return (IActionSetDescriptor[]) children
177: .toArray(new IActionSetDescriptor[children.size()]);
178: }
179:
180: /**
181: * Returns a list of the action sets associated with the given part id.
182: *
183: * @param partId the part id
184: * @return a list of action sets
185: */
186: public IActionSetDescriptor[] getActionSetsFor(String partId) {
187: // check the resolved map first
188: ArrayList actionSets = (ArrayList) mapPartToActionSets
189: .get(partId);
190: if (actionSets != null) {
191: return (IActionSetDescriptor[]) actionSets
192: .toArray(new IActionSetDescriptor[actionSets.size()]);
193: }
194:
195: // get the action set ids for this part
196: ArrayList actionSetIds = (ArrayList) mapPartToActionSetIds
197: .get(partId);
198: if (actionSetIds == null) {
199: return new IActionSetDescriptor[0];
200: }
201:
202: // resolve to action sets
203: actionSets = new ArrayList(actionSetIds.size());
204: for (Iterator i = actionSetIds.iterator(); i.hasNext();) {
205: String actionSetId = (String) i.next();
206: IActionSetDescriptor actionSet = findActionSet(actionSetId);
207: if (actionSet != null) {
208: actionSets.add(actionSet);
209: } else {
210: WorkbenchPlugin
211: .log("Unable to associate action set with part: " + //$NON-NLS-1$
212: partId
213: + ". Action set " + actionSetId + " not found."); //$NON-NLS-2$ //$NON-NLS-1$
214: }
215: }
216:
217: mapPartToActionSets.put(partId, actionSets);
218:
219: return (IActionSetDescriptor[]) actionSets
220: .toArray(new IActionSetDescriptor[actionSets.size()]);
221: }
222:
223: /**
224: * Reads the registry.
225: */
226: private void readFromRegistry() {
227: IExtension[] extensions = getActionSetExtensionPoint()
228: .getExtensions();
229: for (int i = 0; i < extensions.length; i++) {
230: addActionSets(PlatformUI.getWorkbench()
231: .getExtensionTracker(), extensions[i]);
232: }
233:
234: extensions = getActionSetPartAssociationExtensionPoint()
235: .getExtensions();
236: for (int i = 0; i < extensions.length; i++) {
237: addActionSetPartAssociations(PlatformUI.getWorkbench()
238: .getExtensionTracker(), extensions[i]);
239: }
240: }
241:
242: /* (non-Javadoc)
243: * @see org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler#addExtension(org.eclipse.core.runtime.dynamichelpers.IExtensionTracker, org.eclipse.core.runtime.IExtension)
244: */
245: public void addExtension(IExtensionTracker tracker,
246: IExtension extension) {
247: String extensionPointUniqueIdentifier = extension
248: .getExtensionPointUniqueIdentifier();
249: if (extensionPointUniqueIdentifier
250: .equals(getActionSetExtensionPoint()
251: .getUniqueIdentifier())) {
252: addActionSets(tracker, extension);
253: } else if (extensionPointUniqueIdentifier
254: .equals(getActionSetPartAssociationExtensionPoint()
255: .getUniqueIdentifier())) {
256: addActionSetPartAssociations(tracker, extension);
257: }
258: }
259:
260: /**
261: * @param tracker
262: * @param extension
263: */
264: private void addActionSetPartAssociations(
265: IExtensionTracker tracker, IExtension extension) {
266: IConfigurationElement[] elements = extension
267: .getConfigurationElements();
268: for (int i = 0; i < elements.length; i++) {
269: IConfigurationElement element = elements[i];
270: if (element
271: .getName()
272: .equals(
273: IWorkbenchRegistryConstants.TAG_ACTION_SET_PART_ASSOCIATION)) {
274: String actionSetId = element
275: .getAttribute(IWorkbenchRegistryConstants.ATT_TARGET_ID);
276: IConfigurationElement[] children = element
277: .getChildren();
278: for (int j = 0; j < children.length; j++) {
279: IConfigurationElement child = children[j];
280: if (child.getName().equals(
281: IWorkbenchRegistryConstants.TAG_PART)) {
282: String partId = child
283: .getAttribute(IWorkbenchRegistryConstants.ATT_ID);
284: if (partId != null) {
285: Object trackingObject = addAssociation(
286: actionSetId, partId);
287: if (trackingObject != null) {
288: tracker.registerObject(extension,
289: trackingObject,
290: IExtensionTracker.REF_STRONG);
291:
292: }
293:
294: }
295: } else {
296: WorkbenchPlugin
297: .log("Unable to process element: " + //$NON-NLS-1$
298: child.getName()
299: + " in action set part associations extension: " + //$NON-NLS-1$
300: extension.getUniqueIdentifier());
301: }
302: }
303: }
304: }
305:
306: // TODO: optimize
307: mapPartToActionSets.clear();
308: }
309:
310: /**
311: * @param tracker
312: * @param extension
313: */
314: private void addActionSets(IExtensionTracker tracker,
315: IExtension extension) {
316: IConfigurationElement[] elements = extension
317: .getConfigurationElements();
318: for (int i = 0; i < elements.length; i++) {
319: IConfigurationElement element = elements[i];
320: if (element.getName().equals(
321: IWorkbenchRegistryConstants.TAG_ACTION_SET)) {
322: try {
323: ActionSetDescriptor desc = new ActionSetDescriptor(
324: element);
325: addActionSet(desc);
326: tracker.registerObject(extension, desc,
327: IExtensionTracker.REF_WEAK);
328:
329: } catch (CoreException e) {
330: // log an error since its not safe to open a dialog here
331: WorkbenchPlugin
332: .log(
333: "Unable to create action set descriptor.", e.getStatus());//$NON-NLS-1$
334: }
335: }
336: }
337:
338: // TODO: optimize
339: mapPartToActionSets.clear();
340: }
341:
342: /* (non-Javadoc)
343: * @see org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler#removeExtension(org.eclipse.core.runtime.IExtension, java.lang.Object[])
344: */
345: public void removeExtension(IExtension extension, Object[] objects) {
346: String extensionPointUniqueIdentifier = extension
347: .getExtensionPointUniqueIdentifier();
348: if (extensionPointUniqueIdentifier
349: .equals(getActionSetExtensionPoint()
350: .getUniqueIdentifier())) {
351: removeActionSets(objects);
352: } else if (extensionPointUniqueIdentifier
353: .equals(getActionSetPartAssociationExtensionPoint()
354: .getUniqueIdentifier())) {
355: removeActionSetPartAssociations(objects);
356: }
357: }
358:
359: /**
360: * @param objects
361: */
362: private void removeActionSetPartAssociations(Object[] objects) {
363: for (int i = 0; i < objects.length; i++) {
364: Object object = objects[i];
365: if (object instanceof ActionSetPartAssociation) {
366: ActionSetPartAssociation association = (ActionSetPartAssociation) object;
367: String actionSetId = association.actionSetId;
368: ArrayList actionSets = (ArrayList) mapPartToActionSetIds
369: .get(association.partId);
370: if (actionSets == null) {
371: return;
372: }
373: actionSets.remove(actionSetId);
374: if (actionSets.isEmpty()) {
375: mapPartToActionSetIds.remove(association.partId);
376: }
377: }
378: }
379: // TODO: optimize
380: mapPartToActionSets.clear();
381:
382: }
383:
384: /**
385: * @param objects
386: */
387: private void removeActionSets(Object[] objects) {
388: for (int i = 0; i < objects.length; i++) {
389: Object object = objects[i];
390: if (object instanceof IActionSetDescriptor) {
391: IActionSetDescriptor desc = (IActionSetDescriptor) object;
392: removeActionSet(desc);
393:
394: // now clean up the part associations
395: // TODO: this is expensive. We should consider another map from
396: // actionsets
397: // to parts.
398: for (Iterator j = mapPartToActionSetIds.values()
399: .iterator(); j.hasNext();) {
400: ArrayList list = (ArrayList) j.next();
401: list.remove(desc.getId());
402: if (list.isEmpty()) {
403: j.remove();
404: }
405: }
406: }
407: }
408: // TODO: optimize
409: mapPartToActionSets.clear();
410: }
411: }
|