Medical Imaging Interaction Toolkit  2018.4.99-12ad79a3
Medical Imaging Interaction Toolkit
mitkCommandLineParser.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 /*=========================================================================
13 
14  Library: CTK
15 
16  Copyright (c) Kitware Inc.
17 
18  Licensed under the Apache License, Version 2.0 (the "License");
19  you may not use this file except in compliance with the License.
20  You may obtain a copy of the License at
21 
22  http://www.apache.org/licenses/LICENSE-2.0.txt
23 
24  Unless required by applicable law or agreed to in writing, software
25  distributed under the License is distributed on an "AS IS" BASIS,
26  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
27  See the License for the specific language governing permissions and
28  limitations under the License.
29 
30 =========================================================================*/
31 
32 // STL includes
33 #include <iostream>
34 #include <stdexcept>
35 
36 // MITK includes
37 #include "mitkCommandLineParser.h"
38 
39 using namespace std;
40 
41 namespace
42 {
43 // --------------------------------------------------------------------------
44 class CommandLineParserArgumentDescription
45 {
46 public:
47  CommandLineParserArgumentDescription(const string &longArg,
48  const string &longArgPrefix,
49  const string &shortArg,
50  const string &shortArgPrefix,
52  const string &argHelp,
53  const string &argLabel,
54  const us::Any &defaultValue,
55  bool ignoreRest,
56  bool deprecated,
57  bool optional,
59  string &argGroup,
60  string &groupDescription)
61  : LongArg(longArg),
62  LongArgPrefix(longArgPrefix),
63  ShortArg(shortArg),
64  ShortArgPrefix(shortArgPrefix),
65  ArgHelp(argHelp),
66  ArgLabel(argLabel),
67  ArgGroup(argGroup),
68  ArgGroupDescription(groupDescription),
69  IgnoreRest(ignoreRest),
70  NumberOfParametersToProcess(0),
71  Deprecated(deprecated),
72  Optional(optional),
73  Channel(channel),
74  DefaultValue(defaultValue),
75  Value(type),
76  ValueType(type)
77  {
78  Value = defaultValue;
79 
80  switch (type)
81  {
83  {
84  NumberOfParametersToProcess = 1;
85  }
86  break;
88  {
89  NumberOfParametersToProcess = 0;
90  }
91  break;
93  {
94  NumberOfParametersToProcess = -1;
95  }
96  break;
98  {
99  NumberOfParametersToProcess = 1;
100  }
101  break;
103  {
104  NumberOfParametersToProcess = 1;
105  }
106  break;
107 
109  {
110  NumberOfParametersToProcess = 1;
111  }
112  break;
113 
115  {
116  NumberOfParametersToProcess = 1;
117  }
118  break;
120  {
121  NumberOfParametersToProcess = 1;
122  }
123  break;
124 
125  default:
126  std::cout << "Type not supported: " << static_cast<int>(type);
127  }
128  }
129 
130  ~CommandLineParserArgumentDescription() {}
131  bool addParameter(const string &value);
132 
133  string helpText();
134 
135  string LongArg;
136  string LongArgPrefix;
137  string ShortArg;
138  string ShortArgPrefix;
139  string ArgHelp;
140  string ArgLabel;
141  string ArgGroup;
142  string ArgGroupDescription;
143  bool IgnoreRest;
144  int NumberOfParametersToProcess;
145  bool Deprecated;
146  bool Optional;
148 
149  us::Any DefaultValue;
150  us::Any Value;
152 };
153 
154 // --------------------------------------------------------------------------
155 bool CommandLineParserArgumentDescription::addParameter(const string &value)
156 {
157  switch (ValueType)
158  {
160  {
161  Value = value;
162  }
163  break;
165  {
166  if (value.compare("true") == 0)
167  Value = true;
168  else
169  Value = false;
170  }
171  break;
173  {
174  try
175  {
178  list.push_back(value);
179  Value = list;
180  }
181  catch (...)
182  {
184  list.push_back(value);
185  Value = list;
186  }
187  }
188  break;
190  {
191  stringstream ss(value);
192  int i;
193  ss >> i;
194  Value = i;
195  }
196  break;
198  {
199  stringstream ss(value);
200  float f;
201  ss >> f;
202  Value = f;
203  }
204  break;
205 
209  {
210  Value = value;
211  }
212  break;
213 
214  default:
215  return false;
216  }
217 
218  return true;
219 }
220 
221 // --------------------------------------------------------------------------
222 string CommandLineParserArgumentDescription::helpText()
223 {
224  string text;
225 
226  string shortAndLongArg;
227  if (!this->ShortArg.empty())
228  {
229  shortAndLongArg = " ";
230  shortAndLongArg += this->ShortArgPrefix;
231  shortAndLongArg += this->ShortArg;
232  }
233 
234  if (!this->LongArg.empty())
235  {
236  if (this->ShortArg.empty())
237  shortAndLongArg.append(" ");
238  else
239  shortAndLongArg.append(", ");
240 
241  shortAndLongArg += this->LongArgPrefix;
242  shortAndLongArg += this->LongArg;
243  }
244 
245  text = text + shortAndLongArg + ", " + this->ArgHelp;
246 
247  if (this->Optional)
248  text += " (optional)";
249 
250  if (!this->DefaultValue.Empty())
251  {
252  if (this->ValueType == 1)
253  {
254  if (this->DefaultValue.ToString() == "0")
255  text = text + ", (default: false)";
256  else
257  text = text + ", (default: true)";
258  }
259  else
260  text = text + ", (default: " + this->DefaultValue.ToString() + ")";
261  }
262  string value_type = "Unknown";
263  switch (this->ValueType)
264  {
265  case 0:
266  {
267  value_type = "String";
268  break;
269  }
270  case 1:
271  {
272  value_type = "Bool";
273  break;
274  }
275  case 2:
276  {
277  value_type = "StringList";
278  break;
279  }
280  case 3:
281  {
282  value_type = "Int";
283  break;
284  }
285  case 4:
286  {
287  value_type = "Float";
288  break;
289  }
290  case 5:
291  {
292  value_type = "Directory";
293  break;
294  }
295  case 6:
296  {
297  value_type = "File";
298  break;
299  }
300  case 7:
301  {
302  value_type = "Image";
303  }
304  }
305  text = text + ", Type: " + value_type;
306  if (this->Channel == mitkCommandLineParser::Input)
307  text = text + ", Channel: input";
308  else if (this->Channel == mitkCommandLineParser::Output)
309  text = text + ", Channel: output";
310  text += "\n";
311  return text;
312 }
313 }
314 
315 // --------------------------------------------------------------------------
316 // ctkCommandLineParser::ctkInternal class
317 
318 // --------------------------------------------------------------------------
319 class mitkCommandLineParser::ctkInternal
320 {
321 public:
322  ctkInternal() : Debug(false), FieldWidth(0), StrictMode(false) {}
323  ~ctkInternal() {}
324  CommandLineParserArgumentDescription *argumentDescription(const string &argument);
325 
326  vector<CommandLineParserArgumentDescription *> ArgumentDescriptionList;
327  map<string, CommandLineParserArgumentDescription *> ArgNameToArgumentDescriptionMap;
328  map<string, vector<CommandLineParserArgumentDescription *>> GroupToArgumentDescriptionListMap;
329 
330  StringContainerType UnparsedArguments;
331  StringContainerType ProcessedArguments;
332  string ErrorString;
333  bool Debug;
334  string::size_type FieldWidth;
335  string LongPrefix;
336  string ShortPrefix;
337  string CurrentGroup;
338  string DisableQSettingsLongArg;
339  string DisableQSettingsShortArg;
340  bool StrictMode;
341 };
342 
343 // --------------------------------------------------------------------------
344 // ctkCommandLineParser::ctkInternal methods
345 
346 // --------------------------------------------------------------------------
347 CommandLineParserArgumentDescription *mitkCommandLineParser::ctkInternal::argumentDescription(const string &argument)
348 {
349  string unprefixedArg = argument;
350 
351  if (!LongPrefix.empty() && argument.compare(0, LongPrefix.size(), LongPrefix) == 0)
352  {
353  // Case when (ShortPrefix + UnPrefixedArgument) matches LongPrefix
354  if (argument == LongPrefix && !ShortPrefix.empty() && argument.compare(0, ShortPrefix.size(), ShortPrefix) == 0)
355  {
356  unprefixedArg = argument.substr(ShortPrefix.size(), argument.size());
357  }
358  else
359  {
360  unprefixedArg = argument.substr(LongPrefix.size(), argument.size());
361  }
362  }
363  else if (!ShortPrefix.empty() && argument.compare(0, ShortPrefix.size(), ShortPrefix) == 0)
364  {
365  unprefixedArg = argument.substr(ShortPrefix.size(), argument.size());
366  }
367  else if (!LongPrefix.empty() && !ShortPrefix.empty())
368  {
369  return nullptr;
370  }
371 
372  if (ArgNameToArgumentDescriptionMap.count(unprefixedArg))
373  {
374  return this->ArgNameToArgumentDescriptionMap[unprefixedArg];
375  }
376  return nullptr;
377 }
378 
379 // --------------------------------------------------------------------------
380 // ctkCommandLineParser methods
381 
382 // --------------------------------------------------------------------------
384 {
385  this->Internal = new ctkInternal();
386  this->Category = string();
387  this->Title = string();
388  this->Contributor = string();
389  this->Description = string();
390  this->ParameterGroupName = "Parameters";
391  this->ParameterGroupDescription = "Parameters";
392 }
393 
394 // --------------------------------------------------------------------------
396 {
397  delete this->Internal;
398 }
399 
400 // --------------------------------------------------------------------------
401 map<string, us::Any> mitkCommandLineParser::parseArguments(const StringContainerType &arguments, bool *ok)
402 {
403  // Reset
404  this->Internal->UnparsedArguments.clear();
405  this->Internal->ProcessedArguments.clear();
406  this->Internal->ErrorString.clear();
407  // foreach (CommandLineParserArgumentDescription* desc, this->Internal->ArgumentDescriptionList)
408  for (unsigned int i = 0; i < Internal->ArgumentDescriptionList.size(); i++)
409  {
410  CommandLineParserArgumentDescription *desc = Internal->ArgumentDescriptionList.at(i);
411  desc->Value = us::Any(desc->ValueType);
412  if (!desc->DefaultValue.Empty())
413  {
414  desc->Value = desc->DefaultValue;
415  }
416  }
417  bool error = false;
418  bool ignoreRest = false;
419  CommandLineParserArgumentDescription *currentArgDesc = nullptr;
420  vector<CommandLineParserArgumentDescription *> parsedArgDescriptions;
421  for (unsigned int i = 1; i < arguments.size(); ++i)
422  {
423  string argument = arguments.at(i);
424 
425  if (this->Internal->Debug)
426  {
427  std::cout << "Processing" << argument;
428  }
429  if (!argument.compare("--version"))
430  {
431  std::cout << "Git commit hash: " << MITK_REVISION << std::endl;
432  std::cout << "Git branch name: " << MITK_REVISION_NAME << "\n" << std::endl;
433  }
434 
435  if (!argument.compare("--xml") || !argument.compare("-xml") || !argument.compare("--XML") ||
436  !argument.compare("-XML"))
437  {
438  this->generateXmlOutput();
439  return map<string, us::Any>();
440  }
441 
442  // should argument be ignored ?
443  if (ignoreRest)
444  {
445  if (this->Internal->Debug)
446  {
447  std::cout << " Skipping: IgnoreRest flag was been set";
448  }
449  this->Internal->UnparsedArguments.push_back(argument);
450  continue;
451  }
452 
453  // Skip if the argument does not start with the defined prefix
454  if (!(argument.compare(0, Internal->LongPrefix.size(), Internal->LongPrefix) == 0 ||
455  argument.compare(0, Internal->ShortPrefix.size(), Internal->ShortPrefix) == 0))
456  {
457  if (this->Internal->StrictMode)
458  {
459  this->Internal->ErrorString = "Unknown argument ";
460  this->Internal->ErrorString += argument;
461  error = true;
462  break;
463  }
464  if (this->Internal->Debug)
465  {
466  std::cout << " Skipping: It does not start with the defined prefix";
467  }
468  this->Internal->UnparsedArguments.push_back(argument);
469  continue;
470  }
471 
472  // Skip if argument has already been parsed ...
473  bool alreadyProcessed = false;
474  for (auto alreadyHandledArgument : Internal->ProcessedArguments)
475  if (argument.compare(alreadyHandledArgument) == 0)
476  {
477  alreadyProcessed = true;
478  break;
479  }
480 
481  if (alreadyProcessed)
482  {
483  if (this->Internal->StrictMode)
484  {
485  this->Internal->ErrorString = "Argument ";
486  this->Internal->ErrorString += argument;
487  this->Internal->ErrorString += " already processed !";
488  error = true;
489  break;
490  }
491  if (this->Internal->Debug)
492  {
493  std::cout << " Skipping: Already processed !";
494  }
495  continue;
496  }
497 
498  // Retrieve corresponding argument description
499  currentArgDesc = this->Internal->argumentDescription(argument);
500 
501  // Is there a corresponding argument description ?
502  if (currentArgDesc)
503  {
504  // If the argument is deprecated, print the help text but continue processing
505  if (currentArgDesc->Deprecated)
506  {
507  std::cout << "Deprecated argument " << argument << ": " << currentArgDesc->ArgHelp;
508  }
509  else
510  {
511  parsedArgDescriptions.push_back(currentArgDesc);
512  }
513 
514  this->Internal->ProcessedArguments.push_back(currentArgDesc->ShortArg);
515  this->Internal->ProcessedArguments.push_back(currentArgDesc->LongArg);
516  int numberOfParametersToProcess = currentArgDesc->NumberOfParametersToProcess;
517  ignoreRest = currentArgDesc->IgnoreRest;
518  if (this->Internal->Debug && ignoreRest)
519  {
520  std::cout << " IgnoreRest flag is True";
521  }
522 
523  // Is the number of parameters associated with the argument being processed known ?
524  if (numberOfParametersToProcess == 0)
525  {
526  currentArgDesc->addParameter("true");
527  }
528  else if (numberOfParametersToProcess > 0)
529  {
530  string missingParameterError = "Argument %1 has %2 value(s) associated whereas exacly %3 are expected.";
531  for (int j = 1; j <= numberOfParametersToProcess; ++j)
532  {
533  if (i + j >= arguments.size())
534  {
535  // this->Internal->ErrorString =
536  // missingParameterError.arg(argument).arg(j-1).arg(numberOfParametersToProcess);
537  // if (this->Internal->Debug) { std::cout << this->Internal->ErrorString; }
538  if (ok)
539  {
540  *ok = false;
541  }
542  return map<string, us::Any>();
543  }
544  string parameter = arguments.at(i + j);
545  if (this->Internal->Debug)
546  {
547  std::cout << " Processing parameter" << j << ", value:" << parameter;
548  }
549  if (this->argumentAdded(parameter))
550  {
551  // this->Internal->ErrorString =
552  // missingParameterError.arg(argument).arg(j-1).arg(numberOfParametersToProcess);
553  // if (this->Internal->Debug) { std::cout << this->Internal->ErrorString; }
554  if (ok)
555  {
556  *ok = false;
557  }
558  return map<string, us::Any>();
559  }
560  if (!currentArgDesc->addParameter(parameter))
561  {
562  // this->Internal->ErrorString = string(
563  // "Value(s) associated with argument %1 are incorrect. %2").
564  // arg(argument).arg(currentArgDesc->ExactMatchFailedMessage);
565  // if (this->Internal->Debug) { std::cout << this->Internal->ErrorString; }
566  if (ok)
567  {
568  *ok = false;
569  }
570  return map<string, us::Any>();
571  }
572  }
573  // Update main loop increment
574  i = i + numberOfParametersToProcess;
575  }
576  else if (numberOfParametersToProcess == -1)
577  {
578  if (this->Internal->Debug)
579  {
580  std::cout << " Proccessing StringList ...";
581  }
582  int j = 1;
583  while (j + i < arguments.size())
584  {
585  if (this->argumentAdded(arguments.at(j + i)))
586  {
587  if (this->Internal->Debug)
588  {
589  std::cout << " No more parameter for" << argument;
590  }
591  break;
592  }
593  string parameter = arguments.at(j + i);
594 
595  if (parameter.compare(0, Internal->LongPrefix.size(), Internal->LongPrefix) == 0 ||
596  parameter.compare(0, Internal->ShortPrefix.size(), Internal->ShortPrefix) == 0)
597  {
598  j--;
599  break;
600  }
601 
602  if (this->Internal->Debug)
603  {
604  std::cout << " Processing parameter" << j << ", value:" << parameter;
605  }
606  if (!currentArgDesc->addParameter(parameter))
607  {
608  // this->Internal->ErrorString = string(
609  // "Value(s) associated with argument %1 are incorrect. %2").
610  // arg(argument).arg(currentArgDesc->ExactMatchFailedMessage);
611  // if (this->Internal->Debug) { std::cout << this->Internal->ErrorString; }
612  if (ok)
613  {
614  *ok = false;
615  }
616  return map<string, us::Any>();
617  }
618  j++;
619  }
620  // Update main loop increment
621  i = i + j;
622  }
623  }
624  else
625  {
626  if (this->Internal->StrictMode)
627  {
628  this->Internal->ErrorString = "Unknown argument ";
629  this->Internal->ErrorString += argument;
630  error = true;
631  break;
632  }
633  if (this->Internal->Debug)
634  {
635  std::cout << " Skipping: Unknown argument";
636  }
637  this->Internal->UnparsedArguments.push_back(argument);
638  }
639  }
640 
641  if (ok)
642  {
643  *ok = !error;
644  }
645 
646  map<string, us::Any> parsedArguments;
647 
648  int obligatoryArgs = 0;
649  vector<CommandLineParserArgumentDescription *>::iterator it;
650  for (it = Internal->ArgumentDescriptionList.begin(); it != Internal->ArgumentDescriptionList.end(); ++it)
651  {
652  CommandLineParserArgumentDescription *desc = *it;
653 
654  if (!desc->Optional)
655  obligatoryArgs++;
656  }
657 
658  int parsedObligatoryArgs = 0;
659  for (it = parsedArgDescriptions.begin(); it != parsedArgDescriptions.end(); ++it)
660  {
661  CommandLineParserArgumentDescription *desc = *it;
662 
663  string key;
664  if (!desc->LongArg.empty())
665  {
666  key = desc->LongArg;
667  }
668  else
669  {
670  key = desc->ShortArg;
671  }
672 
673  if (!desc->Optional)
674  parsedObligatoryArgs++;
675 
676  std::pair<string, us::Any> elem;
677  elem.first = key;
678  elem.second = desc->Value;
679  parsedArguments.insert(elem);
680  }
681 
682  if (obligatoryArgs > parsedObligatoryArgs)
683  {
684  parsedArguments.clear();
685  cout << helpText();
686  }
687 
688  return parsedArguments;
689 }
690 
691 // -------------------------------------------------------------------------
692 map<string, us::Any> mitkCommandLineParser::parseArguments(int argc, char **argv, bool *ok)
693 {
694  std::cout << "Running Command Line Utility *" << Title << "*" << std::endl;
695  StringContainerType arguments;
696 
697  // Create a StringContainerType of arguments
698  for (int i = 0; i < argc; ++i)
699  arguments.push_back(argv[i]);
700 
701  return this->parseArguments(arguments, ok);
702 }
703 
704 // -------------------------------------------------------------------------
706 {
707  return this->Internal->ErrorString;
708 }
709 
710 // -------------------------------------------------------------------------
712 {
713  return this->Internal->UnparsedArguments;
714 }
715 
716 // --------------------------------------------------------------------------
717 void mitkCommandLineParser::addArgument(const string &longarg,
718  const string &shortarg,
719  Type type,
720  const string &argLabel,
721  const string &argHelp,
722  const us::Any &defaultValue,
723  bool optional,
724  bool ignoreRest,
725  bool deprecated,
727 {
728  if (longarg.empty() && shortarg.empty())
729  {
730  return;
731  }
732 
733  /* Make sure it's not already added */
734  bool added = (this->Internal->ArgNameToArgumentDescriptionMap.count(longarg) != 0);
735  if (added)
736  {
737  return;
738  }
739 
740  added = (this->Internal->ArgNameToArgumentDescriptionMap.count(shortarg) != 0);
741  if (added)
742  {
743  return;
744  }
745 
746  auto argDesc = new CommandLineParserArgumentDescription(longarg,
747  this->Internal->LongPrefix,
748  shortarg,
749  this->Internal->ShortPrefix,
750  type,
751  argHelp,
752  argLabel,
753  defaultValue,
754  ignoreRest,
755  deprecated,
756  optional,
757  channel,
758  ParameterGroupName,
759  ParameterGroupDescription);
760 
761  std::string::size_type argWidth = 0;
762  if (!longarg.empty())
763  {
764  this->Internal->ArgNameToArgumentDescriptionMap[longarg] = argDesc;
765  argWidth += longarg.size() + this->Internal->LongPrefix.size();
766  }
767  if (!shortarg.empty())
768  {
769  this->Internal->ArgNameToArgumentDescriptionMap[shortarg] = argDesc;
770  argWidth += shortarg.size() + this->Internal->ShortPrefix.size() + 2;
771  }
772  argWidth += 5;
773 
774  // Set the field width for the arguments
775  if (argWidth > this->Internal->FieldWidth)
776  {
777  this->Internal->FieldWidth = argWidth;
778  }
779 
780  this->Internal->ArgumentDescriptionList.push_back(argDesc);
781  this->Internal->GroupToArgumentDescriptionListMap[this->Internal->CurrentGroup].push_back(argDesc);
782 }
783 
784 // --------------------------------------------------------------------------
786  const string &shortarg,
787  const string &argLabel,
788  const string &argHelp)
789 {
790  addArgument(longarg, shortarg, StringList, argLabel, argHelp, us::Any(), false, true, false);
791 }
792 
793 // --------------------------------------------------------------------------
794 std::vector < std::map<std::string, us::Any> > mitkCommandLineParser::getArgumentList()
795 {
796  std::vector < std::map<std::string, us::Any> > parameterList;
797  //for (CommandLineParserArgumentDescription* argument : this->Internal->ArgumentDescriptionList)
798  for (std::size_t i = 0; i< this->Internal->ArgumentDescriptionList.size(); ++i)
799  {
800  CommandLineParserArgumentDescription* argument = this->Internal->ArgumentDescriptionList[i];
801  std::map<std::string, us::Any> tmpMap;
802  //tmpMap["helptext"] = us::Any(argument->helpText);
803  tmpMap["longarg"] = us::Any(argument->LongArg);
804  tmpMap["longargprefix"] = us::Any(argument->LongArgPrefix);
805  tmpMap["shortarg"] = us::Any(argument->ShortArg);
806  tmpMap["shortargprefix"] = us::Any(argument->ShortArgPrefix);
807  tmpMap["arghelp"] = us::Any(argument->ArgHelp);
808  tmpMap["arglabel"] = us::Any(argument->ArgLabel);
809  tmpMap["arggroup"] = us::Any(argument->ArgGroup);
810  tmpMap["arggroupdescription"] = us::Any(argument->ArgGroupDescription);
811  tmpMap["ignorerest"] = us::Any(argument->IgnoreRest);
812  tmpMap["numberofparameterstoprocess"] = us::Any(argument->NumberOfParametersToProcess);
813  tmpMap["deprecated"] = us::Any(argument->Deprecated);
814  tmpMap["optional"] = us::Any(argument->Optional);
815  tmpMap["defaultvalue"] = argument->DefaultValue;
816  tmpMap["value"] = argument->Value;
817  tmpMap["valuetype"] = us::Any(argument->ValueType);
818  tmpMap["channel"] = us::Any(argument->Channel);
819  parameterList.push_back(tmpMap);
820  }
821  return parameterList;
822 }
823 
824 // --------------------------------------------------------------------------
825 std::string::size_type mitkCommandLineParser::fieldWidth() const
826 {
827  return this->Internal->FieldWidth;
828 }
829 
830 // --------------------------------------------------------------------------
831 void mitkCommandLineParser::beginGroup(const string &description)
832 {
833  this->Internal->CurrentGroup = description;
834 }
835 
836 // --------------------------------------------------------------------------
838 {
839  this->Internal->CurrentGroup.clear();
840 }
841 
842 // --------------------------------------------------------------------------
844 {
845  string text;
846  vector<CommandLineParserArgumentDescription *> deprecatedArgs;
847 
848  text = "Command Line Utility *" + Title + "* in Category *" + Category + "*\n";
849  text += Description + "\n";
850  text += Contributor + "\n\n";
851  text += "Use --xml to generate an XML description parsable as a CTK Command Line Module Plugin.\n";
852  text += "Use --version to print MITK revision information.\n";
853 
854  // Loop over grouped argument descriptions
855  map<string, vector<CommandLineParserArgumentDescription *>>::iterator it;
856  for (it = Internal->GroupToArgumentDescriptionListMap.begin();
857  it != Internal->GroupToArgumentDescriptionListMap.end();
858  ++it)
859  {
860  if (!(*it).first.empty())
861  {
862  text = text + "\n" + (*it).first + "\n";
863  }
864 
865  vector<CommandLineParserArgumentDescription *>::iterator it2;
866  for (it2 = (*it).second.begin(); it2 != (*it).second.end(); ++it2)
867  {
868  CommandLineParserArgumentDescription *argDesc = *it2;
869  if (argDesc->Deprecated)
870  {
871  deprecatedArgs.push_back(argDesc);
872  }
873  else
874  {
875  text += argDesc->helpText();
876  }
877  }
878  }
879 
880  if (!deprecatedArgs.empty())
881  {
882  text += "\nDeprecated arguments:\n";
883  vector<CommandLineParserArgumentDescription *>::iterator it2;
884  for (it2 = deprecatedArgs.begin(); it2 != deprecatedArgs.end(); ++it2)
885  {
886  CommandLineParserArgumentDescription *argDesc = *it2;
887  text += argDesc->helpText();
888  }
889  }
890 
891  return text;
892 }
893 
894 // --------------------------------------------------------------------------
895 bool mitkCommandLineParser::argumentAdded(const string &argument) const
896 {
897  return (this->Internal->ArgNameToArgumentDescriptionMap.count(argument) != 0);
898 }
899 
900 // --------------------------------------------------------------------------
901 bool mitkCommandLineParser::argumentParsed(const string &argument) const
902 {
903  for (unsigned int i = 0; i < Internal->ProcessedArguments.size(); i++)
904  if (argument.compare(Internal->ProcessedArguments.at(i)) == 0)
905  return true;
906  return false;
907 }
908 
909 // --------------------------------------------------------------------------
910 void mitkCommandLineParser::setArgumentPrefix(const string &longPrefix, const string &shortPrefix)
911 {
912  this->Internal->LongPrefix = longPrefix;
913  this->Internal->ShortPrefix = shortPrefix;
914 }
915 
916 // --------------------------------------------------------------------------
918 {
919  this->Internal->StrictMode = strictMode;
920 }
921 
922 
924 {
925  std::stringstream xml;
926 
927  xml << "<executable>" << endl;
928  xml << "<category>" << Category << "</category>" << endl;
929  xml << "<title>" << Title << "</title>" << endl;
930  xml << "<description>" << Description << "</description>" << endl;
931  xml << "<contributor>" << Contributor << "</contributor>" << endl;
932  xml << "<parameters>" << endl;
933 
934  std::vector<CommandLineParserArgumentDescription *>::iterator it;
935 
936  std::string lastParameterGroup = "";
937  for (it = this->Internal->ArgumentDescriptionList.begin(); it != this->Internal->ArgumentDescriptionList.end(); it++)
938  {
939  std::string type;
940  switch ((*it)->ValueType)
941  {
943  type = "string";
944  break;
945 
947  type = "boolean";
948  break;
949 
951  type = "string-vector";
952  break;
953 
955  type = "integer";
956  break;
957 
959  type = "float";
960  break;
961 
963  type = "directory";
964  break;
965 
967  type = "image";
968  break;
969 
971  type = "file";
972  break;
973  }
974 
975  if (lastParameterGroup.compare((*it)->ArgGroup))
976  {
977  if (it != this->Internal->ArgumentDescriptionList.begin())
978  {
979  xml << "</parameters>" << endl;
980  xml << "<parameters>" << endl;
981  }
982  xml << "<label>" << (*it)->ArgGroup << "</label>" << endl;
983  xml << "<description>" << (*it)->ArgGroupDescription << "</description>" << endl;
984  lastParameterGroup = (*it)->ArgGroup;
985  }
986 
987  // Skip help item, as it's no use in GUI
988  if ((*it)->ShortArg == "h")
989  continue;
990 
991  auto name = (*it)->LongArg;
992  if (name.empty())
993  name = (*it)->ShortArg;
994 
995  xml << "<" << type << ">" << endl;
996  xml << "<name>" << name << "</name>" << endl;
997  xml << "<description>" << (*it)->ArgHelp << "</description>" << endl;
998  xml << "<label>" << (*it)->ArgLabel << "</label>" << endl;
999  if (!(*it)->DefaultValue.Empty())
1000  xml << "<default>" << (*it)->DefaultValue.ToString() << "</default>" << endl;
1001 
1002  xml << "<longflag>" << (*it)->LongArg << "</longflag>" << endl;
1003  xml << "<flag>" << (*it)->ShortArg << "</flag>" << endl;
1004 
1005  if (((*it)->ValueType == mitkCommandLineParser::File ||
1006  (*it)->ValueType == mitkCommandLineParser::Directory ||
1007  (*it)->ValueType == mitkCommandLineParser::Image) &&
1008  (*it)->Channel == mitkCommandLineParser::Channel::Input)
1009  {
1010  xml << "<channel>input</channel>" << endl;
1011  }
1012  else if (((*it)->ValueType == mitkCommandLineParser::File ||
1013  (*it)->ValueType == mitkCommandLineParser::Directory ||
1014  (*it)->ValueType == mitkCommandLineParser::Image) &&
1015  (*it)->Channel == mitkCommandLineParser::Channel::Output)
1016  {
1017  xml << "<channel>output</channel>" << endl;
1018  }
1019  else if ((*it)->Channel == mitkCommandLineParser::Channel::Output ||
1020  (*it)->Channel == mitkCommandLineParser::Channel::Input)
1021  {
1022  std::cout << "Only the types Directory, File or Image may be flagged as Input or Output! Ignoring flag for parameter " + name << std::endl;
1023  }
1024  xml << "</" << type << ">" << endl;
1025  }
1026 
1027  xml << "</parameters>" << endl;
1028  xml << "</executable>" << endl;
1029 
1030  cout << xml.str();
1031 }
1032 
1034 {
1035  Title = title;
1036 }
1038 {
1039  Contributor = contributor;
1040 }
1041 
1043 {
1044  Category = category;
1045 }
1046 
1048 {
1049  Description = description;
1050 }
1051 
1052 void mitkCommandLineParser::changeParameterGroup(string name, string tooltip)
1053 {
1054  ParameterGroupName = name;
1055  ParameterGroupDescription = tooltip;
1056 }
void changeParameterGroup(std::string name, std::string tooltip)
#define MITK_REVISION_NAME
Definition: mitkVersion.h:12
void setStrictModeEnabled(bool strictMode)
void setContributor(std::string contributor)
bool argumentAdded(const std::string &argument) const
std::vector< std::map< std::string, us::Any > > getArgumentList()
STL namespace.
ValueType * any_cast(Any *operand)
Definition: usAny.h:377
std::string errorString() const
void addArgument(const std::string &longarg, const std::string &shortarg, Type type, const std::string &argLabel, const std::string &argHelp=std::string(), const us::Any &defaultValue=us::Any(), bool optional=true, bool ignoreRest=false, bool deprecated=false, mitkCommandLineParser::Channel channel=mitkCommandLineParser::Channel::None)
std::map< std::string, us::Any > parseArguments(const StringContainerType &arguments, bool *ok=nullptr)
ValueType
Type of the value held by a Value object.
Definition: jsoncpp.h:345
Definition: usAny.h:163
#define MITK_REVISION
Definition: mitkVersion.h:11
std::string helpText() const
void setCategory(std::string category)
std::vector< std::string > StringList
const StringContainerType & unparsedArguments() const
void setArgumentPrefix(const std::string &longPrefix, const std::string &shortPrefix)
void addDeprecatedArgument(const std::string &longarg, const std::string &shortarg, const std::string &argLabel, const std::string &argHelp)
bool argumentParsed(const std::string &argument) const
std::vector< std::string > StringContainerType
std::string::size_type fieldWidth() const
void setTitle(std::string title)
void setDescription(std::string description)
void beginGroup(const std::string &description)