KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > core > commands > CommandManager


1 /*******************************************************************************
2  * Copyright (c) 2004, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.core.commands;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Collections JavaDoc;
15 import java.util.HashMap JavaDoc;
16 import java.util.HashSet JavaDoc;
17 import java.util.Iterator JavaDoc;
18 import java.util.Map JavaDoc;
19 import java.util.Set JavaDoc;
20 import java.util.WeakHashMap JavaDoc;
21
22 import org.eclipse.core.commands.common.HandleObjectManager;
23 import org.eclipse.core.commands.common.NotDefinedException;
24 import org.eclipse.core.runtime.ListenerList;
25
26 /**
27  * <p>
28  * A central repository for commands -- both in the defined and undefined
29  * states. Commands can be created and retrieved using this manager. It is
30  * possible to listen to changes in the collection of commands by attaching a
31  * listener to the manager.
32  * </p>
33  *
34  * @see CommandManager#getCommand(String)
35  * @since 3.1
36  */

37 public final class CommandManager extends HandleObjectManager implements
38         ICategoryListener, ICommandListener, IParameterTypeListener {
39
40     /**
41      * A listener that forwards incoming execution events to execution listeners
42      * on this manager. The execution events will come from any command on this
43      * manager.
44      *
45      * @since 3.1
46      */

47     private final class ExecutionListener implements
48             IExecutionListenerWithChecks {
49
50         public void notDefined(String JavaDoc commandId, NotDefinedException exception) {
51             if (executionListeners != null) {
52                 final Object JavaDoc[] listeners = executionListeners.getListeners();
53                 for (int i = 0; i < listeners.length; i++) {
54                     final Object JavaDoc object = listeners[i];
55                     if (object instanceof IExecutionListenerWithChecks) {
56                         final IExecutionListenerWithChecks listener = (IExecutionListenerWithChecks) object;
57                         listener.notDefined(commandId, exception);
58                     }
59                 }
60             }
61         }
62
63         public void notEnabled(String JavaDoc commandId, NotEnabledException exception) {
64             if (executionListeners != null) {
65                 final Object JavaDoc[] listeners = executionListeners.getListeners();
66                 for (int i = 0; i < listeners.length; i++) {
67                     final Object JavaDoc object = listeners[i];
68                     if (object instanceof IExecutionListenerWithChecks) {
69                         final IExecutionListenerWithChecks listener = (IExecutionListenerWithChecks) object;
70                         listener.notEnabled(commandId, exception);
71                     }
72                 }
73             }
74         }
75
76         public final void notHandled(final String JavaDoc commandId,
77                 final NotHandledException exception) {
78             if (executionListeners != null) {
79                 final Object JavaDoc[] listeners = executionListeners.getListeners();
80                 for (int i = 0; i < listeners.length; i++) {
81                     final Object JavaDoc object = listeners[i];
82                     if (object instanceof IExecutionListener) {
83                         final IExecutionListener listener = (IExecutionListener) object;
84                         listener.notHandled(commandId, exception);
85                     }
86                 }
87             }
88         }
89
90         public final void postExecuteFailure(final String JavaDoc commandId,
91                 final ExecutionException exception) {
92             if (executionListeners != null) {
93                 final Object JavaDoc[] listeners = executionListeners.getListeners();
94                 for (int i = 0; i < listeners.length; i++) {
95                     final Object JavaDoc object = listeners[i];
96                     if (object instanceof IExecutionListener) {
97                         final IExecutionListener listener = (IExecutionListener) object;
98                         listener.postExecuteFailure(commandId, exception);
99                     }
100                 }
101             }
102         }
103
104         public final void postExecuteSuccess(final String JavaDoc commandId,
105                 final Object JavaDoc returnValue) {
106             if (executionListeners != null) {
107                 final Object JavaDoc[] listeners = executionListeners.getListeners();
108                 for (int i = 0; i < listeners.length; i++) {
109                     final Object JavaDoc object = listeners[i];
110                     if (object instanceof IExecutionListener) {
111                         final IExecutionListener listener = (IExecutionListener) object;
112                         listener.postExecuteSuccess(commandId, returnValue);
113                     }
114                 }
115             }
116         }
117
118         public final void preExecute(final String JavaDoc commandId,
119                 final ExecutionEvent event) {
120             if (executionListeners != null) {
121                 final Object JavaDoc[] listeners = executionListeners.getListeners();
122                 for (int i = 0; i < listeners.length; i++) {
123                     final Object JavaDoc object = listeners[i];
124                     if (object instanceof IExecutionListener) {
125                         final IExecutionListener listener = (IExecutionListener) object;
126                         listener.preExecute(commandId, event);
127                     }
128                 }
129             }
130         }
131     }
132
133     /**
134      * The identifier of the category in which all auto-generated commands will
135      * appear. This value must never be <code>null</code>.
136      *
137      * @since 3.2
138      */

139     public static final String JavaDoc AUTOGENERATED_CATEGORY_ID = "org.eclipse.core.commands.categories.autogenerated"; //$NON-NLS-1$
140

141     /**
142      * The escape character to use for serialization and deserialization of
143      * parameterized commands.
144      */

145     static final char ESCAPE_CHAR = '%';
146
147     /**
148      * The character that separates a parameter id from its value.
149      */

150     static final char ID_VALUE_CHAR = '=';
151
152     /**
153      * The character that indicates the end of a list of parameters.
154      */

155     static final char PARAMETER_END_CHAR = ')';
156
157     /**
158      * The character that separators parameters from each other.
159      */

160     static final char PARAMETER_SEPARATOR_CHAR = ',';
161
162     /**
163      * The character that indicates the start of a list of parameters.
164      */

165     static final char PARAMETER_START_CHAR = '(';
166
167     /**
168      * Unescapes special characters in the command id, parameter ids and
169      * parameter values for {@link #deserialize()}. The special characters
170      * {@link #PARAMETER_START_CHAR}, {@link #PARAMETER_END_CHAR},
171      * {@link #ID_VALUE_CHAR}, {@link #PARAMETER_SEPARATOR_CHAR} and
172      * {@link #ESCAPE_CHAR} are escaped by prepending an {@link #ESCAPE_CHAR}
173      * character.
174      *
175      * @param escapedText
176      * a <code>String</code> that may contain escaped special
177      * characters for command serialization.
178      * @return a <code>String</code> representing <code>escapedText</code>
179      * with any escaped characters replaced by their literal values
180      * @throws SerializationException
181      * if <code>escapedText</code> contains an invalid escape
182      * sequence
183      * @see ParameterizedCommand#escape(String)
184      * @since 3.2
185      */

186     private static final String JavaDoc unescape(final String JavaDoc escapedText)
187             throws SerializationException {
188
189         // defer initialization of a StringBuffer until we know we need one
190
StringBuffer JavaDoc buffer = null;
191
192         for (int i = 0; i < escapedText.length(); i++) {
193
194             char c = escapedText.charAt(i);
195             if (c != ESCAPE_CHAR) {
196                 // normal unescaped character
197
if (buffer != null) {
198                     buffer.append(c);
199                 }
200             } else {
201                 if (buffer == null) {
202                     buffer = new StringBuffer JavaDoc(escapedText.substring(0, i));
203                 }
204
205                 if (++i < escapedText.length()) {
206                     c = escapedText.charAt(i);
207                     switch (c) {
208                     case PARAMETER_START_CHAR:
209                     case PARAMETER_END_CHAR:
210                     case ID_VALUE_CHAR:
211                     case PARAMETER_SEPARATOR_CHAR:
212                     case ESCAPE_CHAR:
213                         buffer.append(c);
214                         break;
215                     default:
216                         throw new SerializationException(
217                                 "Invalid character '" + c + "' in escape sequence"); //$NON-NLS-1$ //$NON-NLS-2$
218
}
219                 } else {
220                     throw new SerializationException(
221                             "Unexpected termination of escape sequence"); //$NON-NLS-1$
222
}
223             }
224
225         }
226
227         if (buffer == null) {
228             return escapedText;
229         }
230
231         return buffer.toString();
232     }
233
234     /**
235      * The map of category identifiers (<code>String</code>) to categories (
236      * <code>Category</code>). This collection may be empty, but it is never
237      * <code>null</code>.
238      */

239     private final Map JavaDoc categoriesById = new HashMap JavaDoc();
240
241     /**
242      * The set of identifiers for those categories that are defined. This value
243      * may be empty, but it is never <code>null</code>.
244      */

245     private final Set JavaDoc definedCategoryIds = new HashSet JavaDoc();
246
247     /**
248      * The set of identifiers for those command parameter types that are
249      * defined. This value may be empty, but it is never <code>null</code>.
250      *
251      * @since 3.2
252      */

253     private final Set JavaDoc definedParameterTypeIds = new HashSet JavaDoc();
254
255     /**
256      * The execution listener for this command manager. This just forwards
257      * events from commands controlled by this manager to listeners on this
258      * manager.
259      */

260     private IExecutionListener executionListener = null;
261
262     /**
263      * The collection of execution listeners. This collection is
264      * <code>null</code> if there are no listeners.
265      */

266     private ListenerList executionListeners = null;
267
268     /**
269      * The help context identifiers ({@link String}) for a handler ({@link IHandler}).
270      * This map may be empty, but it is never <code>null</code>. Entries are
271      * removed if all strong references to the handler are removed.
272      *
273      * @since 3.2
274      */

275     private final Map JavaDoc helpContextIdsByHandler = new WeakHashMap JavaDoc();
276
277     /**
278      * The map of parameter type identifiers (<code>String</code>) to
279      * parameter types ( <code>ParameterType</code>). This collection may be
280      * empty, but it is never <code>null</code>.
281      *
282      * @since 3.2
283      */

284     private final Map JavaDoc parameterTypesById = new HashMap JavaDoc();
285
286     /**
287      * Adds a listener to this command manager. The listener will be notified
288      * when the set of defined commands changes. This can be used to track the
289      * global appearance and disappearance of commands.
290      *
291      * @param listener
292      * The listener to attach; must not be <code>null</code>.
293      */

294     public final void addCommandManagerListener(
295             final ICommandManagerListener listener) {
296         addListenerObject(listener);
297     }
298
299     /**
300      * Adds an execution listener to this manager. This listener will be
301      * notified if any of the commands controlled by this manager execute. This
302      * can be used to support macros and instrumentation of commands.
303      *
304      * @param listener
305      * The listener to attach; must not be <code>null</code>.
306      */

307     public final void addExecutionListener(final IExecutionListener listener) {
308         if (listener == null) {
309             throw new NullPointerException JavaDoc(
310                     "Cannot add a null execution listener"); //$NON-NLS-1$
311
}
312
313         if (executionListeners == null) {
314             executionListeners = new ListenerList(ListenerList.IDENTITY);
315
316             // Add an execution listener to every command.
317
executionListener = new ExecutionListener();
318             final Iterator JavaDoc commandItr = handleObjectsById.values().iterator();
319             while (commandItr.hasNext()) {
320                 final Command command = (Command) commandItr.next();
321                 command.addExecutionListener(executionListener);
322             }
323
324         }
325
326         executionListeners.add(listener);
327     }
328
329     /*
330      * (non-Javadoc)
331      *
332      * @see org.eclipse.core.commands.ICategoryListener#categoryChanged(org.eclipse.core.commands.CategoryEvent)
333      */

334     public final void categoryChanged(CategoryEvent categoryEvent) {
335         if (categoryEvent.isDefinedChanged()) {
336             final Category category = categoryEvent.getCategory();
337             final String JavaDoc categoryId = category.getId();
338             final boolean categoryIdAdded = category.isDefined();
339             if (categoryIdAdded) {
340                 definedCategoryIds.add(categoryId);
341             } else {
342                 definedCategoryIds.remove(categoryId);
343             }
344             if (isListenerAttached()) {
345                 fireCommandManagerChanged(new CommandManagerEvent(this, null,
346                         false, false, categoryId, categoryIdAdded, true));
347             }
348         }
349     }
350
351     /*
352      * (non-Javadoc)
353      *
354      * @see org.eclipse.commands.ICommandListener#commandChanged(org.eclipse.commands.CommandEvent)
355      */

356     public final void commandChanged(final CommandEvent commandEvent) {
357         if (commandEvent.isDefinedChanged()) {
358             final Command command = commandEvent.getCommand();
359             final String JavaDoc commandId = command.getId();
360             final boolean commandIdAdded = command.isDefined();
361             if (commandIdAdded) {
362                 definedHandleObjects.add(command);
363             } else {
364                 definedHandleObjects.remove(command);
365             }
366             if (isListenerAttached()) {
367                 fireCommandManagerChanged(new CommandManagerEvent(this,
368                         commandId, commandIdAdded, true, null, false, false));
369             }
370         }
371     }
372
373     /**
374      * Sets the name and description of the category for uncategorized commands.
375      * This is the category that will be returned if
376      * {@link #getCategory(String)} is called with <code>null</code>.
377      *
378      * @param name
379      * The name of the category for uncategorized commands; must not
380      * be <code>null</code>.
381      * @param description
382      * The description of the category for uncategorized commands;
383      * may be <code>null</code>.
384      * @since 3.2
385      */

386     public final void defineUncategorizedCategory(final String JavaDoc name,
387             final String JavaDoc description) {
388         final Category category = getCategory(AUTOGENERATED_CATEGORY_ID);
389         category.define(name, description);
390     }
391
392     /**
393      * <p>
394      * Returns a {@link ParameterizedCommand} with a command and
395      * parameterizations as specified in the provided
396      * <code>serializedParameterizedCommand</code> string. The
397      * <code>serializedParameterizedCommand</code> must use the format
398      * returned by {@link ParameterizedCommand#serialize()} and described in the
399      * Javadoc for that method.
400      * </p>
401      * <p>
402      * If a parameter id encoded in the
403      * <code>serializedParameterizedCommand</code> does not exist in the
404      * encoded command, that parameter id and value are ignored. A given
405      * parameter id should not be used more than once in
406      * <code>serializedParameterizedCommand</code>. This will not result in
407      * an exception, but in this case the value of the parameter when the
408      * command is executed is unspecified.
409      * </p>
410      * <p>
411      * This method will never return <code>null</code>, however it may throw
412      * an exception if there is a problem processing the serialization string or
413      * the encoded command is undefined.
414      * </p>
415      *
416      * @param serializedParameterizedCommand
417      * a string representing a command id and parameter ids and
418      * values; must not be <code>null</code>
419      * @return a {@link ParameterizedCommand} with the command and
420      * parameterizations encoded in the
421      * <code>serializedParameterizedCommand</code>; never
422      * <code>null</code>.
423      * @throws NotDefinedException
424      * if the command indicated in
425      * <code>serializedParameterizedCommand</code> is not defined
426      * @throws SerializationException
427      * if there is an error deserializing
428      * <code>serializedParameterizedCommand</code>
429      * @see ParameterizedCommand#serialize()
430      * @since 3.2
431      */

432     public final ParameterizedCommand deserialize(
433             final String JavaDoc serializedParameterizedCommand)
434             throws NotDefinedException, SerializationException {
435
436         final int lparenPosition = unescapedIndexOf(
437                 serializedParameterizedCommand, PARAMETER_START_CHAR);
438
439         final String JavaDoc commandIdEscaped;
440         final String JavaDoc serializedParameters;
441         if (lparenPosition == -1) {
442             commandIdEscaped = serializedParameterizedCommand;
443             serializedParameters = null;
444         } else {
445             commandIdEscaped = serializedParameterizedCommand.substring(0,
446                     lparenPosition);
447
448             if (serializedParameterizedCommand
449                     .charAt(serializedParameterizedCommand.length() - 1) != PARAMETER_END_CHAR) {
450                 throw new SerializationException(
451                         "Parentheses must be balanced in serialized ParameterizedCommand"); //$NON-NLS-1$
452
}
453
454             serializedParameters = serializedParameterizedCommand.substring(
455                     lparenPosition + 1, // skip PARAMETER_START_CHAR
456
serializedParameterizedCommand.length() - 1); // skip
457
// PARAMETER_END_CHAR
458
}
459
460         final String JavaDoc commandId = unescape(commandIdEscaped);
461         final Command command = getCommand(commandId);
462         final IParameter[] parameters = command.getParameters();
463         final Parameterization[] parameterizations = getParameterizations(
464                 serializedParameters, parameters);
465
466         return new ParameterizedCommand(command, parameterizations);
467     }
468
469     /**
470      * Notifies all of the listeners to this manager that the set of defined
471      * command identifiers has changed.
472      *
473      * @param event
474      * The event to send to all of the listeners; must not be
475      * <code>null</code>.
476      */

477     private final void fireCommandManagerChanged(final CommandManagerEvent event) {
478         if (event == null) {
479             throw new NullPointerException JavaDoc();
480         }
481
482         final Object JavaDoc[] listeners = getListeners();
483         for (int i = 0; i < listeners.length; i++) {
484             final ICommandManagerListener listener = (ICommandManagerListener) listeners[i];
485             listener.commandManagerChanged(event);
486         }
487     }
488
489     /**
490      * Returns all of the commands known by this manager -- defined and
491      * undefined.
492      *
493      * @return All of the commands; may be empty, but never <code>null</code>.
494      * @since 3.2
495      */

496     public final Command[] getAllCommands() {
497         return (Command[]) handleObjectsById.values().toArray(
498                 new Command[handleObjectsById.size()]);
499     }
500
501     /**
502      * Gets the category with the given identifier. If no such category
503      * currently exists, then the category will be created (but be undefined).
504      *
505      * @param categoryId
506      * The identifier to find; must not be <code>null</code>. If
507      * the category is <code>null</code>, then a category suitable
508      * for uncategorized items is defined and returned.
509      * @return The category with the given identifier; this value will never be
510      * <code>null</code>, but it might be undefined.
511      * @see Category
512      */

513     public final Category getCategory(final String JavaDoc categoryId) {
514         if (categoryId == null) {
515             return getCategory(AUTOGENERATED_CATEGORY_ID);
516         }
517
518         checkId(categoryId);
519
520         Category category = (Category) categoriesById.get(categoryId);
521         if (category == null) {
522             category = new Category(categoryId);
523             categoriesById.put(categoryId, category);
524             category.addCategoryListener(this);
525         }
526
527         return category;
528     }
529
530     /**
531      * Gets the command with the given identifier. If no such command currently
532      * exists, then the command will be created (but will be undefined).
533      *
534      * @param commandId
535      * The identifier to find; must not be <code>null</code> and
536      * must not be zero-length.
537      * @return The command with the given identifier; this value will never be
538      * <code>null</code>, but it might be undefined.
539      * @see Command
540      */

541     public final Command getCommand(final String JavaDoc commandId) {
542         checkId(commandId);
543
544         Command command = (Command) handleObjectsById.get(commandId);
545         if (command == null) {
546             command = new Command(commandId);
547             handleObjectsById.put(commandId, command);
548             command.addCommandListener(this);
549
550             if (executionListener != null) {
551                 command.addExecutionListener(executionListener);
552             }
553         }
554
555         return command;
556     }
557
558     /**
559      * Returns the categories that are defined.
560      *
561      * @return The defined categories; this value may be empty, but it is never
562      * <code>null</code>.
563      * @since 3.2
564      */

565     public final Category[] getDefinedCategories() {
566         final Category[] categories = new Category[definedCategoryIds.size()];
567         final Iterator JavaDoc categoryIdItr = definedCategoryIds.iterator();
568         int i = 0;
569         while (categoryIdItr.hasNext()) {
570             String JavaDoc categoryId = (String JavaDoc) categoryIdItr.next();
571             categories[i++] = getCategory(categoryId);
572         }
573         return categories;
574     }
575
576     /**
577      * Returns the set of identifiers for those category that are defined.
578      *
579      * @return The set of defined category identifiers; this value may be empty,
580      * but it is never <code>null</code>.
581      */

582     public final Set JavaDoc getDefinedCategoryIds() {
583         return Collections.unmodifiableSet(definedCategoryIds);
584     }
585
586     /**
587      * Returns the set of identifiers for those commands that are defined.
588      *
589      * @return The set of defined command identifiers; this value may be empty,
590      * but it is never <code>null</code>.
591      */

592     public final Set JavaDoc getDefinedCommandIds() {
593         return getDefinedHandleObjectIds();
594     }
595
596     /**
597      * Returns the commands that are defined.
598      *
599      * @return The defined commands; this value may be empty, but it is never
600      * <code>null</code>.
601      * @since 3.2
602      */

603     public final Command[] getDefinedCommands() {
604         return (Command[]) definedHandleObjects
605                 .toArray(new Command[definedHandleObjects.size()]);
606     }
607
608     /**
609      * Returns the set of identifiers for those parameter types that are
610      * defined.
611      *
612      * @return The set of defined command parameter type identifiers; this value
613      * may be empty, but it is never <code>null</code>.
614      * @since 3.2
615      */

616     public final Set JavaDoc getDefinedParameterTypeIds() {
617         return Collections.unmodifiableSet(definedParameterTypeIds);
618     }
619
620     /**
621      * Returns the command parameter types that are defined.
622      *
623      * @return The defined command parameter types; this value may be empty, but
624      * it is never <code>null</code>.
625      * @since 3.2
626      */

627     public final ParameterType[] getDefinedParameterTypes() {
628         final ParameterType[] parameterTypes = new ParameterType[definedParameterTypeIds
629                 .size()];
630         final Iterator JavaDoc iterator = definedParameterTypeIds.iterator();
631         int i = 0;
632         while (iterator.hasNext()) {
633             final String JavaDoc parameterTypeId = (String JavaDoc) iterator.next();
634             parameterTypes[i++] = getParameterType(parameterTypeId);
635         }
636         return parameterTypes;
637     }
638
639     /**
640      * Gets the help context identifier for a particular command. The command's
641      * handler is first checked for a help context identifier. If the handler
642      * does not have a help context identifier, then the help context identifier
643      * for the command is returned. If neither has a help context identifier,
644      * then <code>null</code> is returned.
645      *
646      * @param command
647      * The command for which the help context should be retrieved;
648      * must not be <code>null</code>.
649      * @return The help context identifier to use for the given command; may be
650      * <code>null</code>.
651      * @throws NotDefinedException
652      * If the given command is not defined.
653      * @since 3.2
654      */

655     public final String JavaDoc getHelpContextId(final Command command)
656             throws NotDefinedException {
657         // Check if the command is defined.
658
if (!command.isDefined()) {
659             throw new NotDefinedException("The command is not defined. " //$NON-NLS-1$
660
+ command.getId());
661         }
662
663         // Check the handler.
664
final IHandler handler = command.getHandler();
665         if (handler != null) {
666             final String JavaDoc helpContextId = (String JavaDoc) helpContextIdsByHandler
667                     .get(handler);
668             if (helpContextId != null) {
669                 return helpContextId;
670             }
671         }
672
673         // Simply return whatever the command has as a help context identifier.
674
return command.getHelpContextId();
675     }
676
677     /**
678      * Returns an array of parameterizations for the provided command by
679      * deriving the parameter ids and values from the provided
680      * <code>serializedParameters</code> string.
681      *
682      * @param serializedParameters
683      * a String encoding parameter ids and values; must not be
684      * <code>null</code>.
685      * @param parameters
686      * array of parameters of the command being deserialized; may be
687      * <code>null</code>.
688      * @return an array of parameterizations; may be <code>null</code>.
689      * @throws NotDefinedException
690      * if the command is not defined
691      * @throws SerializationException
692      * if there is an error deserializing the parameters
693      * @since 3.2
694      */

695     private final Parameterization[] getParameterizations(
696             String JavaDoc serializedParameters, final IParameter[] parameters)
697             throws SerializationException {
698
699         if (serializedParameters == null
700                 || (serializedParameters.length() == 0)) {
701             return null;
702         }
703
704         if ((parameters == null) || (parameters.length == 0)) {
705             return null;
706         }
707
708         final ArrayList JavaDoc paramList = new ArrayList JavaDoc();
709
710         int commaPosition; // split off each param by looking for ','
711
do {
712             commaPosition = unescapedIndexOf(serializedParameters, ',');
713
714             final String JavaDoc idEqualsValue;
715             if (commaPosition == -1) {
716                 // no more parameters after this
717
idEqualsValue = serializedParameters;
718             } else {
719                 // take the first parameter...
720
idEqualsValue = serializedParameters
721                         .substring(0, commaPosition);
722
723                 // ... and put the rest back into serializedParameters
724
serializedParameters = serializedParameters
725                         .substring(commaPosition + 1);
726             }
727
728             final int equalsPosition = unescapedIndexOf(idEqualsValue, '=');
729
730             final String JavaDoc parameterId;
731             final String JavaDoc parameterValue;
732             if (equalsPosition == -1) {
733                 // missing values are null
734
parameterId = unescape(idEqualsValue);
735                 parameterValue = null;
736             } else {
737                 parameterId = unescape(idEqualsValue.substring(0,
738                         equalsPosition));
739                 parameterValue = unescape(idEqualsValue
740                         .substring(equalsPosition + 1));
741             }
742
743             for (int i = 0; i < parameters.length; i++) {
744                 final IParameter parameter = parameters[i];
745                 if (parameter.getId().equals(parameterId)) {
746                     paramList.add(new Parameterization(parameter,
747                             parameterValue));
748                     break;
749                 }
750             }
751
752         } while (commaPosition != -1);
753
754         return (Parameterization[]) paramList
755                 .toArray(new Parameterization[paramList.size()]);
756     }
757
758     /**
759      * Gets the command {@link ParameterType} with the given identifier. If no
760      * such command parameter type currently exists, then the command parameter
761      * type will be created (but will be undefined).
762      *
763      * @param parameterTypeId
764      * The identifier to find; must not be <code>null</code> and
765      * must not be zero-length.
766      * @return The {@link ParameterType} with the given identifier; this value
767      * will never be <code>null</code>, but it might be undefined.
768      * @since 3.2
769      */

770     public final ParameterType getParameterType(final String JavaDoc parameterTypeId) {
771         checkId(parameterTypeId);
772
773         ParameterType parameterType = (ParameterType) parameterTypesById
774                 .get(parameterTypeId);
775         if (parameterType == null) {
776             parameterType = new ParameterType(parameterTypeId);
777             parameterTypesById.put(parameterTypeId, parameterType);
778             parameterType.addListener(this);
779         }
780
781         return parameterType;
782     }
783
784     /**
785      * {@inheritDoc}
786      *
787      * @since 3.2
788      */

789     public final void parameterTypeChanged(
790             final ParameterTypeEvent parameterTypeEvent) {
791         if (parameterTypeEvent.isDefinedChanged()) {
792             final ParameterType parameterType = parameterTypeEvent
793                     .getParameterType();
794             final String JavaDoc parameterTypeId = parameterType.getId();
795             final boolean parameterTypeIdAdded = parameterType.isDefined();
796             if (parameterTypeIdAdded) {
797                 definedParameterTypeIds.add(parameterTypeId);
798             } else {
799                 definedParameterTypeIds.remove(parameterTypeId);
800             }
801
802             fireCommandManagerChanged(new CommandManagerEvent(this,
803                     parameterTypeId, parameterTypeIdAdded, true));
804         }
805     }
806
807     /**
808      * Removes a listener from this command manager.
809      *
810      * @param listener
811      * The listener to be removed; must not be <code>null</code>.
812      */

813     public final void removeCommandManagerListener(
814             final ICommandManagerListener listener) {
815         removeListenerObject(listener);
816     }
817
818     /**
819      * Removes an execution listener from this command manager.
820      *
821      * @param listener
822      * The listener to be removed; must not be <code>null</code>.
823      */

824     public final void removeExecutionListener(final IExecutionListener listener) {
825         if (listener == null) {
826             throw new NullPointerException JavaDoc("Cannot remove a null listener"); //$NON-NLS-1$
827
}
828
829         if (executionListeners == null) {
830             return;
831         }
832
833         executionListeners.remove(listener);
834
835         if (executionListeners.isEmpty()) {
836             executionListeners = null;
837
838             // Remove the execution listener to every command.
839
final Iterator JavaDoc commandItr = handleObjectsById.values().iterator();
840             while (commandItr.hasNext()) {
841                 final Command command = (Command) commandItr.next();
842                 command.removeExecutionListener(executionListener);
843             }
844             executionListener = null;
845
846         }
847     }
848
849     /**
850      * Block updates all of the handlers for all of the commands. If the handler
851      * is <code>null</code> or the command id does not exist in the map, then
852      * the command becomes unhandled. Otherwise, the handler is set to the
853      * corresponding value in the map.
854      *
855      * @param handlersByCommandId
856      * A map of command identifiers (<code>String</code>) to
857      * handlers (<code>IHandler</code>). This map may be
858      * <code>null</code> if all handlers should be cleared.
859      * Similarly, if the map is empty, then all commands will become
860      * unhandled.
861      */

862     public final void setHandlersByCommandId(final Map JavaDoc handlersByCommandId) {
863         // Make that all the reference commands are created.
864
final Iterator JavaDoc commandIdItr = handlersByCommandId.keySet().iterator();
865         while (commandIdItr.hasNext()) {
866             getCommand((String JavaDoc) commandIdItr.next());
867         }
868
869         // Now, set-up the handlers on all of the existing commands.
870
final Iterator JavaDoc commandItr = handleObjectsById.values().iterator();
871         while (commandItr.hasNext()) {
872             final Command command = (Command) commandItr.next();
873             final String JavaDoc commandId = command.getId();
874             final Object JavaDoc value = handlersByCommandId.get(commandId);
875             if (value instanceof IHandler) {
876                 command.setHandler((IHandler) value);
877             } else {
878                 command.setHandler(null);
879             }
880         }
881     }
882
883     /**
884      * Sets the help context identifier to associate with a particular handler.
885      *
886      * @param handler
887      * The handler with which to register a help context identifier;
888      * must not be <code>null</code>.
889      * @param helpContextId
890      * The help context identifier to register; may be
891      * <code>null</code> if the help context identifier should be
892      * removed.
893      * @since 3.2
894      */

895     public final void setHelpContextId(final IHandler handler,
896             final String JavaDoc helpContextId) {
897         if (handler == null) {
898             throw new NullPointerException JavaDoc("The handler cannot be null"); //$NON-NLS-1$
899
}
900         if (helpContextId == null) {
901             helpContextIdsByHandler.remove(handler);
902         } else {
903             helpContextIdsByHandler.put(handler, helpContextId);
904         }
905     }
906
907     /**
908      * Searches for the index of a <code>char</code> in a <code>String</code>
909      * but disregards characters prefixed with the {@link #ESCAPE_CHAR} escape
910      * character. This is used by {@link #deserialize(String)} and
911      * {@link #getParameterizations(String, IParameter[])} to parse the
912      * serialized parameterized command string.
913      *
914      * @param escapedText
915      * the string to search for the index of <code>ch</code> in
916      * @param ch
917      * a character to search for in <code>escapedText</code>
918      * @return the index of the first unescaped occurrence of the character in
919      * <code>escapedText</code>, or <code>-1</code> if the
920      * character does not occur unescaped.
921      * @see String#indexOf(int)
922      */

923     private final int unescapedIndexOf(final String JavaDoc escapedText, final char ch) {
924
925         int pos = escapedText.indexOf(ch);
926
927         // first char can't be escaped
928
if (pos == 0) {
929             return pos;
930         }
931
932         while (pos != -1) {
933             // look back for the escape character
934
if (escapedText.charAt(pos - 1) != ESCAPE_CHAR) {
935                 return pos;
936             }
937
938             // scan for the next instance of ch
939
pos = escapedText.indexOf(ch, pos + 1);
940         }
941
942         return pos;
943
944     }
945
946 }
947
Popular Tags