001: /*******************************************************************************
002: * Copyright (c) 2005, 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.commands;
011:
012: import java.util.ArrayList;
013: import java.util.Collection;
014: import java.util.Collections;
015: import java.util.HashMap;
016: import java.util.Iterator;
017: import java.util.List;
018: import java.util.Map;
019:
020: import org.eclipse.core.commands.Category;
021: import org.eclipse.core.commands.Command;
022: import org.eclipse.core.commands.CommandManager;
023: import org.eclipse.core.commands.IExecutionListener;
024: import org.eclipse.core.commands.IHandler;
025: import org.eclipse.core.commands.ParameterType;
026: import org.eclipse.core.commands.ParameterizedCommand;
027: import org.eclipse.core.commands.SerializationException;
028: import org.eclipse.core.commands.State;
029: import org.eclipse.core.commands.common.NotDefinedException;
030: import org.eclipse.core.runtime.ISafeRunnable;
031: import org.eclipse.core.runtime.SafeRunner;
032: import org.eclipse.jface.commands.PersistentState;
033: import org.eclipse.ui.commands.IElementReference;
034: import org.eclipse.ui.commands.IElementUpdater;
035: import org.eclipse.ui.commands.ICommandService;
036: import org.eclipse.ui.internal.WorkbenchPlugin;
037: import org.eclipse.ui.internal.util.PrefUtil;
038: import org.eclipse.ui.menus.UIElement;
039:
040: /**
041: * <p>
042: * Provides services related to the command architecture within the workbench.
043: * This service can be used to access the set of commands and handlers.
044: * </p>
045: *
046: * @since 3.1
047: */
048: public final class CommandService implements ICommandService {
049:
050: /**
051: * The preference key prefix for all handler state.
052: */
053: private static final String PREFERENCE_KEY_PREFIX = "org.eclipse.ui.commands/state"; //$NON-NLS-1$
054:
055: /**
056: * Creates a preference key for the given piece of state on the given
057: * command.
058: *
059: * @param command
060: * The command for which the preference key should be created;
061: * must not be <code>null</code>.
062: * @param stateId
063: * The identifier of the state for which the preference key
064: * should be created; must not be <code>null</code>.
065: * @return A suitable preference key; never <code>null</code>.
066: */
067: static final String createPreferenceKey(final Command command,
068: final String stateId) {
069: return PREFERENCE_KEY_PREFIX + '/' + command.getId() + '/'
070: + stateId;
071: }
072:
073: /**
074: * The command manager that supports this service. This value is never
075: * <code>null</code>.
076: */
077: private final CommandManager commandManager;
078:
079: /**
080: * The persistence class for this command service.
081: */
082: private final CommandPersistence commandPersistence;
083:
084: /**
085: * Constructs a new instance of <code>CommandService</code> using a
086: * command manager.
087: *
088: * @param commandManager
089: * The command manager to use; must not be <code>null</code>.
090: */
091: public CommandService(final CommandManager commandManager) {
092: if (commandManager == null) {
093: throw new NullPointerException(
094: "Cannot create a command service with a null manager"); //$NON-NLS-1$
095: }
096: this .commandManager = commandManager;
097: this .commandPersistence = new CommandPersistence(this );
098: }
099:
100: public final void addExecutionListener(
101: final IExecutionListener listener) {
102: commandManager.addExecutionListener(listener);
103: }
104:
105: public final void defineUncategorizedCategory(final String name,
106: final String description) {
107: commandManager.defineUncategorizedCategory(name, description);
108: }
109:
110: public final ParameterizedCommand deserialize(
111: final String serializedParameterizedCommand)
112: throws NotDefinedException, SerializationException {
113: return commandManager
114: .deserialize(serializedParameterizedCommand);
115: }
116:
117: public final void dispose() {
118: commandPersistence.dispose();
119:
120: /*
121: * All state on all commands neeeds to be disposed. This is so that the
122: * state has a chance to persist any changes.
123: */
124: final Command[] commands = commandManager.getAllCommands();
125: for (int i = 0; i < commands.length; i++) {
126: final Command command = commands[i];
127: final String[] stateIds = command.getStateIds();
128: for (int j = 0; j < stateIds.length; j++) {
129: final String stateId = stateIds[j];
130: final State state = command.getState(stateId);
131: if (state instanceof PersistentState) {
132: final PersistentState persistentState = (PersistentState) state;
133: if (persistentState.shouldPersist()) {
134: persistentState.save(PrefUtil
135: .getInternalPreferenceStore(),
136: createPreferenceKey(command, stateId));
137: }
138: }
139: }
140: }
141: commandCallbacks = null;
142: }
143:
144: public final Category getCategory(final String categoryId) {
145: return commandManager.getCategory(categoryId);
146: }
147:
148: public final Command getCommand(final String commandId) {
149: return commandManager.getCommand(commandId);
150: }
151:
152: public final Category[] getDefinedCategories() {
153: return commandManager.getDefinedCategories();
154: }
155:
156: public final Collection getDefinedCategoryIds() {
157: return commandManager.getDefinedCategoryIds();
158: }
159:
160: public final Collection getDefinedCommandIds() {
161: return commandManager.getDefinedCommandIds();
162: }
163:
164: public final Command[] getDefinedCommands() {
165: return commandManager.getDefinedCommands();
166: }
167:
168: public Collection getDefinedParameterTypeIds() {
169: return commandManager.getDefinedParameterTypeIds();
170: }
171:
172: public ParameterType[] getDefinedParameterTypes() {
173: return commandManager.getDefinedParameterTypes();
174: }
175:
176: public final String getHelpContextId(final Command command)
177: throws NotDefinedException {
178: return commandManager.getHelpContextId(command);
179: }
180:
181: public final String getHelpContextId(final String commandId)
182: throws NotDefinedException {
183: final Command command = getCommand(commandId);
184: return commandManager.getHelpContextId(command);
185: }
186:
187: public ParameterType getParameterType(final String parameterTypeId) {
188: return commandManager.getParameterType(parameterTypeId);
189: }
190:
191: public final void readRegistry() {
192: commandPersistence.read();
193: }
194:
195: public final void removeExecutionListener(
196: final IExecutionListener listener) {
197: commandManager.removeExecutionListener(listener);
198: }
199:
200: public final void setHelpContextId(final IHandler handler,
201: final String helpContextId) {
202: commandManager.setHelpContextId(handler, helpContextId);
203: }
204:
205: /**
206: * This is a map of commandIds to a list containing currently registered
207: * callbacks, in the form of ICallbackReferences.
208: */
209: private Map commandCallbacks = new HashMap();
210:
211: /*
212: * (non-Javadoc)
213: *
214: * @see org.eclipse.ui.commands.ICommandService#refreshElements(java.lang.String,
215: * java.util.Map)
216: */
217: public final void refreshElements(String commandId, Map filter) {
218: Command cmd = getCommand(commandId);
219:
220: if (!cmd.isDefined()
221: || !(cmd.getHandler() instanceof IElementUpdater)) {
222: return;
223: }
224: final IElementUpdater updater = (IElementUpdater) cmd
225: .getHandler();
226:
227: if (commandCallbacks == null) {
228: return;
229: }
230:
231: List callbackRefs = (List) commandCallbacks.get(commandId);
232: if (callbackRefs == null) {
233: return;
234: }
235:
236: for (Iterator i = callbackRefs.iterator(); i.hasNext();) {
237: final IElementReference callbackRef = (IElementReference) i
238: .next();
239: final Map parms = Collections.unmodifiableMap(callbackRef
240: .getParameters());
241: ISafeRunnable run = new ISafeRunnable() {
242: public void handleException(Throwable exception) {
243: WorkbenchPlugin.log("Failed to update callback: " //$NON-NLS-1$
244: + callbackRef.getCommandId(), exception);
245: }
246:
247: public void run() throws Exception {
248: updater.updateElement(callbackRef.getElement(),
249: parms);
250: }
251: };
252: if (filter == null) {
253: SafeRunner.run(run);
254: } else {
255: boolean match = true;
256: for (Iterator j = filter.entrySet().iterator(); j
257: .hasNext()
258: && match;) {
259: Map.Entry parmEntry = (Map.Entry) j.next();
260: Object value = parms.get(parmEntry.getKey());
261: if (!parmEntry.getValue().equals(value)) {
262: match = false;
263: }
264: }
265: if (match) {
266: SafeRunner.run(run);
267: }
268: }
269: }
270: }
271:
272: /*
273: * (non-Javadoc)
274: *
275: * @see org.eclipse.ui.commands.ICommandService#registerElementForCommand(org.eclipse.core.commands.ParameterizedCommand,
276: * org.eclipse.ui.menus.UIElement)
277: */
278: public final IElementReference registerElementForCommand(
279: ParameterizedCommand command, UIElement element)
280: throws NotDefinedException {
281: if (!command.getCommand().isDefined()) {
282: throw new NotDefinedException(
283: "Cannot define a callback for undefined command " //$NON-NLS-1$
284: + command.getCommand().getId());
285: }
286: if (element == null) {
287: throw new NotDefinedException(
288: "No callback defined for command " //$NON-NLS-1$
289: + command.getCommand().getId());
290: }
291:
292: ElementReference ref = new ElementReference(command.getId(),
293: element, command.getParameterMap());
294: registerElement(ref);
295: return ref;
296: }
297:
298: /*
299: * (non-Javadoc)
300: *
301: * @see org.eclipse.ui.commands.ICommandService#registerElement(org.eclipse.ui.commands.IElementReference)
302: */
303: public void registerElement(IElementReference elementReference) {
304: List parameterizedCommands = (List) commandCallbacks
305: .get(elementReference.getCommandId());
306: if (parameterizedCommands == null) {
307: parameterizedCommands = new ArrayList();
308: commandCallbacks.put(elementReference.getCommandId(),
309: parameterizedCommands);
310: }
311: parameterizedCommands.add(elementReference);
312:
313: // If the active handler wants to update the callback, it can do
314: // so now
315: Command command = getCommand(elementReference.getCommandId());
316: if (command.isDefined()) {
317: if (command.getHandler() instanceof IElementUpdater) {
318: ((IElementUpdater) command.getHandler()).updateElement(
319: elementReference.getElement(), elementReference
320: .getParameters());
321: }
322: }
323: }
324:
325: /*
326: * (non-Javadoc)
327: *
328: * @see org.eclipse.ui.commands.ICommandService#unregisterElement(org.eclipse.ui.commands.IElementReference)
329: */
330: public void unregisterElement(IElementReference elementReference) {
331: List parameterizedCommands = (List) commandCallbacks
332: .get(elementReference.getCommandId());
333: if (parameterizedCommands != null) {
334: parameterizedCommands.remove(elementReference);
335: if (parameterizedCommands.isEmpty()) {
336: commandCallbacks
337: .remove(elementReference.getCommandId());
338: }
339: }
340: }
341: }
|