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