KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*******************************************************************************
2  * Copyright (c) 2004, 2007 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.io.BufferedWriter JavaDoc;
14 import java.io.IOException JavaDoc;
15 import java.io.StringWriter JavaDoc;
16
17 import org.eclipse.core.commands.common.NotDefinedException;
18 import org.eclipse.core.commands.util.Tracing;
19 import org.eclipse.core.internal.commands.util.Util;
20 import org.eclipse.core.runtime.ISafeRunnable;
21 import org.eclipse.core.runtime.ListenerList;
22 import org.eclipse.core.runtime.SafeRunner;
23
24 /**
25  * <p>
26  * A command is an abstract representation for some semantic behaviour. It is
27  * not the actual implementation of this behaviour, nor is it the visual
28  * appearance of this behaviour in the user interface. Instead, it is a bridge
29  * between the two.
30  * </p>
31  * <p>
32  * The concept of a command is based on the command design pattern. The notable
33  * difference is how the command delegates responsibility for execution. Rather
34  * than allowing concrete subclasses, it uses a handler mechanism (see the
35  * <code>handlers</code> extension point). This provides another level of
36  * indirection.
37  * </p>
38  * <p>
39  * A command will exist in two states: defined and undefined. A command is
40  * defined if it is declared in the XML of a resolved plug-in. If the plug-in is
41  * unloaded or the command is simply not declared, then it is undefined. Trying
42  * to reference an undefined command will succeed, but trying to access any of
43  * its functionality will fail with a <code>NotDefinedException</code>. If
44  * you need to know when a command changes from defined to undefined (or vice
45  * versa), then attach a command listener.
46  * </p>
47  * <p>
48  * Commands are mutable and will change as their definition changes.
49  * </p>
50  *
51  * @since 3.1
52  */

53 public final class Command extends NamedHandleObjectWithState implements
54         Comparable JavaDoc {
55
56     /**
57      * This flag can be set to <code>true</code> if commands should print
58      * information to <code>System.out</code> when executing.
59      */

60     public static boolean DEBUG_COMMAND_EXECUTION = false;
61
62     /**
63      * This flag can be set to <code>true</code> if commands should print
64      * information to <code>System.out</code> when changing handlers.
65      */

66     public static boolean DEBUG_HANDLERS = false;
67
68     /**
69      * This flag can be set to a particular command identifier if only that
70      * command should print information to <code>System.out</code> when
71      * changing handlers.
72      */

73     public static String JavaDoc DEBUG_HANDLERS_COMMAND_ID = null;
74
75     /**
76      * The category to which this command belongs. This value should not be
77      * <code>null</code> unless the command is undefined.
78      */

79     private Category category = null;
80
81     /**
82      * A collection of objects listening to the execution of this command. This
83      * collection is <code>null</code> if there are no listeners.
84      */

85     private transient ListenerList executionListeners = null;
86
87     /**
88      * The handler currently associated with this command. This value may be
89      * <code>null</code> if there is no handler currently.
90      */

91     private transient IHandler handler = null;
92
93     /**
94      * The help context identifier for this command. This can be
95      * <code>null</code> if there is no help currently associated with the
96      * command.
97      *
98      * @since 3.2
99      */

100     private String JavaDoc helpContextId;
101
102     /**
103      * The ordered array of parameters understood by this command. This value
104      * may be <code>null</code> if there are no parameters, or if the command
105      * is undefined. It may also be empty.
106      */

107     private IParameter[] parameters = null;
108
109     /**
110      * The type of the return value of this command. This value may be
111      * <code>null</code> if the command does not declare a return type.
112      *
113      * @since 3.2
114      */

115     private ParameterType returnType = null;
116
117     /**
118      * Our command will listen to the active handler for enablement changes so
119      * that they can be fired from the command itself.
120      *
121      * @since 3.3
122      */

123     private IHandlerListener handlerListener;
124
125     /**
126      * Constructs a new instance of <code>Command</code> based on the given
127      * identifier. When a command is first constructed, it is undefined.
128      * Commands should only be constructed by the <code>CommandManager</code>
129      * to ensure that the identifier remains unique.
130      *
131      * @param id
132      * The identifier for the command. This value must not be
133      * <code>null</code>, and must be unique amongst all commands.
134      */

135     Command(final String JavaDoc id) {
136         super(id);
137     }
138
139     /**
140      * Adds a listener to this command that will be notified when this command's
141      * state changes.
142      *
143      * @param commandListener
144      * The listener to be added; must not be <code>null</code>.
145      */

146     public final void addCommandListener(final ICommandListener commandListener) {
147         if (commandListener == null) {
148             throw new NullPointerException JavaDoc("Cannot add a null command listener"); //$NON-NLS-1$
149
}
150         addListenerObject(commandListener);
151     }
152
153     /**
154      * Adds a listener to this command that will be notified when this command
155      * is about to execute.
156      *
157      * @param executionListener
158      * The listener to be added; must not be <code>null</code>.
159      */

160     public final void addExecutionListener(
161             final IExecutionListener executionListener) {
162         if (executionListener == null) {
163             throw new NullPointerException JavaDoc(
164                     "Cannot add a null execution listener"); //$NON-NLS-1$
165
}
166
167         if (executionListeners == null) {
168             executionListeners = new ListenerList(ListenerList.IDENTITY);
169         }
170
171         executionListeners.add(executionListener);
172     }
173
174     /**
175      * <p>
176      * Adds a state to this command. This will add this state to the active
177      * handler, if the active handler is an instance of {@link IObjectWithState}.
178      * </p>
179      * <p>
180      * A single instance of {@link State} cannot be registered with multiple
181      * commands. Each command requires its own unique instance.
182      * </p>
183      *
184      * @param id
185      * The identifier of the state to add; must not be
186      * <code>null</code>.
187      * @param state
188      * The state to add; must not be <code>null</code>.
189      * @since 3.2
190      */

191     public void addState(final String JavaDoc id, final State state) {
192         super.addState(id, state);
193         state.setId(id);
194         if (handler instanceof IObjectWithState) {
195             ((IObjectWithState) handler).addState(id, state);
196         }
197     }
198
199     /**
200      * Compares this command with another command by comparing each of its
201      * non-transient attributes.
202      *
203      * @param object
204      * The object with which to compare; must be an instance of
205      * <code>Command</code>.
206      * @return A negative integer, zero or a postivie integer, if the object is
207      * greater than, equal to or less than this command.
208      */

209     public final int compareTo(final Object JavaDoc object) {
210         final Command castedObject = (Command) object;
211         int compareTo = Util.compare(category, castedObject.category);
212         if (compareTo == 0) {
213             compareTo = Util.compare(defined, castedObject.defined);
214             if (compareTo == 0) {
215                 compareTo = Util.compare(description, castedObject.description);
216                 if (compareTo == 0) {
217                     compareTo = Util.compare(handler, castedObject.handler);
218                     if (compareTo == 0) {
219                         compareTo = Util.compare(id, castedObject.id);
220                         if (compareTo == 0) {
221                             compareTo = Util.compare(name, castedObject.name);
222                             if (compareTo == 0) {
223                                 compareTo = Util.compare(parameters,
224                                         castedObject.parameters);
225                             }
226                         }
227                     }
228                 }
229             }
230         }
231         return compareTo;
232     }
233
234     /**
235      * <p>
236      * Defines this command by giving it a name, and possibly a description as
237      * well. The defined property automatically becomes <code>true</code>.
238      * </p>
239      * <p>
240      * Notification is sent to all listeners that something has changed.
241      * </p>
242      *
243      * @param name
244      * The name of this command; must not be <code>null</code>.
245      * @param description
246      * The description for this command; may be <code>null</code>.
247      * @param category
248      * The category for this command; must not be <code>null</code>.
249      * @since 3.2
250      */

251     public final void define(final String JavaDoc name, final String JavaDoc description,
252             final Category category) {
253         define(name, description, category, null);
254     }
255
256     /**
257      * <p>
258      * Defines this command by giving it a name, and possibly a description as
259      * well. The defined property automatically becomes <code>true</code>.
260      * </p>
261      * <p>
262      * Notification is sent to all listeners that something has changed.
263      * </p>
264      *
265      * @param name
266      * The name of this command; must not be <code>null</code>.
267      * @param description
268      * The description for this command; may be <code>null</code>.
269      * @param category
270      * The category for this command; must not be <code>null</code>.
271      * @param parameters
272      * The parameters understood by this command. This value may be
273      * either <code>null</code> or empty if the command does not
274      * accept parameters.
275      */

276     public final void define(final String JavaDoc name, final String JavaDoc description,
277             final Category category, final IParameter[] parameters) {
278         define(name, description, category, parameters, null);
279     }
280
281     /**
282      * <p>
283      * Defines this command by giving it a name, and possibly a description as
284      * well. The defined property automatically becomes <code>true</code>.
285      * </p>
286      * <p>
287      * Notification is sent to all listeners that something has changed.
288      * </p>
289      *
290      * @param name
291      * The name of this command; must not be <code>null</code>.
292      * @param description
293      * The description for this command; may be <code>null</code>.
294      * @param category
295      * The category for this command; must not be <code>null</code>.
296      * @param parameters
297      * The parameters understood by this command. This value may be
298      * either <code>null</code> or empty if the command does not
299      * accept parameters.
300      * @param returnType
301      * The type of value returned by this command. This value may be
302      * <code>null</code> if the command does not declare a return
303      * type.
304      * @since 3.2
305      */

306     public final void define(final String JavaDoc name, final String JavaDoc description,
307             final Category category, final IParameter[] parameters,
308             ParameterType returnType) {
309         define(name, description, category, parameters, returnType, null);
310     }
311
312     /**
313      * <p>
314      * Defines this command by giving it a name, and possibly a description as
315      * well. The defined property automatically becomes <code>true</code>.
316      * </p>
317      * <p>
318      * Notification is sent to all listeners that something has changed.
319      * </p>
320      *
321      * @param name
322      * The name of this command; must not be <code>null</code>.
323      * @param description
324      * The description for this command; may be <code>null</code>.
325      * @param category
326      * The category for this command; must not be <code>null</code>.
327      * @param parameters
328      * The parameters understood by this command. This value may be
329      * either <code>null</code> or empty if the command does not
330      * accept parameters.
331      * @param returnType
332      * The type of value returned by this command. This value may be
333      * <code>null</code> if the command does not declare a return
334      * type.
335      * @param helpContextId
336      * The identifier of the help context to associate with this
337      * command; may be <code>null</code> if this command does not
338      * have any help associated with it.
339      * @since 3.2
340      */

341     public final void define(final String JavaDoc name, final String JavaDoc description,
342             final Category category, final IParameter[] parameters,
343             ParameterType returnType, final String JavaDoc helpContextId) {
344         if (name == null) {
345             throw new NullPointerException JavaDoc(
346                     "The name of a command cannot be null"); //$NON-NLS-1$
347
}
348
349         if (category == null) {
350             throw new NullPointerException JavaDoc(
351                     "The category of a command cannot be null"); //$NON-NLS-1$
352
}
353
354         final boolean definedChanged = !this.defined;
355         this.defined = true;
356
357         final boolean nameChanged = !Util.equals(this.name, name);
358         this.name = name;
359
360         final boolean descriptionChanged = !Util.equals(this.description,
361                 description);
362         this.description = description;
363
364         final boolean categoryChanged = !Util.equals(this.category, category);
365         this.category = category;
366
367         final boolean parametersChanged = !Util.equals(this.parameters,
368                 parameters);
369         this.parameters = parameters;
370
371         final boolean returnTypeChanged = !Util.equals(this.returnType,
372                 returnType);
373         this.returnType = returnType;
374
375         final boolean helpContextIdChanged = !Util.equals(this.helpContextId,
376                 helpContextId);
377         this.helpContextId = helpContextId;
378
379         fireCommandChanged(new CommandEvent(this, categoryChanged,
380                 definedChanged, descriptionChanged, false, nameChanged,
381                 parametersChanged, returnTypeChanged, helpContextIdChanged));
382     }
383
384     /**
385      * Executes this command by delegating to the current handler, if any. If
386      * the debugging flag is set, then this method prints information about
387      * which handler is selected for performing this command. This method will
388      * succeed regardless of whether the command is enabled or defined. It is
389      * generally preferred to call {@link #executeWithChecks(ExecutionEvent)}.
390      *
391      * @param event
392      * An event containing all the information about the current
393      * state of the application; must not be <code>null</code>.
394      * @return The result of the execution; may be <code>null</code>. This
395      * result will be available to the client executing the command, and
396      * execution listeners.
397      * @throws ExecutionException
398      * If the handler has problems executing this command.
399      * @throws NotHandledException
400      * If there is no handler.
401      * @deprecated Please use {@link #executeWithChecks(ExecutionEvent)}
402      * instead.
403      */

404     public final Object JavaDoc execute(final ExecutionEvent event)
405             throws ExecutionException, NotHandledException {
406         firePreExecute(event);
407         final IHandler handler = this.handler;
408
409         // Perform the execution, if there is a handler.
410
if ((handler != null) && (handler.isHandled())) {
411             try {
412                 final Object JavaDoc returnValue = handler.execute(event);
413                 firePostExecuteSuccess(returnValue);
414                 return returnValue;
415             } catch (final ExecutionException e) {
416                 firePostExecuteFailure(e);
417                 throw e;
418             }
419         }
420
421         final NotHandledException e = new NotHandledException(
422                 "There is no handler to execute. " + getId()); //$NON-NLS-1$
423
fireNotHandled(e);
424         throw e;
425     }
426
427     /**
428      * Executes this command by delegating to the current handler, if any. If
429      * the debugging flag is set, then this method prints information about
430      * which handler is selected for performing this command. This does checks
431      * to see if the command is enabled and defined. If it is not both enabled
432      * and defined, then the execution listeners will be notified and an
433      * exception thrown.
434      *
435      * @param event
436      * An event containing all the information about the current
437      * state of the application; must not be <code>null</code>.
438      * @return The result of the execution; may be <code>null</code>. This
439      * result will be available to the client executing the command, and
440      * execution listeners.
441      * @throws ExecutionException
442      * If the handler has problems executing this command.
443      * @throws NotDefinedException
444      * If the command you are trying to execute is not defined.
445      * @throws NotEnabledException
446      * If the command you are trying to execute is not enabled.
447      * @throws NotHandledException
448      * If there is no handler.
449      * @since 3.2
450      */

451     public final Object JavaDoc executeWithChecks(final ExecutionEvent event)
452             throws ExecutionException, NotDefinedException,
453             NotEnabledException, NotHandledException {
454         firePreExecute(event);
455         final IHandler handler = this.handler;
456
457         if (!isDefined()) {
458             final NotDefinedException exception = new NotDefinedException(
459                     "Trying to execute a command that is not defined. " //$NON-NLS-1$
460
+ getId());
461             fireNotDefined(exception);
462             throw exception;
463         }
464
465         // Perform the execution, if there is a handler.
466
if ((handler != null) && (handler.isHandled())) {
467             if (!isEnabled()) {
468                 final NotEnabledException exception = new NotEnabledException(
469                         "Trying to execute the disabled command " + getId()); //$NON-NLS-1$
470
fireNotEnabled(exception);
471                 throw exception;
472             }
473
474             try {
475                 final Object JavaDoc returnValue = handler.execute(event);
476                 firePostExecuteSuccess(returnValue);
477                 return returnValue;
478             } catch (final ExecutionException e) {
479                 firePostExecuteFailure(e);
480                 throw e;
481             }
482         }
483
484         final NotHandledException e = new NotHandledException(
485                 "There is no handler to execute for command " + getId()); //$NON-NLS-1$
486
fireNotHandled(e);
487         throw e;
488     }
489
490     /**
491      * Notifies the listeners for this command that it has changed in some way.
492      *
493      * @param commandEvent
494      * The event to send to all of the listener; must not be
495      * <code>null</code>.
496      */

497     private final void fireCommandChanged(final CommandEvent commandEvent) {
498         if (commandEvent == null) {
499             throw new NullPointerException JavaDoc("Cannot fire a null event"); //$NON-NLS-1$
500
}
501
502         final Object JavaDoc[] listeners = getListeners();
503         for (int i = 0; i < listeners.length; i++) {
504             final ICommandListener listener = (ICommandListener) listeners[i];
505             SafeRunner.run(new ISafeRunnable() {
506                 public void handleException(Throwable JavaDoc exception) {
507                 }
508
509                 public void run() throws Exception JavaDoc {
510                     listener.commandChanged(commandEvent);
511                 }
512             });
513         }
514     }
515
516     /**
517      * Notifies the execution listeners for this command that an attempt to
518      * execute has failed because the command is not defined.
519      *
520      * @param e
521      * The exception that is about to be thrown; never
522      * <code>null</code>.
523      * @since 3.2
524      */

525     private final void fireNotDefined(final NotDefinedException e) {
526         // Debugging output
527
if (DEBUG_COMMAND_EXECUTION) {
528             Tracing.printTrace("COMMANDS", "execute" + Tracing.SEPARATOR //$NON-NLS-1$ //$NON-NLS-2$
529
+ "not defined: id=" + getId() + "; exception=" + e); //$NON-NLS-1$ //$NON-NLS-2$
530
}
531
532         if (executionListeners != null) {
533             final Object JavaDoc[] listeners = executionListeners.getListeners();
534             for (int i = 0; i < listeners.length; i++) {
535                 final Object JavaDoc object = listeners[i];
536                 if (object instanceof IExecutionListenerWithChecks) {
537                     final IExecutionListenerWithChecks listener = (IExecutionListenerWithChecks) object;
538                     listener.notDefined(getId(), e);
539                 }
540             }
541         }
542     }
543
544     /**
545      * Notifies the execution listeners for this command that an attempt to
546      * execute has failed because there is no handler.
547      *
548      * @param e
549      * The exception that is about to be thrown; never
550      * <code>null</code>.
551      * @since 3.2
552      */

553     private final void fireNotEnabled(final NotEnabledException e) {
554         // Debugging output
555
if (DEBUG_COMMAND_EXECUTION) {
556             Tracing.printTrace("COMMANDS", "execute" + Tracing.SEPARATOR //$NON-NLS-1$ //$NON-NLS-2$
557
+ "not enabled: id=" + getId() + "; exception=" + e); //$NON-NLS-1$ //$NON-NLS-2$
558
}
559
560         if (executionListeners != null) {
561             final Object JavaDoc[] listeners = executionListeners.getListeners();
562             for (int i = 0; i < listeners.length; i++) {
563                 final Object JavaDoc object = listeners[i];
564                 if (object instanceof IExecutionListenerWithChecks) {
565                     final IExecutionListenerWithChecks listener = (IExecutionListenerWithChecks) object;
566                     listener.notEnabled(getId(), e);
567                 }
568             }
569         }
570     }
571
572     /**
573      * Notifies the execution listeners for this command that an attempt to
574      * execute has failed because there is no handler.
575      *
576      * @param e
577      * The exception that is about to be thrown; never
578      * <code>null</code>.
579      */

580     private final void fireNotHandled(final NotHandledException e) {
581         // Debugging output
582
if (DEBUG_COMMAND_EXECUTION) {
583             Tracing.printTrace("COMMANDS", "execute" + Tracing.SEPARATOR //$NON-NLS-1$ //$NON-NLS-2$
584
+ "not handled: id=" + getId() + "; exception=" + e); //$NON-NLS-1$ //$NON-NLS-2$
585
}
586
587         if (executionListeners != null) {
588             final Object JavaDoc[] listeners = executionListeners.getListeners();
589             for (int i = 0; i < listeners.length; i++) {
590                 final IExecutionListener listener = (IExecutionListener) listeners[i];
591                 listener.notHandled(getId(), e);
592             }
593         }
594     }
595
596     /**
597      * Notifies the execution listeners for this command that an attempt to
598      * execute has failed during the execution.
599      *
600      * @param e
601      * The exception that has been thrown; never <code>null</code>.
602      * After this method completes, the exception will be thrown
603      * again.
604      */

605     private final void firePostExecuteFailure(final ExecutionException e) {
606         // Debugging output
607
if (DEBUG_COMMAND_EXECUTION) {
608             Tracing.printTrace("COMMANDS", "execute" + Tracing.SEPARATOR //$NON-NLS-1$ //$NON-NLS-2$
609
+ "failure: id=" + getId() + "; exception=" + e); //$NON-NLS-1$ //$NON-NLS-2$
610
}
611
612         if (executionListeners != null) {
613             final Object JavaDoc[] listeners = executionListeners.getListeners();
614             for (int i = 0; i < listeners.length; i++) {
615                 final IExecutionListener listener = (IExecutionListener) listeners[i];
616                 listener.postExecuteFailure(getId(), e);
617             }
618         }
619     }
620
621     /**
622      * Notifies the execution listeners for this command that an execution has
623      * completed successfully.
624      *
625      * @param returnValue
626      * The return value from the command; may be <code>null</code>.
627      */

628     private final void firePostExecuteSuccess(final Object JavaDoc returnValue) {
629         // Debugging output
630
if (DEBUG_COMMAND_EXECUTION) {
631             Tracing.printTrace("COMMANDS", "execute" + Tracing.SEPARATOR //$NON-NLS-1$ //$NON-NLS-2$
632
+ "success: id=" + getId() + "; returnValue=" //$NON-NLS-1$ //$NON-NLS-2$
633
+ returnValue);
634         }
635
636         if (executionListeners != null) {
637             final Object JavaDoc[] listeners = executionListeners.getListeners();
638             for (int i = 0; i < listeners.length; i++) {
639                 final IExecutionListener listener = (IExecutionListener) listeners[i];
640                 listener.postExecuteSuccess(getId(), returnValue);
641             }
642         }
643     }
644
645     /**
646      * Notifies the execution listeners for this command that an attempt to
647      * execute is about to start.
648      *
649      * @param event
650      * The execution event that will be used; never <code>null</code>.
651      */

652     private final void firePreExecute(final ExecutionEvent event) {
653         // Debugging output
654
if (DEBUG_COMMAND_EXECUTION) {
655             Tracing.printTrace("COMMANDS", "execute" + Tracing.SEPARATOR //$NON-NLS-1$ //$NON-NLS-2$
656
+ "starting: id=" + getId() + "; event=" + event); //$NON-NLS-1$ //$NON-NLS-2$
657
}
658
659         if (executionListeners != null) {
660             final Object JavaDoc[] listeners = executionListeners.getListeners();
661             for (int i = 0; i < listeners.length; i++) {
662                 final IExecutionListener listener = (IExecutionListener) listeners[i];
663                 listener.preExecute(getId(), event);
664             }
665         }
666     }
667
668     /**
669      * Returns the category for this command.
670      *
671      * @return The category for this command; never <code>null</code>.
672      * @throws NotDefinedException
673      * If the handle is not currently defined.
674      */

675     public final Category getCategory() throws NotDefinedException {
676         if (!isDefined()) {
677             throw new NotDefinedException(
678                     "Cannot get the category from an undefined command. " //$NON-NLS-1$
679
+ id);
680         }
681
682         return category;
683     }
684
685     /**
686      * Returns the current handler for this command. This is used by the command
687      * manager for determining the appropriate help context identifiers and by
688      * the command service to allow handlers to update elements.
689      * <p>
690      * This value can change at any time and should never be cached.
691      * </p>
692      *
693      * @return The current handler for this command; may be <code>null</code>.
694      * @since 3.3
695      */

696     public final IHandler getHandler() {
697         return handler;
698     }
699
700     /**
701      * Returns the help context identifier associated with this command. This
702      * method should not be called by clients. Clients should use
703      * {@link CommandManager#getHelpContextId(String)} instead.
704      *
705      * @return The help context identifier for this command; may be
706      * <code>null</code> if there is none.
707      * @since 3.2
708      */

709     final String JavaDoc getHelpContextId() {
710         return helpContextId;
711     }
712
713     /**
714      * Returns the parameter with the provided id or <code>null</code> if this
715      * command does not have a parameter with the id.
716      *
717      * @param parameterId
718      * The id of the parameter to retrieve.
719      * @return The parameter with the provided id or <code>null</code> if this
720      * command does not have a parameter with the id.
721      * @throws NotDefinedException
722      * If the handle is not currently defined.
723      * @since 3.2
724      */

725     public final IParameter getParameter(final String JavaDoc parameterId)
726             throws NotDefinedException {
727         if (!isDefined()) {
728             throw new NotDefinedException(
729                     "Cannot get a parameter from an undefined command. " //$NON-NLS-1$
730
+ id);
731         }
732
733         if (parameters == null) {
734             return null;
735         }
736
737         for (int i = 0; i < parameters.length; i++) {
738             final IParameter parameter = parameters[i];
739             if (parameter.getId().equals(parameterId)) {
740                 return parameter;
741             }
742         }
743
744         return null;
745     }
746
747     /**
748      * Returns the parameters for this command. This call triggers provides a
749      * copy of the array, so excessive calls to this method should be avoided.
750      *
751      * @return The parameters for this command. This value might be
752      * <code>null</code>, if the command has no parameters.
753      * @throws NotDefinedException
754      * If the handle is not currently defined.
755      */

756     public final IParameter[] getParameters() throws NotDefinedException {
757         if (!isDefined()) {
758             throw new NotDefinedException(
759                     "Cannot get the parameters from an undefined command. " //$NON-NLS-1$
760
+ id);
761         }
762
763         if ((parameters == null) || (parameters.length == 0)) {
764             return null;
765         }
766
767         final IParameter[] returnValue = new IParameter[parameters.length];
768         System.arraycopy(parameters, 0, returnValue, 0, parameters.length);
769         return returnValue;
770     }
771
772     /**
773      * Returns the {@link ParameterType} for the parameter with the provided id
774      * or <code>null</code> if this command does not have a parameter type
775      * with the id.
776      *
777      * @param parameterId
778      * The id of the parameter to retrieve the {@link ParameterType}
779      * of.
780      * @return The {@link ParameterType} for the parameter with the provided id
781      * or <code>null</code> if this command does not have a parameter
782      * type with the provided id.
783      * @throws NotDefinedException
784      * If the handle is not currently defined.
785      * @since 3.2
786      */

787     public final ParameterType getParameterType(final String JavaDoc parameterId)
788             throws NotDefinedException {
789         final IParameter parameter = getParameter(parameterId);
790         if (parameter instanceof ITypedParameter) {
791             final ITypedParameter parameterWithType = (ITypedParameter) parameter;
792             return parameterWithType.getParameterType();
793         }
794         return null;
795     }
796
797     /**
798      * Returns the {@link ParameterType} for the return value of this command or
799      * <code>null</code> if this command does not declare a return value
800      * parameter type.
801      *
802      * @return The {@link ParameterType} for the return value of this command or
803      * <code>null</code> if this command does not declare a return
804      * value parameter type.
805      * @throws NotDefinedException
806      * If the handle is not currently defined.
807      * @since 3.2
808      */

809     public final ParameterType getReturnType() throws NotDefinedException {
810         if (!isDefined()) {
811             throw new NotDefinedException(
812                     "Cannot get the return type of an undefined command. " //$NON-NLS-1$
813
+ id);
814         }
815
816         return returnType;
817     }
818
819     /**
820      * Returns whether this command has a handler, and whether this handler is
821      * also handled and enabled.
822      *
823      * @return <code>true</code> if the command is handled; <code>false</code>
824      * otherwise.
825      */

826     public final boolean isEnabled() {
827         if (handler == null) {
828             return false;
829         }
830
831         return handler.isEnabled();
832     }
833
834     /**
835      * Returns whether this command has a handler, and whether this handler is
836      * also handled.
837      *
838      * @return <code>true</code> if the command is handled; <code>false</code>
839      * otherwise.
840      */

841     public final boolean isHandled() {
842         if (handler == null) {
843             return false;
844         }
845
846         return handler.isHandled();
847     }
848
849     /**
850      * Removes a listener from this command.
851      *
852      * @param commandListener
853      * The listener to be removed; must not be <code>null</code>.
854      *
855      */

856     public final void removeCommandListener(
857             final ICommandListener commandListener) {
858         if (commandListener == null) {
859             throw new NullPointerException JavaDoc(
860                     "Cannot remove a null command listener"); //$NON-NLS-1$
861
}
862
863         removeListenerObject(commandListener);
864     }
865
866     /**
867      * Removes a listener from this command.
868      *
869      * @param executionListener
870      * The listener to be removed; must not be <code>null</code>.
871      *
872      */

873     public final void removeExecutionListener(
874             final IExecutionListener executionListener) {
875         if (executionListener == null) {
876             throw new NullPointerException JavaDoc(
877                     "Cannot remove a null execution listener"); //$NON-NLS-1$
878
}
879
880         if (executionListeners != null) {
881             executionListeners.remove(executionListener);
882             if (executionListeners.isEmpty()) {
883                 executionListeners = null;
884             }
885         }
886     }
887
888     /**
889      * <p>
890      * Removes a state from this command. This will remove the state from the
891      * active handler, if the active handler is an instance of
892      * {@link IObjectWithState}.
893      * </p>
894      *
895      * @param stateId
896      * The identifier of the state to remove; must not be
897      * <code>null</code>.
898      * @since 3.2
899      */

900     public void removeState(final String JavaDoc stateId) {
901         if (handler instanceof IObjectWithState) {
902             ((IObjectWithState) handler).removeState(stateId);
903         }
904         super.removeState(stateId);
905     }
906
907     /**
908      * Changes the handler for this command. This will remove all the state from
909      * the currently active handler (if any), and add it to <code>handler</code>.
910      * If debugging is turned on, then this will also print information about
911      * the change to <code>System.out</code>.
912      *
913      * @param handler
914      * The new handler; may be <code>null</code> if none.
915      * @return <code>true</code> if the handler changed; <code>false</code>
916      * otherwise.
917      */

918     public final boolean setHandler(final IHandler handler) {
919         if (Util.equals(handler, this.handler)) {
920             return false;
921         }
922
923         // Swap the state around.
924
final String JavaDoc[] stateIds = getStateIds();
925         if (stateIds != null) {
926             for (int i = 0; i < stateIds.length; i++) {
927                 final String JavaDoc stateId = stateIds[i];
928                 if (this.handler instanceof IObjectWithState) {
929                     ((IObjectWithState) this.handler).removeState(stateId);
930                 }
931                 if (handler instanceof IObjectWithState) {
932                     final State stateToAdd = getState(stateId);
933                     ((IObjectWithState) handler).addState(stateId, stateToAdd);
934                 }
935             }
936         }
937
938         boolean enabled = isEnabled();
939         if (this.handler != null) {
940             this.handler.removeHandlerListener(getHandlerListener());
941         }
942
943         // Update the handler, and flush the string representation.
944
this.handler = handler;
945         if (this.handler != null) {
946             this.handler.addHandlerListener(getHandlerListener());
947         }
948         string = null;
949
950         // Debugging output
951
if ((DEBUG_HANDLERS)
952                 && ((DEBUG_HANDLERS_COMMAND_ID == null) || (DEBUG_HANDLERS_COMMAND_ID
953                         .equals(id)))) {
954             final StringBuffer JavaDoc buffer = new StringBuffer JavaDoc("Command('"); //$NON-NLS-1$
955
buffer.append(id);
956             buffer.append("') has changed to "); //$NON-NLS-1$
957
if (handler == null) {
958                 buffer.append("no handler"); //$NON-NLS-1$
959
} else {
960                 buffer.append('\'');
961                 buffer.append(handler);
962                 buffer.append("' as its handler"); //$NON-NLS-1$
963
}
964             Tracing.printTrace("HANDLERS", buffer.toString()); //$NON-NLS-1$
965
}
966
967         // Send notification
968
fireCommandChanged(new CommandEvent(this, false, false, false, true,
969                 false, false, false, false, enabled != isEnabled()));
970
971         return true;
972     }
973
974     /**
975      * @return
976      */

977     private IHandlerListener getHandlerListener() {
978         if (handlerListener == null) {
979             handlerListener = new IHandlerListener() {
980                 public void handlerChanged(HandlerEvent handlerEvent) {
981                     boolean enabledChanged = handlerEvent.isEnabledChanged();
982                     boolean handledChanged = handlerEvent.isHandledChanged();
983                     fireCommandChanged(new CommandEvent(Command.this, false,
984                             false, false, handledChanged, false, false, false,
985                             false, enabledChanged));
986                 }
987             };
988         }
989         return handlerListener;
990     }
991
992     /**
993      * The string representation of this command -- for debugging purposes only.
994      * This string should not be shown to an end user.
995      *
996      * @return The string representation; never <code>null</code>.
997      */

998     public final String JavaDoc toString() {
999         if (string == null) {
1000            final StringWriter JavaDoc sw = new StringWriter JavaDoc();
1001            final BufferedWriter JavaDoc buffer = new BufferedWriter JavaDoc(sw);
1002            try {
1003                buffer.write("Command("); //$NON-NLS-1$
1004
buffer.write(id);
1005                buffer.write(',');
1006                buffer.write(name==null?"":name); //$NON-NLS-1$
1007
buffer.write(',');
1008                buffer.newLine();
1009                buffer.write("\t\t"); //$NON-NLS-1$
1010
buffer.write(description==null?"":description); //$NON-NLS-1$
1011
buffer.write(',');
1012                buffer.newLine();
1013                buffer.write("\t\t"); //$NON-NLS-1$
1014
buffer.write(category==null?"":category.toString()); //$NON-NLS-1$
1015
buffer.write(',');
1016                buffer.newLine();
1017                buffer.write("\t\t"); //$NON-NLS-1$
1018
buffer.write(handler==null?"":handler.toString()); //$NON-NLS-1$
1019
buffer.write(',');
1020                buffer.newLine();
1021                buffer.write("\t\t"); //$NON-NLS-1$
1022
buffer.write(parameters==null?"":parameters.toString()); //$NON-NLS-1$
1023
buffer.write(',');
1024                buffer.write(returnType==null?"":returnType.toString()); //$NON-NLS-1$
1025
buffer.write(',');
1026                buffer.write(""+defined); //$NON-NLS-1$
1027
buffer.write(')');
1028                buffer.flush();
1029            } catch (IOException JavaDoc e) {
1030                // should never get this exception
1031
}
1032            string = sw.toString();
1033        }
1034        return string;
1035    }
1036
1037    /**
1038     * Makes this command become undefined. This has the side effect of changing
1039     * the name and description to <code>null</code>. This also removes all
1040     * state and disposes of it. Notification is sent to all listeners.
1041     */

1042    public final void undefine() {
1043        boolean enabledChanged = isEnabled();
1044
1045        string = null;
1046
1047        final boolean definedChanged = defined;
1048        defined = false;
1049
1050        final boolean nameChanged = name != null;
1051        name = null;
1052
1053        final boolean descriptionChanged = description != null;
1054        description = null;
1055
1056        final boolean categoryChanged = category != null;
1057        category = null;
1058
1059        final boolean parametersChanged = parameters != null;
1060        parameters = null;
1061
1062        final boolean returnTypeChanged = returnType != null;
1063        returnType = null;
1064
1065        final String JavaDoc[] stateIds = getStateIds();
1066        if (stateIds != null) {
1067            if (handler instanceof IObjectWithState) {
1068                final IObjectWithState handlerWithState = (IObjectWithState) handler;
1069                for (int i = 0; i < stateIds.length; i++) {
1070                    final String JavaDoc stateId = stateIds[i];
1071                    handlerWithState.removeState(stateId);
1072
1073                    final State state = getState(stateId);
1074                    removeState(stateId);
1075                    state.dispose();
1076                }
1077            } else {
1078                for (int i = 0; i < stateIds.length; i++) {
1079                    final String JavaDoc stateId = stateIds[i];
1080                    final State state = getState(stateId);
1081                    removeState(stateId);
1082                    state.dispose();
1083                }
1084            }
1085        }
1086
1087        fireCommandChanged(new CommandEvent(this, categoryChanged,
1088                definedChanged, descriptionChanged, false, nameChanged,
1089                parametersChanged, returnTypeChanged, false, enabledChanged));
1090    }
1091}
1092
Popular Tags