MarlinMT  0.1.0
XMLConfigReader.cc
Go to the documentation of this file.
1 
2 // -- marlinmt headers
4 #include <marlinmt/Exceptions.h>
6 #include <marlinmt/Utils.h>
7 
8 // -- std headers
9 #include <algorithm>
10 #include <locale>
11 #include <sstream>
12 #include <set>
13 #include <memory>
14 #include <thread>
15 #include <filesystem>
16 
17 // -- tinyxml headers
18 #include <tinyxml.h>
19 
20 namespace marlinmt {
21 
26  class XMLConfigReader : public ConfigReader {
27  public:
28  // from ConfigReader
29  void init( const std::string &desc ) override ;
30  void read( Configuration &cfg ) override ;
31 
32  private:
42  void parseSection( TiXmlElement *parentElement, const std::string &name, Configuration &cfg, bool addAttributes, bool throwIfNotFound ) const ;
43 
50  void parseExecuteSection( TiXmlElement *parentElement, Configuration &cfg ) const ;
51 
58  void resolveGroupSections( TiXmlElement *rootElement ) const ;
59 
68  void parseProcessorParameters( TiXmlElement* parent, Configuration &cfg ) const ;
69 
77  std::string getAttribute( const TiXmlElement* element, const std::string& name ) const ;
78 
86  void parseConstants( TiXmlDocument *idoc, Configuration &cfg ) const ;
87 
94  void parseConstant( TiXmlElement *element, Configuration &cfg ) const ;
95 
103  void processIncludeElements( TiXmlElement* element, const Configuration &cfg ) const ;
104 
114  void processIncludeElement( TiXmlElement* element , const Configuration &cfg , TiXmlDocument &document ) const ;
115 
122  void checkForNestedIncludes( const TiXmlNode *node ) const ;
123 
142  void parametersFromXMLElement( const TiXmlElement *element, const Configuration &cfg, ConfigSection &section, bool addAttributes, const std::string &replacePrefix = "" ) const ;
143 
150  void processConditions( TiXmlNode* current, const std::string &aCondition ) const ;
151 
158  void replaceGroups( TiXmlNode* processorsParent, TiXmlNode* section ) const ;
159 
176  TiXmlNode *findElement( TiXmlNode* node, const std::string& tag, const std::string& attribute, const std::string& value ) const ;
177 
178  std::optional<std::string> getReplacementParameter( const std::string &arg, const Configuration &config ) const ;
179 
180  private:
182  std::string _fname {} ;
183  };
184 
185  //--------------------------------------------------------------------------
186  //--------------------------------------------------------------------------
187 
188  void XMLConfigReader::init( const std::string &desc ) {
189  _fname = desc ;
190  }
191 
192  //--------------------------------------------------------------------------
193 
195  // create and parse the XML document
196  auto document = std::make_unique<TiXmlDocument>() ;
197  bool loadOkay = document->LoadFile( _fname ) ;
198  if( !loadOkay ) {
199  std::stringstream str ;
200  str << "Parse error in file [" << _fname
201  << ", row: " << document->ErrorRow() << ", col: " << document->ErrorCol() << "] : "
202  << document->ErrorDesc() ;
203 
204  MARLINMT_THROW_T( ParseException, str.str() ) ;
205  }
206  auto rootElement = document->RootElement() ;
207  if( nullptr == rootElement || rootElement->ValueStr() != "marlinmt" ) {
208  MARLINMT_THROW_T( ParseException, "No root tag <marlinmt>...</marlinmt> found in " + _fname ) ;
209  }
210  // parse constants
211  parseConstants( document.get(), cfg ) ;
212  // resolve <include> elements
213  processIncludeElements( rootElement, cfg ) ;
214 
215  // parseSection( parentElement, section, cfg, addAttributes, throwIfNotFound ) ;
216  // parse geometry section
217  parseSection(rootElement, "geometry", cfg, true, true) ;
218  // parse bookstore section
219  parseSection(rootElement, "bookstore", cfg, true, false) ;
220  // parse scheduler section
221  parseSection(rootElement, "scheduler", cfg, true, false) ;
222  // parse data source section
223  parseSection(rootElement, "datasource", cfg, true, true) ;
224  // parse logging section
225  parseSection(rootElement, "logging", cfg, true, false) ;
226  // parse global section
227  parseSection(rootElement, "global", cfg, true, false) ;
228 
229  // parse the execute section: groups, conditions and active processors
230  parseExecuteSection( rootElement, cfg ) ;
231  // resolve groups sections in the root XML element
232  // simply copy all group parameters to the processors
233  // and then copy the processors to the root node <marlinmt>
234  // 'section' comes from above as first execute child, get the next section so we
235  // do not cleanup the execute section in loop body below, only the groups
236  resolveGroupSections( rootElement ) ;
237 
238  // parse all <processor> elements
239  parseProcessorParameters( rootElement, cfg ) ;
240  }
241 
242  //--------------------------------------------------------------------------
243 
244  void XMLConfigReader::parseSection( TiXmlElement *parentElement, const std::string &name, Configuration &cfg, bool addAttributes, bool throwIfNotFound ) const {
245  auto sectionElement = parentElement->FirstChildElement( name ) ;
246  if( nullptr == sectionElement ) {
247  if( throwIfNotFound ) {
248  MARLINMT_THROW_T( ParseException, "Missing <" + name + "> section in " + _fname ) ;
249  }
250  }
251  else {
252  auto &section = cfg.createSection( name ) ;
253  parametersFromXMLElement( sectionElement, cfg, section, addAttributes, name ) ;
254  }
255  }
256 
257  //--------------------------------------------------------------------------
258 
259  void XMLConfigReader::parseExecuteSection( TiXmlElement *parentElement, Configuration &cfg ) const {
260  try {
261  // parse execute section
262  auto executeElement = parentElement->FirstChildElement("execute") ;
263  if( nullptr == executeElement ) {
264  MARLINMT_THROW_T( ParseException, "Missing <execute> section in " + _fname ) ;
265  }
266  replaceGroups( parentElement, executeElement ) ;
267  processConditions( executeElement, "" ) ;
268  TiXmlNode* proc = 0 ;
269  std::set<std::string> processorDuplicates {} ;
270  std::vector<std::string> processorConditions {}, processorNames {} ;
271  // create a section and subsections for storing the scheduling conditions
272  auto &executeSection = cfg.createSection("execute") ;
273  while( ( proc = executeElement->IterateChildren( "processor", proc ) ) != 0 ) {
274  std::string processorName( getAttribute( proc->ToElement(), "name") ) ;
275  cfg.replaceConstants( processorName ) ;
276  auto inserted = processorDuplicates.insert( processorName ) ;
277  if( 1 != inserted.second ) {
278  MARLINMT_THROW_T( ParseException, "Processor " + processorName + " defined more than once in <execute> section" ) ;
279  }
280  processorNames.push_back( processorName ) ;
281  std::string condition ;
282  auto conditionReplace = getReplacementParameter( "execute." + processorName, cfg ) ;
283  if( conditionReplace.has_value() ) {
284  condition = conditionReplace.value() ;
285  }
286  else {
287  condition = getAttribute( proc->ToElement(), "condition") ;
288  }
289  cfg.replaceConstants( condition ) ;
290  if( condition.empty() ) {
291  condition = "true" ;
292  }
293  processorConditions.push_back( condition ) ;
294  }
295  for( std::size_t i=0 ; i<processorNames.size() ; i++ ) {
296  executeSection.setParameter( processorNames[i], processorConditions[i] ) ;
297  }
298  }
299  catch(Exception &e) {
300  MARLINMT_RETHROW( e, "Couldn't parse execute section" ) ;
301  }
302  }
303 
304  //--------------------------------------------------------------------------
305 
306  void XMLConfigReader::resolveGroupSections( TiXmlElement *rootElement ) const {
307  TiXmlNode *section = nullptr ;
308  TiXmlNode* nextSection = rootElement->IterateChildren("group", section) ;
309  while((section = nextSection) != 0) {
310  nextSection = rootElement->IterateChildren("group", section);
311  std::vector<TiXmlNode*> groupParams ;
312  TiXmlNode* param = 0 ;
313  while( ( param = section->IterateChildren( "parameter" , param ) ) != 0 ) {
314  groupParams.push_back( param->Clone() ) ;
315  }
316  TiXmlNode* proc = 0 ;
317  while( ( proc = section->IterateChildren( "processor" , proc ) ) != 0 ) {
318  for( std::vector<TiXmlNode*>::iterator it = groupParams.begin() ; it != groupParams.end() ; it++){
319  proc->InsertEndChild( **it ) ;
320  }
321  std::shared_ptr<TiXmlNode> clone( proc->Clone() ) ;
322  rootElement->InsertBeforeChild( section , *clone ) ; // FIXME: memory mngmt. ?
323  }
324  rootElement->RemoveChild( section ) ;
325  for( std::vector<TiXmlNode*>::iterator it = groupParams.begin() ; it != groupParams.end() ; it++) {
326  delete *it ;
327  }
328  }
329  }
330 
331  //--------------------------------------------------------------------------
332 
333  void XMLConfigReader::parseProcessorParameters( TiXmlElement* parent, Configuration &cfg ) const {
334  std::vector<std::string> availableProcs ;
335  TiXmlNode *section = nullptr ;
336  auto &parentSection = cfg.createSection( "processors" ) ;
337  while( (section = parent->IterateChildren("processor", section ) ) != 0 ) {
338  // get processor name and create a new config section
339  std::string name = getAttribute( section->ToElement(), "name") ;
340  try {
341  // create the section in the configuration
342  auto &procSection = parentSection.addSection( name ) ;
343  // parse parameters from XML element. Also copy attributes
344  parametersFromXMLElement( section->ToElement(), cfg, procSection, true, name ) ;
345  availableProcs.push_back( name ) ;
346  }
347  catch( marlinmt::Exception &e ) {
348  MARLINMT_RETHROW_T( ParseException, e, "Duplicated processor section: " + name ) ;
349  }
350  }
351  if( availableProcs.empty() ) {
352  MARLINMT_THROW_T( ParseException, "No <processor> section found in root section <marlinmt>" ) ;
353  }
354  }
355 
356  //--------------------------------------------------------------------------
357 
358  std::string XMLConfigReader::getAttribute( const TiXmlElement* element , const std::string& name ) const {
359  const char* attr = element->Attribute( name.c_str() ) ;
360  if( nullptr == attr ) {
361  MARLINMT_THROW_T( ParseException, "Missing attribute '" + name + "' in element <" + element->ValueStr() + "> in file " + _fname ) ;
362  }
363  return attr ;
364  }
365 
366  //--------------------------------------------------------------------------
367 
368  void XMLConfigReader::parseConstants( TiXmlDocument *idoc, Configuration &cfg ) const {
369  TiXmlElement *constantsElement = idoc->RootElement()->FirstChildElement("constants") ;
370  if( nullptr == constantsElement ) {
371  return ;
372  }
373  TiXmlElement *previous(nullptr), *child(nullptr) ;
374  while(1) {
375  if( nullptr == child ) {
376  child = constantsElement->FirstChildElement() ;
377  }
378  else {
379  child = child->NextSiblingElement() ;
380  }
381  if( nullptr == child ) {
382  break ;
383  }
384  if( child->ValueStr() == "constant" ) {
385  // process single constant
386  parseConstant( child , cfg ) ;
387  }
388  // need to process includes in constants section since some
389  // constants may be defined in includes and could then be
390  // used in next constant values
391  else if ( child->ValueStr() == "include" ) {
392  // process the include and returns the first and last elements found in the include
393  TiXmlDocument document ;
394  processIncludeElement( child , cfg , document ) ;
395  // add them to the xml tree
396  TiXmlNode *includeAfter( child ) ;
397  for( TiXmlElement *elt = document.FirstChildElement() ; elt ; elt = elt->NextSiblingElement() ) {
398  if ( elt->ValueStr() == "constant" ) {
399  includeAfter = constantsElement->InsertAfterChild( includeAfter, *elt ) ;
400  }
401  }
402  constantsElement->RemoveChild(child) ;
403  child = previous ;
404  }
405  previous = child ;
406  }
407  }
408 
409  //--------------------------------------------------------------------------
410 
411  void XMLConfigReader::parseConstant( TiXmlElement* element, Configuration &cfg ) const {
412  try {
413  // parse constant name
414  std::string name = getAttribute( element, "name" ) ;
415  // parse constant value
416  std::string value ;
417  if( element->Attribute("value") ) {
418  value = element->Attribute("value") ;
419  }
420  else {
421  if( element->FirstChild() ) {
422  value = element->FirstChild()->ValueStr() ;
423  }
424  }
425  // check if we have a replacement constant
426  auto replValue = getReplacementParameter( "constant." + name, cfg ) ;
427  if( replValue.has_value() ) {
428  // TODO missing handling of non-existing cmd line parameters
429  value = replValue.value() ;
430  }
431  cfg.replaceConstants( value ) ;
432  cfg.addConstant( name , value ) ;
433  }
434  catch(Exception &e) {
435  MARLINMT_RETHROW( e, "Couldn't parse constant XML element" ) ;
436  }
437  }
438 
439  //--------------------------------------------------------------------------
440 
441  void XMLConfigReader::processIncludeElements( TiXmlElement* element, const Configuration &cfg ) const {
442  TiXmlElement* child = element->FirstChildElement() ;
443  while( 1 ) {
444  if( nullptr == child ) {
445  break ;
446  }
447  // constants already processed a step before
448  if( child->ValueStr() == "constants" ) {
449  child = child->NextSiblingElement() ;
450  continue ;
451  }
452  // go recursively !
453  if( child->ValueStr() != "include" ) {
454  processIncludeElements( child , cfg ) ;
455  child = child->NextSiblingElement() ;
456  continue ;
457  }
458  // process the include and returns the first and last elements found in the include
459  TiXmlDocument document ;
460  processIncludeElement( child , cfg , document ) ;
461  // add them to the xml tree
462  TiXmlNode *includeAfter( child ) ;
463  for( TiXmlElement *includeElement = document.FirstChildElement() ; includeElement ; includeElement = includeElement->NextSiblingElement() ) {
464  includeAfter = element->InsertAfterChild( includeAfter, *includeElement ) ;
465  }
466  // tricky lines :
467  // 1) Remove the include element
468  element->RemoveChild(child) ;
469  // 2) Go to the next sibling element of the last included element to skip nested <include> elements
470  child = includeAfter->NextSiblingElement() ;
471  }
472  }
473 
474  //--------------------------------------------------------------------------
475 
476  void XMLConfigReader::processIncludeElement( TiXmlElement* element , const Configuration &cfg , TiXmlDocument &document ) const {
477  try {
478  std::string ref = getAttribute( element, "ref" ) ;
479  cfg.replaceConstants( ref ) ;
480  std::filesystem::path filepath = ref ;
481  if( not filepath.has_stem() || filepath.extension() != ".xml" ) {
482  MARLINMT_THROW_T( ParseException, "Invalid ref file name '" + ref + "' in element <" + element->ValueStr() + "/> in file " + _fname ) ;
483  }
484  // if the include ref is not absolute, then
485  // it is relative to the input file name
486  if( not filepath.is_absolute() ) {
487  auto idocdir = std::filesystem::path(_fname).parent_path() ;
488  filepath = idocdir / filepath ;
489  }
490  // load the include document and check for nested includes (not allowed for the time being)
491  bool loadOkay = document.LoadFile( filepath.string() ) ;
492  if( not loadOkay ) {
493  std::stringstream str ;
494  str << "Couldn't load include document. Error in file [" << filepath
495  << ", row: " << document.ErrorRow() << ", col: " << document.ErrorCol() << "] : "
496  << document.ErrorDesc() ;
497  MARLINMT_THROW_T( ParseException, str.str() ) ;
498  }
499  checkForNestedIncludes( &document ) ;
500  }
501  catch(Exception &e) {
502  MARLINMT_RETHROW( e, "Couldn't process include element" ) ;
503  }
504  }
505 
506  //--------------------------------------------------------------------------
507 
508  void XMLConfigReader::checkForNestedIncludes( const TiXmlNode *node ) const {
509  for(const TiXmlElement *child = node->FirstChildElement() ; child ; child = child->NextSiblingElement()) {
510  if( child->ValueStr() == "include" ) {
511  std::stringstream ss;
512  ss << "Nested includes are not allowed [in file: " << node->GetDocument()->ValueStr() << ", line: " << child->Row() << "] !" ;
513  MARLINMT_THROW_T( ParseException, ss.str() ) ;
514  }
515  checkForNestedIncludes( child ) ;
516  }
517  }
518 
519  //--------------------------------------------------------------------------
520 
521  void XMLConfigReader::parametersFromXMLElement( const TiXmlElement *element, const Configuration &cfg, ConfigSection &section, bool addAttributes, const std::string &replacePrefix ) const {
522  try {
523  auto elementValue = element->ValueStr() ;
524  // Copy all XML element attributes to the parameter list
525  // e.g <element name="toto" type="tutu"/>
526  // two parameters called ElementName and ElementType will be added in the parameter list
527  if( addAttributes ) {
528  elementValue[0] = std::toupper( elementValue[0], std::locale() ) ;
529  for(const TiXmlAttribute *attr = element->FirstAttribute() ; attr != nullptr ; attr = attr->Next()) {
530  std::string attrName = attr->Name() ;
531  attrName[0] = std::toupper( attrName[0], std::locale() ) ;
532  std::string attrValue = attr->ValueStr() ;
533  if( not replacePrefix.empty() ) {
534  attrValue = getReplacementParameter( replacePrefix + "." + attrName, cfg ).value_or( attrValue ) ;
535  }
536  cfg.replaceConstants( attrValue ) ;
537  section.setParameter( elementValue + attrName, attrValue ) ;
538  }
539  }
540  for(const TiXmlElement *child = element->FirstChildElement("parameter") ; child ; child = child->NextSiblingElement("parameter")) {
541  auto parameterName = getAttribute( child, "name" ) ;
542  std::string parameterValue ;
543  // get the value from the attribute value or from the XML element content
544  try {
545  parameterValue = getAttribute( child->ToElement() , "value" ) ;
546  }
547  catch( ParseException& ) {
548  if( child->FirstChild() ) {
549  parameterValue = child->FirstChild()->ValueStr() ;
550  }
551  }
552  if( not replacePrefix.empty() ) {
553  parameterValue = getReplacementParameter( replacePrefix + "." + parameterName, cfg ).value_or( parameterValue ) ;
554  }
555  cfg.replaceConstants( parameterValue ) ;
556  section.setParameter( parameterName, parameterValue ) ;
557  // TODO: treatment of in/out types ? drop it?
558  }
559  }
560  catch(Exception &e) {
561  MARLINMT_RETHROW( e, "Couldn't parse parameters from XML section" ) ;
562  }
563  }
564 
565  //--------------------------------------------------------------------------
566 
567  void XMLConfigReader::processConditions( TiXmlNode* current, const std::string &aCondition ) const {
568  try {
569  std::string condition ;
570  // put parentheses around compound expressions
571  if( aCondition.find('&') != std::string::npos || aCondition.find('|') != std::string::npos ) {
572  condition = "(" + aCondition + ")" ;
573  }
574  else {
575  condition = aCondition ;
576  }
577  // Do it recursively
578  TiXmlNode* child = 0 ;
579  while( ( child = current->IterateChildren( "if" , child ) ) != 0 ) {
580  processConditions( child->ToElement() , getAttribute( child->ToElement(), "condition") ) ;
581  }
582  while( ( child = current->IterateChildren( "processor" , child ) ) != 0 ) {
583  if( child->ToElement()->Attribute( "condition" ) == 0 ) {
584  child->ToElement()->SetAttribute( "condition", condition ) ;
585  }
586  else {
587  std::string cond( child->ToElement()->Attribute("condition") ) ;
588  if( cond.size() > 0 && not condition.empty() ) {
589  cond += " && " ;
590  }
591  cond += condition ;
592  child->ToElement()->SetAttribute( "condition", cond ) ;
593  }
594  if( current->ValueStr() != "execute" ) {
595  // unless we are already in the top node (<execute/>) we have to move all processors up
596  TiXmlNode* parent = current->Parent() ;
597  std::shared_ptr<TiXmlNode> clone( child->Clone() ) ;
598  parent->InsertBeforeChild( current , *clone ) ;
599  }
600  }
601  // remove the current <if/> node
602  if( current->ValueStr() != "execute" ) {
603  TiXmlNode* parent = current->Parent() ;
604  parent->RemoveChild( current ) ;
605  }
606  }
607  catch(Exception &e) {
608  MARLINMT_RETHROW( e, "Couldn't process conditions in execute section" ) ;
609  }
610  }
611 
612  //--------------------------------------------------------------------------
613 
614  void XMLConfigReader::replaceGroups( TiXmlNode* processorsParent, TiXmlNode* section ) const {
615  try {
616  TiXmlNode* child = 0 ;
617  TiXmlNode* nextChild = section->IterateChildren( child ) ;
618  while((child = nextChild) != 0) {
619  nextChild = section->IterateChildren(child) ;
620  if( child->ValueStr() == "group" ) {
621  // find group definition in root node
622  auto groupName = getAttribute( child->ToElement(), "name") ;
623  TiXmlNode* group = findElement( processorsParent, "group", "name" , groupName ) ;
624  if( nullptr == group ) {
625  MARLINMT_THROW_T( ParseException, "Group not found : " + groupName ) ;
626  }
627  TiXmlNode* sub = 0 ;
628  while( ( sub = group->IterateChildren( "processor" , sub ) ) != 0 ){
629  // insert <processor/> tag
630  TiXmlElement item( "processor" ) ;
631  item.SetAttribute( "name", getAttribute( sub->ToElement(), "name") ) ;
632  section->InsertBeforeChild( child , item ) ;
633  }
634  section->RemoveChild( child ) ;
635  }
636  else if( child->ValueStr() == "if" ) { // other element, e.g. <if></if>
637  replaceGroups( processorsParent, child ) ;
638  }
639  }
640  }
641  catch(Exception &e) {
642  MARLINMT_RETHROW( e, "Couldn't replace groups in XML file" ) ;
643  }
644  }
645 
646  //--------------------------------------------------------------------------
647 
648  TiXmlNode* XMLConfigReader::findElement( TiXmlNode* node, const std::string& type, const std::string& attribute, const std::string& value ) const {
649  TiXmlNode* child = 0 ;
650  while( (child = node->IterateChildren( type , child ) ) != 0 ) {
651  if( std::string( *child->ToElement()->Attribute( attribute ) ) == value ) {
652  return child ;
653  }
654  }
655  return nullptr ;
656  }
657 
658  //--------------------------------------------------------------------------
659 
660  std::optional<std::string> XMLConfigReader::getReplacementParameter( const std::string &arg, const Configuration &config ) const {
661  if( config.hasSection("CmdLine") ) {
662  auto &cmdline = config.section("CmdLine") ;
663  if( cmdline.hasSection("AdditionalArgs") ) {
664  auto &addArgs = cmdline.section("AdditionalArgs") ;
665  if( addArgs.hasParameter( arg ) ) {
666  return addArgs.parameter<std::string>( arg ) ;
667  }
668  }
669  }
670  return std::nullopt ;
671  }
672 
673  // plugin registration
675 
676 } // namespace marlinmt
ConfigSection & section(const std::string &n)
Get a subsection by name.
T parameter(const std::string &n) const
Get a parameter value as type T.
void processConditions(TiXmlNode *current, const std::string &aCondition) const
Treat the conditions for a XML node.
#define MARLINMT_THROW_T(ExceptionType, message)
Definition: Exceptions.h:9
ConfigSection & createSection(const std::string &sn)
Create a new section by name.
TiXmlNode * findElement(TiXmlNode *node, const std::string &tag, const std::string &attribute, const std::string &value) const
Find a particular XML node by matching tag, and a specific attribute value.
void parseConstants(TiXmlDocument *idoc, Configuration &cfg) const
Parse the <constants> section.
void parseExecuteSection(TiXmlElement *parentElement, Configuration &cfg) const
Parse the <execute> section and populate the configuration object accordingly.
std::string _fname
The input/output file name.
constexpr unsigned long long value(const Flag_t &flag)
Definition: Flags.h:106
#define MARLINMT_RETHROW(orig, message)
Definition: Exceptions.h:10
#define MARLINMT_DECLARE_CONFIG_READER(Class)
Definition: PluginManager.h:48
Configuration & addConstant(const std::string &cn, const T &val)
Add a constant.
XMLConfigReader plugin Read an XML file and populate the configuration with sections and parameters...
ConfigReader base class Interface for reading configuration.
void resolveGroupSections(TiXmlElement *rootElement) const
Resolve the <group> sections.
void parseSection(TiXmlElement *parentElement, const std::string &name, Configuration &cfg, bool addAttributes, bool throwIfNotFound) const
Parse a configuration section from the parent XML element.
void parseConstant(TiXmlElement *element, Configuration &cfg) const
Parse a single <constant> element.
void checkForNestedIncludes(const TiXmlNode *node) const
Check recursively for XML element in the node.
ConfigSection & section(const std::string &sn)
Get a section by name.
Configuration class.
std::string getAttribute(const TiXmlElement *element, const std::string &name) const
Helper method to get a XML element attribute as string.
std::optional< std::string > getReplacementParameter(const std::string &arg, const Configuration &config) const
void parametersFromXMLElement(const TiXmlElement *element, const Configuration &cfg, ConfigSection &section, bool addAttributes, const std::string &replacePrefix="") const
Read the <parameter> XML elements form the parent XML element.
#define MARLINMT_RETHROW_T(ExceptionType, orig, message)
Definition: Exceptions.h:11
void parseProcessorParameters(TiXmlElement *parent, Configuration &cfg) const
Parse all the processor parameter sections in the parent XML element.
ConfigSection & setParameter(const std::string &n, const T &val)
Set a parameter value.
Definition: Configuration.h:97
void processIncludeElements(TiXmlElement *element, const Configuration &cfg) const
Process all XML elements recursively.
void replaceConstants(std::string &str) const
Replace all occurences of ${constant_name} in the input string where "constant_name" must match a reg...
ConfigSection class Holds a set of parameters and subsection.
Definition: Configuration.h:20
void init(const std::string &desc) override
Initialize the parser.
bool hasSection(const std::string &n) const
Whether the section exists.
Exception class.
Definition: Exceptions.h:60
void read(Configuration &cfg) override
Read the configuration and populate the configuration object.
void replaceGroups(TiXmlNode *processorsParent, TiXmlNode *section) const
Replace the <group> tags in the execute section by the corresponding processors.
void processIncludeElement(TiXmlElement *element, const Configuration &cfg, TiXmlDocument &document) const
Process a single XML element.