Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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)