Medical Imaging Interaction Toolkit  2018.4.99-08619e4f
Medical Imaging Interaction Toolkit
berryParameterizedCommand.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
14 
15 #include "berryIParameter.h"
16 #include "berryIParameterValues.h"
17 #include "berryCommand.h"
18 #include "berryParameterization.h"
19 #include "berryExecutionEvent.h"
20 #include "berryCommandManager.h"
21 #include "berryCommandCategory.h"
22 #include "berryState.h"
23 #include "berryIHandler.h"
24 
25 #include "internal/berryCommandUtils.h"
26 
27 #include <berryObjectString.h>
28 
29 
30 namespace berry
31 {
32 
33 const uint ParameterizedCommand::HASH_CODE_NOT_COMPUTED = 0;
34 const uint ParameterizedCommand::HASH_FACTOR = 89;
35 const uint ParameterizedCommand::HASH_INITIAL = qHash("berry::ParameterizedCommand");
36 
38  const QList<Parameterization>& params)
39  : command(command), hashCode(HASH_CODE_NOT_COMPUTED)
40 {
41  if (!command)
42  {
43  throw Poco::NullPointerException(
44  "A parameterized command cannot have a null command");
45  }
46 
47  QList<IParameter::Pointer> parameters;
48  try
49  {
50  parameters = command->GetParameters();
51  } catch (const NotDefinedException* /*e*/)
52  {
53  // This should not happen.
54  }
55  if (!params.empty() && !parameters.empty())
56  {
57  for (int j = 0; j < parameters.size(); j++)
58  {
59  for (int i = 0; i < params.size(); i++)
60  {
61  if (parameters[j] == params[i].GetParameter())
62  {
63  this->parameterizations.push_back(params[i]);
64  }
65  }
66  }
67  }
68 }
69 
70 bool ParameterizedCommand::operator<(const Object* object) const
71 {
72  const ParameterizedCommand* command = dynamic_cast<const ParameterizedCommand*>(object);
73  const bool thisDefined = this->command->IsDefined();
74  const bool otherDefined = command->command->IsDefined();
75  if (!thisDefined || !otherDefined)
76  {
77  return CommandUtils::Compare(thisDefined, otherDefined) < 0;
78  }
79 
80  try
81  {
82  const int compareTo = this->GetName().compare(command->GetName());
83  if (compareTo == 0)
84  {
85  return (this->GetId() < command->GetId());
86  }
87  return compareTo < 0;
88  }
89  catch (const NotDefinedException* /*e*/)
90  {
91  throw CommandException(
92  "Concurrent modification of a command's defined state");
93  }
94 }
95 
96 bool ParameterizedCommand::operator==(const Object* object) const
97 {
98  if (this == object)
99  {
100  return true;
101  }
102 
103  if (const ParameterizedCommand* command = dynamic_cast<const ParameterizedCommand*>(object))
104  {
105  if (!(this->command == command->command))
106  {
107  return false;
108  }
109 
110  return CommandUtils::Equals(this->parameterizations, command->parameterizations);
111  }
112 
113  return false;
114 }
115 
117  const Object::Pointer& applicationContext)
118 {
119  ExecutionEvent::Pointer excEvent(new ExecutionEvent(command,
120  this->GetParameterMap(), trigger, applicationContext));
121  return command->ExecuteWithChecks(excEvent);
122 }
123 
125 {
126  return command;
127 }
128 
130 {
131  return command->GetId();
132 }
133 
135 {
136  if (name.isEmpty())
137  {
138  QTextStream nameBuffer(&name);
139  nameBuffer << command->GetName() << " (";
140  const unsigned int parameterizationCount = (unsigned int) parameterizations.size();
141  for (unsigned int i = 0; i < parameterizationCount; i++)
142  {
143  const Parameterization& parameterization = parameterizations[i];
144  nameBuffer << parameterization.GetParameter()->GetName() << ": ";
145  try
146  {
147  nameBuffer << parameterization.GetValueName();
148  }
149  catch (const ParameterValuesException& /*e*/)
150  {
151  /*
152  * Just let it go for now. If someone complains we can
153  * add more info later.
154  */
155  }
156 
157  // If there is another item, append a separator.
158  if (i + 1 < parameterizationCount)
159  {
160  nameBuffer << ", ";
161  }
162 
163  nameBuffer << ")";
164  }
165  }
166  return name;
167 }
168 
169 QHash<QString, QString> ParameterizedCommand::GetParameterMap() const
170 {
171  QHash<QString, QString> parameterMap;
172  for (int i = 0; i < parameterizations.size(); i++)
173  {
174  const Parameterization& parameterization = parameterizations[i];
175  parameterMap.insert(parameterization.GetParameter()->GetId(),
176  parameterization.GetValue());
177  }
178  return parameterMap;
179 }
180 
182 {
183  if (hashCode == HASH_CODE_NOT_COMPUTED)
184  {
185  hashCode = HASH_INITIAL * HASH_FACTOR + (command ? command->HashCode() : 0);
186  hashCode = hashCode * HASH_FACTOR;
187  for (int i = 0; i < parameterizations.size(); i++)
188  {
189  hashCode += parameterizations[i].HashCode();
190  }
191 
192  if (hashCode == HASH_CODE_NOT_COMPUTED)
193  {
194  hashCode++;
195  }
196  }
197  return hashCode;
198 }
199 
201 {
202  const QString escapedId(this->Escape(this->GetId()));
203 
204  if (parameterizations.empty())
205  {
206  return escapedId;
207  }
208 
209  QString str;
210  QTextStream buffer(&str);
212 
213  for (int i = 0; i < parameterizations.size(); i++)
214  {
215 
216  if (i> 0)
217  {
218  // insert separator between parameters
220  }
221 
222  const Parameterization& parameterization = parameterizations[i];
223  const QString parameterId(parameterization.GetParameter()->GetId());
224  const QString escapedParameterId(this->Escape(parameterId));
225 
226  buffer << escapedParameterId;
227 
228  const QString parameterValue(parameterization.GetValue());
229  if (!parameterValue.isEmpty())
230  {
231  const QString escapedParameterValue(this->Escape(parameterValue));
233  << escapedParameterValue;
234  }
235  }
236 
238 
239  return str;
240 }
241 
243 {
244  QString str;
245  QTextStream buffer(&str);
246  buffer << "ParameterizedCommand(" << command->ToString() << ","
247  << CommandUtils::ToString(parameterizations) << ")";
248  return str;
249 }
250 
251 QList<ParameterizedCommand::Pointer>
253 {
254  QList<IParameter::Pointer> parameters(command->GetParameters());
255 
256  typedef QList<QList<Parameterization> > ExpandedParamsType;
257  const ExpandedParamsType expansion(ExpandParameters(0, parameters));
258  QList<ParameterizedCommand::Pointer> combinations;
259 
260  for (ExpandedParamsType::const_iterator expansionItr = expansion.begin();
261  expansionItr != expansion.end(); ++expansionItr)
262  {
263  QList<Parameterization> combination(*expansionItr);
264 
265  QList<Parameterization> parameterizations(combination);
267  parameterizations));
268  combinations.push_back(pCmd);
269  }
270 
271  return combinations;
272 }
273 
275  const QHash<QString, Object::Pointer>& parameters)
276 {
277  // no parameters
278  if (parameters.empty())
279  {
280  ParameterizedCommand::Pointer pCmd(new ParameterizedCommand(command, QList<Parameterization>()));
281  return pCmd;
282  }
283 
284  try
285  {
286  QList<Parameterization> parms;
287 
288  // iterate over given parameters
289  for (QHash<QString, Object::Pointer>::const_iterator i = parameters.begin();
290  i != parameters.end(); ++i)
291  {
292  QString key(i.key());
293 
294  // get the parameter from the command
295  IParameter::Pointer parameter(command->GetParameter(key));
296 
297  // if the parameter is defined add it to the parameter list
298  if (!parameter)
299  {
300  return ParameterizedCommand::Pointer(nullptr);
301  }
302  ParameterType::Pointer parameterType(command->GetParameterType(key));
303  if (!parameterType)
304  {
305  QString val = i.value()->ToString();
306  parms.push_back(Parameterization(parameter, val));
307  }
308  else
309  {
310  IParameterValueConverter* valueConverter(parameterType->GetValueConverter());
311  if (valueConverter)
312  {
313  QString val(valueConverter->ConvertToString(i.value()));
314  parms.push_back(Parameterization(parameter, val));
315  }
316  else
317  {
318  QString val = i.value()->ToString();
319  parms.push_back(Parameterization(parameter, val));
320  }
321  }
322  }
323 
324  // convert the parameters to an Parameterization array and create
325  // the command
326  ParameterizedCommand::Pointer pCmd(new ParameterizedCommand(command, parms));
327  return pCmd;
328  }
329  catch (const NotDefinedException* /*e*/)
330  {
331  }
332  catch (const ParameterValueConversionException* /*e*/)
333  {
334  }
335  return ParameterizedCommand::Pointer(nullptr);
336 }
337 
338 QString ParameterizedCommand::Escape(const QString& rawText)
339 {
340 
341  QString buffer;
342 
343  for (QString::const_iterator i = rawText.begin();
344  i != rawText.end(); ++i)
345  {
346 
347  QString::value_type c = *i;
353  {
354  buffer += CommandManager::ESCAPE_CHAR;
355  }
356 
357  buffer += c;
358  }
359 
360  if (buffer.isEmpty())
361  {
362  return rawText;
363  }
364  return buffer;
365 }
366 
367 QList<QList<Parameterization> > ParameterizedCommand::ExpandParameters(
368  unsigned int startIndex, const QList<IParameter::Pointer>& parameters)
369 {
370  typedef QList<QList<Parameterization> > ReturnType;
371 
372  const int nextIndex = startIndex + 1;
373  const bool noMoreParameters = (nextIndex >= parameters.size());
374 
375  const IParameter::Pointer parameter(parameters[startIndex]);
376  ReturnType parameterizations;
377 
378  if (parameter->IsOptional())
379  {
380  parameterizations.push_back(QList<Parameterization>());
381  }
382 
383  IParameterValues* values = nullptr;
384  try
385  {
386  values = parameter->GetValues();
387  }
388  catch (const ParameterValuesException& /*e*/)
389  {
390  if (noMoreParameters)
391  {
392  return parameterizations;
393  }
394 
395  // Make recursive call
396  return ExpandParameters(nextIndex, parameters);
397  }
398 
399  const QHash<QString,QString> parameterValues = values->GetParameterValues();
400  for (IParameter::ParameterValues::const_iterator parameterValueItr =
401  parameterValues.begin(); parameterValueItr != parameterValues.end(); ++parameterValueItr)
402  {
403  QList<Parameterization> combination;
404  combination.push_back(
405  Parameterization(parameter, parameterValueItr.value()));
406  parameterizations.push_back(combination);
407  }
408 
409  // Check if another iteration will produce any more names.
410  if (noMoreParameters)
411  {
412  // This is it, so just return the current parameterizations.
413  return parameterizations;
414  }
415 
416  // Make recursive call
417  ReturnType suffixes(ExpandParameters(nextIndex, parameters));
418  if (suffixes.empty())
419  {
420  // This is it, so just return the current parameterizations.
421  return parameterizations;
422  }
423 
424  ReturnType returnValue;
425  for (ReturnType::iterator suffixItr = suffixes.begin(); suffixItr
426  != suffixes.end(); ++suffixItr)
427  {
428  for (ReturnType::iterator combinationItr = parameterizations.begin(); combinationItr
429  != parameterizations.end(); ++combinationItr)
430  {
431  QList<Parameterization> newCombination(*combinationItr);
432  newCombination.append(*suffixItr);
433  returnValue.push_back(newCombination);
434  }
435  }
436 
437  return returnValue;
438 }
439 
440 }
static const char PARAMETER_START_CHAR
SmartPointer< Command > GetCommand() const
Light weight base class for most BlueBerry classes.
Definition: berryObject.h:72
static const char ESCAPE_CHAR
Implements transparent reference counting.
static ParameterizedCommand::Pointer GenerateCommand(const SmartPointer< Command > command, const QHash< QString, Object::Pointer > &parameters)
Object::Pointer ExecuteWithChecks(const Object::ConstPointer &trigger, const Object::Pointer &applicationContext)
virtual QHash< QString, QString > GetParameterValues() const =0
berry::SmartPointer< Self > Pointer
Definition: berryObject.h:82
QHash< QString, QString > GetParameterMap() const
SmartPointer< const IParameter > GetParameter() const
static const char PARAMETER_END_CHAR
ParameterizedCommand(const SmartPointer< Command > &command, const QList< Parameterization > &parameterizations)
static const char PARAMETER_SEPARATOR_CHAR
unsigned int uint
static const char ID_VALUE_CHAR
bool operator==(const Object *object) const override
static QList< ParameterizedCommand::Pointer > GenerateCombinations(const SmartPointer< Command > command)
bool operator<(const Object *object) const override
uint qHash(const berry::Object &o)