Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
berryCommand.cpp
Go to the documentation of this file.
1 /*===================================================================
2 
3 BlueBerry Platform
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
17 #include "berryCommand.h"
18 
19 #include "berryIParameter.h"
20 #include "berryITypedParameter.h"
21 #include "berryIHandler.h"
22 #include "berryIHandlerListener.h"
24 #include "berryHandlerEvent.h"
25 #include "berryCommandEvent.h"
26 #include "berryExecutionEvent.h"
27 #include "berryCommandCategory.h"
28 #include "berryState.h"
29 
31 #include "internal/berryCommandUtils.h"
32 
33 #include <QTextStream>
34 
35 namespace berry {
36 
38 
39 bool Command::DEBUG_HANDLERS = false;
40 
41 QString Command::DEBUG_HANDLERS_COMMAND_ID = QString::null;
42 
43 
44 Command::Command(const QString& id)
46 {
47 }
48 
50 {
51  if (!commandListener)
52  {
53  throw ctkInvalidArgumentException("Cannot add a null command listener");
54  }
55  commandEvents.AddListener(commandListener);
56 }
57 
59 {
60  if (!executionListener)
61  {
62  throw ctkInvalidArgumentException("Cannot add a null execution listener");
63  }
64  executionEvents.AddListener(executionListener);
65 }
66 
67 void Command::AddState(const QString& id, const State::Pointer& state)
68 {
69  NamedHandleObjectWithState::AddState(id, state);
70  state->SetId(id);
71  if (IObjectWithState::Pointer stateHandler = handler.Cast<IObjectWithState>())
72  {
73  stateHandler->AddState(id, state);
74  }
75 }
76 
77 bool Command::operator<(const Object* object) const
78 {
79  const Command* castedObject = dynamic_cast<const Command*>(object);
80  int compareTo = CommandUtils::CompareObj(category, castedObject->category);
81  if (compareTo == 0)
82  {
83  compareTo = CommandUtils::Compare(defined, castedObject->defined);
84  if (compareTo == 0)
85  {
86  compareTo = CommandUtils::Compare(description, castedObject->description);
87  if (compareTo == 0)
88  {
89  compareTo = CommandUtils::CompareObj(handler, castedObject->handler);
90  if (compareTo == 0)
91  {
92  compareTo = CommandUtils::Compare(id, castedObject->id);
93  if (compareTo == 0)
94  {
95  compareTo = CommandUtils::Compare(name, castedObject->name);
96  if (compareTo == 0)
97  {
98  compareTo = CommandUtils::Compare(parameters,
99  castedObject->parameters);
100  }
101  }
102  }
103  }
104  }
105  }
106  return compareTo < 0;
107 }
108 
109 void Command::Define(const QString& name, const QString& description,
110  const CommandCategory::Pointer category,
111  const QList<IParameter::Pointer>& parameters,
112  const ParameterType::Pointer& returnType,
113  const QString& helpContextId)
114 {
115  if (name == "")
116  {
117  throw ctkInvalidArgumentException("The name of a command cannot be empty");
118  }
119 
120  if (!category)
121  {
122  throw ctkInvalidArgumentException("The category of a command cannot be null");
123  }
124 
125  const bool definedChanged = !this->defined;
126  this->defined = true;
127 
128  const bool nameChanged = this->name != name;
129  this->name = name;
130 
131  const bool descriptionChanged = this->description != description;
132  this->description = description;
133 
134  const bool categoryChanged = this->category != category;
135  this->category = category;
136 
137  const bool parametersChanged = !CommandUtils::Equals(this->parameters,
138  parameters);
139  this->parameters = parameters;
140 
141  const bool returnTypeChanged = this->returnType != returnType;
142  this->returnType = returnType;
143 
144  const bool helpContextIdChanged = this->helpContextId != helpContextId;
145  this->helpContextId = helpContextId;
146 
147  CommandEvent::Pointer event(new CommandEvent(Command::Pointer(this), categoryChanged,
148  definedChanged, descriptionChanged, false, nameChanged,
149  parametersChanged, returnTypeChanged, helpContextIdChanged));
150  this->FireCommandChanged(event);
151 }
152 
154 {
155  this->FirePreExecute(event);
156  const IHandler::Pointer handler(this->handler);
157 
158  if (!this->IsDefined())
159  {
160  const NotDefinedException exception(
161  "Trying to execute a command that is not defined. " + this->GetId());
162  this->FireNotDefined(&exception);
163  throw exception;
164  }
165 
166  // Perform the execution, if there is a handler.
167  if (handler && handler->IsHandled())
168  {
169  this->SetEnabled(event->GetApplicationContext());
170  if (!this->IsEnabled()) {
171  const NotEnabledException exception(
172  "Trying to execute the disabled command " + this->GetId());
173  this->FireNotEnabled(&exception);
174  throw exception;
175  }
176 
177  try
178  {
179  const Object::Pointer returnValue(handler->Execute(event));
180  this->FirePostExecuteSuccess(returnValue);
181  return returnValue;
182  }
183  catch (const ExecutionException* e)
184  {
185  this->FirePostExecuteFailure(e);
186  throw e;
187  }
188  }
189 
190  const NotHandledException e(
191  "There is no handler to execute for command " + this->GetId());
192  this->FireNotHandled(&e);
193  throw e;
194 }
195 
196 void Command::FireCommandChanged(const CommandEvent::ConstPointer commandEvent)
197 {
198  if (!commandEvent)
199  {
200  throw ctkInvalidArgumentException("Cannot fire a null event");
201  }
202 
203  try
204  {
205  commandEvents.commandChanged(commandEvent);
206  }
207  catch (...)
208  {
209  //TODO log exceptions?
210  }
211 }
212 
213 void Command::FireNotDefined(const NotDefinedException* e)
214 {
215  // Debugging output
217  {
219  + "not defined: id=" + this->GetId() + "; exception=" + e->what());
220  }
221 
222  executionEvents.notDefined(this->GetId(), e);
223 }
224 
225 void Command::FireNotEnabled(const NotEnabledException* e)
226 {
227  // Debugging output
229  {
231  + "not enabled: id=" + this->GetId() + "; exception=" + e->what());
232  }
233 
234  executionEvents.notEnabled(this->GetId(), e);
235 }
236 
237 void Command::FireNotHandled(const NotHandledException* e)
238 {
239  // Debugging output
242  + "not handled: id=" + this->GetId() + "; exception=" + e->what());
243  }
244 
245  executionEvents.notHandled(this->GetId(), e);
246 }
247 
248 void Command::FirePostExecuteFailure(const ExecutionException* e)
249 {
250  // Debugging output
252  {
254  + "failure: id=" + this->GetId() + "; exception=" + e->what());
255  }
256 
257  executionEvents.postExecuteFailure(this->GetId(), e);
258 }
259 
260 void Command::FirePostExecuteSuccess(const Object::Pointer returnValue)
261 {
262  // Debugging output
264  {
266  + "success: id=" + this->GetId() + "; returnValue=" +
267  (returnValue.IsNull() ? QString("NULL") : returnValue->ToString()));
268  }
269 
270  executionEvents.postExecuteSuccess(this->GetId(), returnValue);
271 }
272 
273 void Command::FirePreExecute(const ExecutionEvent::ConstPointer event)
274 {
275  // Debugging output
277  {
279  + "starting: id=" + this->GetId() + "; event=" + event->ToString());
280  }
281 
282  executionEvents.preExecute(this->GetId(), event);
283 }
284 
286 {
287  return handler;
288 }
289 
291 {
292  return helpContextId;
293 }
294 
295 IParameter::Pointer Command::GetParameter(const QString& parameterId) const
296 {
297  if (!this->IsDefined())
298  {
299  throw NotDefinedException(
300  "Cannot get a parameter from an undefined command. " + id);
301  }
302 
303  for (int i = 0; i < parameters.size(); i++)
304  {
305  IParameter::Pointer parameter(parameters[i]);
306  if (parameter->GetId() == parameterId) {
307  return parameter;
308  }
309  }
310 
311  return IParameter::Pointer(nullptr);
312 }
313 
314 QList<SmartPointer<IParameter> > Command::GetParameters() const
315 {
316  if (!this->IsDefined())
317  {
318  throw NotDefinedException(
319  "Cannot get the parameters from an undefined command. " + id);
320  }
321 
322  return parameters;
323 }
324 
325 ParameterType::Pointer Command::GetParameterType(const QString& parameterId) const
326 {
327  const IParameter::Pointer parameter(this->GetParameter(parameterId));
328  if (ITypedParameter::Pointer parameterWithType = parameter.Cast<ITypedParameter>())
329  {
330  return parameterWithType->GetParameterType();
331  }
332  return ParameterType::Pointer(nullptr);
333 }
334 
336 {
337  if (!this->IsDefined())
338  {
339  throw NotDefinedException(
340  "Cannot get the return type of an undefined command. " + id);
341  }
342 
343  return returnType;
344 }
345 
346 bool Command::IsEnabled() const
347 {
348  if (!handler)
349  {
350  return false;
351  }
352 
353  return handler->IsEnabled();
354 }
355 
356 void Command::SetEnabled(const Object::Pointer& evaluationContext)
357 {
358  if (handler)
359  {
360  handler->SetEnabled(evaluationContext);
361  }
362 }
363 
364 bool Command::IsHandled() const
365 {
366  if (!handler)
367  {
368  return false;
369  }
370 
371  return handler->IsHandled();
372 }
373 
375 {
376  if (!commandListener)
377  {
378  throw ctkInvalidArgumentException(
379  "Cannot remove a null command listener");
380  }
381 
382  commandEvents.RemoveListener(commandListener);
383 }
384 
393 {
394  if (!executionListener)
395  {
396  throw Poco::NullPointerException(
397  "Cannot remove a null execution listener");
398  }
399  executionEvents.RemoveListener(executionListener);
400 }
401 
402 void Command::RemoveState(const QString& stateId)
403 {
404  if (IObjectWithState::Pointer stateHandler = handler.Cast<IObjectWithState>())
405  {
406  stateHandler->RemoveState(stateId);
407  }
409 }
410 
412 {
413  if (handler == this->handler)
414  {
415  return false;
416  }
417 
418  // Swap the state around.
419  const QList<QString> stateIds(this->GetStateIds());
420  for (int i = 0; i < stateIds.size(); ++i)
421  {
422  const QString stateId = stateIds[i];
423  if (IObjectWithState::Pointer stateHandler = this->handler.Cast<IObjectWithState>())
424  {
425  stateHandler->RemoveState(stateId);
426  }
427  if (IObjectWithState::Pointer stateHandler = handler.Cast<IObjectWithState>())
428  {
429  const State::Pointer stateToAdd(this->GetState(stateId));
430  stateHandler->AddState(stateId, stateToAdd);
431  }
432  }
433 
434  bool enabled = this->IsEnabled();
435  if (this->handler)
436  {
437  this->handler->RemoveHandlerListener(this->GetHandlerListener());
438  }
439 
440  // Update the handler, and flush the string representation.
441  this->handler = handler;
442  if (this->handler)
443  {
444  this->handler->AddHandlerListener(this->GetHandlerListener());
445  }
446  this->str = "";
447 
448  // Debugging output
449  if ((DEBUG_HANDLERS)
450  && ((DEBUG_HANDLERS_COMMAND_ID.isEmpty()) || (DEBUG_HANDLERS_COMMAND_ID == id)))
451  {
452  QString buffer("Command('");
453  buffer += id + "') has changed to ";
454  if (!handler) {
455  buffer += "no handler";
456  } else {
457  buffer += "\'" + handler->ToString() + "' as its handler";
458  }
459  CommandTracing::PrintTrace("HANDLERS", buffer);
460  }
461 
462  // Send notification
463  CommandEvent::Pointer cmdEvent(new CommandEvent(Command::Pointer(this), false, false, false, true,
464  false, false, false, false, enabled != this->IsEnabled()));
465  this->FireCommandChanged(cmdEvent);
466 
467  return true;
468 }
469 
470 IHandlerListener* Command::GetHandlerListener()
471 {
472  return this;
473 }
474 
475 void Command::HandlerChanged(const SmartPointer<HandlerEvent>& handlerEvent)
476 {
477  bool enabledChanged = handlerEvent->IsEnabledChanged();
478  bool handledChanged = handlerEvent->IsHandledChanged();
479  CommandEvent::Pointer cmdEvent(new CommandEvent(Command::Pointer(this), false,
480  false, false, handledChanged, false, false, false,
481  false, enabledChanged));
482  this->FireCommandChanged(cmdEvent);
483 }
484 
485 QString Command::ToString() const
486 {
487  if (str.isEmpty())
488  {
489  QTextStream buffer(&str);
490 
491  buffer << "Command(" << id << ',' << name << ",\n\t\t";
492  buffer << description << ",\n\t\t" << (category ? category->ToString() : QString(""));
493  buffer << ",\n\t\t" << (handler ? handler->ToString() : "");
494  buffer << ",\n\t\t" << "[";
495  for (int i = 0; i < parameters.size(); ++i)
496  {
497  buffer << parameters[i]->GetId();
498  }
499  buffer << "]," << (returnType ? returnType->ToString() : "");
500  buffer << "," << defined << ")";
501  }
502  return str;
503 }
504 
506 {
507  bool enabledChanged = this->IsEnabled();
508 
509  str = "";
510 
511  const bool definedChanged = defined;
512  defined = false;
513 
514  const bool nameChanged = !name.isEmpty();
515  name = "";
516 
517  const bool descriptionChanged = !description.isEmpty();
518  description = "";
519 
520  const bool categoryChanged = category;
521  category = nullptr;
522 
523  const bool parametersChanged = !parameters.empty();
524  parameters.clear();
525 
526  const bool returnTypeChanged = returnType;
527  returnType = nullptr;
528 
529  const QList<QString> stateIds(this->GetStateIds());
530  if (IObjectWithState::Pointer handlerWithState = handler.Cast<IObjectWithState>())
531  {
532  for (int i = 0; i < stateIds.size(); i++)
533  {
534  const QString stateId(stateIds[i]);
535  handlerWithState->RemoveState(stateId);
536 
537  const State::Pointer state(this->GetState(stateId));
538  this->RemoveState(stateId);
539  //state.dispose();
540  }
541  }
542  else
543  {
544  for (int i = 0; i < stateIds.size(); ++i)
545  {
546  const QString stateId(stateIds[i]);
547  const State::Pointer state(this->GetState(stateId));
548  this->RemoveState(stateId);
549  //state.dispose();
550  }
551  }
552 
553  CommandEvent::Pointer cmdEvent(new CommandEvent(Command::Pointer(this), categoryChanged,
554  definedChanged, descriptionChanged, false, nameChanged,
555  parametersChanged, returnTypeChanged, false, enabledChanged));
556  this->FireCommandChanged(cmdEvent);
557 }
558 
559 }
berry::SmartPointer< const Self > ConstPointer
Definition: berryObject.h:89
SmartPointer< ParameterType > GetParameterType(const QString &parameterId) const
static MsgHandler handler
Definition: usUtils.cpp:261
Message2< const QString &, const NotEnabledException * > notEnabled
Object::Pointer ExecuteWithChecks(const SmartPointer< const ExecutionEvent > event)
void AddExecutionListener(IExecutionListener *executionListener)
void RemoveListener(ICommandListener *listener)
bool IsEnabled() const
Light weight base class for most BlueBerry classes.
Definition: berryObject.h:78
void AddState(const QString &id, const SmartPointer< State > &state) override
QString GetId() const
SmartPointer< IHandler > GetHandler() const
Message2< const QString &, const ExecutionException * > postExecuteFailure
void AddCommandListener(ICommandListener *commandListener)
static void PrintTrace(const QString &component, const QString &message)
bool operator<(const Object *object) const override
static const QString SEPARATOR
SmartPointer< IParameter > GetParameter(const QString &parameterId) const
QList< QString > GetStateIds() const override
static bool DEBUG_HANDLERS
Definition: berryCommand.h:81
berry::SmartPointer< Self > Pointer
Definition: berryObject.h:88
void RemoveListener(IExecutionListener *listener) override
void Define(const QString &name, const QString &description, const SmartPointer< CommandCategory > category, const QList< SmartPointer< IParameter > > &parameters=QList< SmartPointer< IParameter > >(), const SmartPointer< ParameterType > &returnType=SmartPointer< ParameterType >(nullptr), const QString &helpContextId="")
const SmartPointer< State > & state
QString ToString() const override
Message2< const QString &, const NotDefinedException * > notDefined
void RemoveExecutionListener(IExecutionListener *executionListener)
static bool DEBUG_COMMAND_EXECUTION
Definition: berryCommand.h:75
QString GetHelpContextId() const
Message2< const QString &, const Object::Pointer & > postExecuteSuccess
void RemoveState(const QString &stateId) override
bool SetHandler(const SmartPointer< IHandler > handler)
void RemoveCommandListener(ICommandListener *commandListener)
void AddListener(ICommandListener *listener)
SmartPointer< Other > Cast() const
static QString DEBUG_HANDLERS_COMMAND_ID
Definition: berryCommand.h:88
SmartPointer< State > GetState(const QString &stateId) const override
void Undefine() override
QList< SmartPointer< IParameter > > GetParameters() const
Message2< const QString &, const SmartPointer< const ExecutionEvent > & > preExecute
Command(const QString &id)
Message2< const QString &, const NotHandledException * > notHandled
void AddListener(IExecutionListener *listener) override
SmartPointer< ParameterType > GetReturnType() const
bool IsHandled() const
void SetEnabled(const Object::Pointer &evaluationContext)