XXMLManager.h
Go to the documentation of this file.
1 #ifndef _det_XXMLManager_h_
2 #define _det_XXMLManager_h_
3 
4 #include <det/VManager.h>
5 #include <det/ValidityStamp.h>
6 
7 #include <utl/ErrorLogger.h>
8 #include <utl/Branch.h>
9 
10 #include <boost/multi_index_container.hpp>
11 #include <boost/multi_index/member.hpp>
12 #include <boost/multi_index/ordered_index.hpp>
13 #include <boost/tokenizer.hpp>
14 #include <boost/lambda/lambda.hpp>
15 #include <boost/mpl/if.hpp>
16 #include <boost/mpl/empty_base.hpp>
17 
18 #include <map>
19 #include <string>
20 #include <set>
21 #include <vector>
22 #include <cstddef>
23 
24 
25 namespace det {
26 
28  namespace detail {
29 
38  public:
41 
50 
54  unsigned int GetCurrentConfiguration() const { return fCurrentConfiguration; }
55 
59  void SetCurrentConfiguration(unsigned int n) { fCurrentConfiguration = n; }
60 
61  private:
62  unsigned int fCurrentConfiguration;
63  };
64 
71  typedef boost::mpl::empty_base MonoConfigBase;
72 
73  }
74 
75 
181  template<class Info>
182  class XXMLManager : public det::VManager,
183  // Here we're choosing the base class according to the boolean flag.
184  public boost::mpl::if_c<
185  Info::kAllowMultiConfig,
186  detail::MultiConfigBase,
187  detail::MonoConfigBase
188  >::type {
189  public:
191  virtual ~XXMLManager() { }
192  // Call.
196  VMANAGER_GETDATA_CALL(GetDataInternal, std::list<int>);
197  VMANAGER_GETDATA_CALL(GetDataInternal, std::vector<double>);
198  VMANAGER_GETDATA_CALL(GetDataInternal, std::vector<int>);
200  // Deny.
201  //VMANAGER_GETDATA_DENIED(std::vector<int>);
202  //VMANAGER_GETDATA_DENIED(unsigned long long int)
203  VMANAGER_GETDATA_DENIED(std::vector<std::string>);
204  VMANAGER_GETDATA_DENIED(std::list<double>);
205  VMANAGER_GETDATA_DENIED(std::list<std::string>);
206  VMANAGER_GETDATA_DENIED(std::list<std::pair<int, int> >);
207  VMANAGER_GETDATA_DENIED(std::map<int, utl::TabulatedFunction>);
208  VMANAGER_GETDATA_DENIED(std::map<std::string, double>);
209  VMANAGER_GETDATA_DENIED(std::vector<std::vector<int> >);
211  VMANAGER_GETDATA_DENIED(std::vector<bool>);
212 
213  private:
215 
227  template<typename T, std::size_t N>
228  static
229  std::size_t
230  Size(const T (&)[N])
231  {
232  // A const seems proper, anyway no parameter name!!!
233  return N;
234  }
235 
247  template<typename T, std::size_t N>
248  static
249  bool
250  LookUpCoda(utl::Branch& dest, const utl::Branch& src, const T (&path)[N])
251  {
252  utl::Branch b = src;
253  // Now, do the transversing the remainding until finding it.
254  unsigned int i = 1;// From the second of the path.
255  // No need to call Size, we already have N.
256  for ( ; i < N && b; ++i)
257  b = b.GetChild(path[i]);
258  /*
259  * For sucessful result we have to have a branch
260  * and also transversed all the desired path.
261  */
262  if (b && i == N) {
263  dest = b;
264  return true;
265  }
266  return false;
267  }
268 
282  template<bool AllowMultiConfig, int dummy = 0>
283  struct ConfigHandler {
284  // Perform look up with MultiConfig criteria.
285  template<typename T, std::size_t N>
286  static
287  bool
288  Handle(const XXMLManager& m, utl::Branch& dest, const T (&path)[N])
289  {
290  /*
291  * If no child, just make a quick return without bothering too much (without a
292  * time consuming logic) and being quiet without prompting messages.
293  * Here we will have a quick return when the manager is configured with
294  * an empty branch.
295  */
296  if (!m.fBranch.GetFirstChild())
297  return false;
298  // If there's something, proceed with the logic as normal.
299  // Call the method that is defined in the variable base-class that keeps the count of the current number.
300  const int currConfig = m.GetCurrentConfiguration();
301  const int minConfig = 1;
302  /*
303  * Start looking from the current 'til the first.
304  * Note that since path[0] is likely to be the same in model or data cases we may
305  * find it, tough without further levels in one of the cases (ie it will be there
306  * because of the other case).
307  */
308  for (int n = currConfig; n >= minConfig; --n) {
309  // Look up a child with the configured name, and the current number as attribute.
310  const utl::AttributeMap attr{{Info::kIdAtt, boost::lexical_cast<std::string>(n)}};
311  // Note the unconditional access to element #0; it's a requirement to have at least 1.
312  if (const utl::Branch br = m.fBranch.GetChild(path[0], attr)) {
313  // Now that we've found the root, now complete the lookup stage.
314  // If found == true, then dest was already modified and so we simply return.
315  if (LookUpCoda(dest, br, path))
316  return true;
317  }
318  }
319  std::ostringstream msg;
320  msg << "In configuration change, no branch "
321  << path[0]
322  << " was found for configuration number from "
323  << currConfig
324  << " down to "
325  << minConfig
326  << " used as attribute "
327  << Info::kIdAtt
328  << ".";
329  WARNING(msg);
330  return false;
331  }
332  };
333 
335  template<int dummy>
336  struct ConfigHandler<false, dummy> {
337  // If no configuration change is allowed then the top branch is used directly.
338  template<typename T, std::size_t N>
339  static bool Handle(const XXMLManager& m, utl::Branch& dest, const T (&path)[N])
340  { return LookUpCoda(dest, m.fBranch, path); }
341  };
342 
343  //
347  class IdMatcher {
348  public:
350  IdMatcher(const std::string& i,const std::string& compName, bool report) :
351  fId(i),
352  fCompName(compName),
353  fIsReportingErrors(report)
354  { }
355 
359  {
360  // XXX Some hardcoding for this tag/wildcard.
361  const std::string kAllTag("all");
362  // If there was no match with ranges a last
363  // chance is to allow a wildcard match.
364  utl::AttributeMap all;
365  all[Info::kIdAtt] = kAllTag;
366  //DEBUGLOG("Child looked-up by wilcard on");
367  //DEBUGLOG(b.GetName());
368  // The outcome doesn't need to be checked if it's null.
369  return b.GetChild(fCompName, all);
370  }
371 
373  bool
374  operator()(const int lowerBound, const int upperBound)
375  {
376  std::istringstream is(fId);
377  int i = 0;
378  if (is >> i) {
379  const bool b = lowerBound <= i && i <= upperBound;
380  //DEBUGLOG(b ? "Child found by range." : "");
381  return b;
382  } else if (fIsReportingErrors) {
383  std::ostringstream warn;
384  warn << "The id "
385  << fId
386  << " specified for the component "
387  << fCompName
388  << " was ignored as it couldn't be interpreted as integer in range matching.";
389  WARNING(warn);
390  }
391  return false;
392  }
393 
395  bool
396  operator()(const int id)
397  {
398  std::istringstream is(fId);
399  int i = 0;
400  if (is >> i) {
401  const bool b = i == id;
402  //DEBUGLOG(b ? "Child found by specific id." : "");
403  return b;
404  } else if (fIsReportingErrors) {
405  std::ostringstream warn;
406  warn << "The id "
407  << fId
408  << " specified for the component "
409  << fCompName
410  << " was ignored as it couldn't be interpreted as integer in specific id matching";
411  WARNING(warn);
412  }
413  return false;
414  }
415 
416  private:
417  const std::string& fId;
418  const std::string& fCompName;
419  const bool fIsReportingErrors;
420  };
421 
425  template<class Container>
427  public:
429  AccumulatorMatcher(Container& ids, const bool report) :
430  fIds(ids),
431  fIsReportingErrors(report),
432  fModified(false)
433  { }
434 
437  { return utl::Branch(); }
438 
440  bool
441  operator()(const int lowerBound, const int upperBound)
442  {
443  for (int i = lowerBound; i<= upperBound; ++i) {
444  fIds.push_back(i);
445  fModified = true;
446  }
447  return false;
448  }
449 
451  bool
452  operator()(const int id)
453  {
454  fIds.push_back(id);
455  fModified = true;
456  return false;
457  }
458 
460  bool IsModified() const { return fModified; }
461 
462  private:
463  Container& fIds;
464  const bool fIsReportingErrors;
465  bool fModified;
466  };
467 
476  template<class Matcher>
477  static utl::Branch FindMatchingBranch(const utl::Branch& parent,
478  const std::string& compName,
479  Matcher& matcher,
480  bool isReportingErrors);
481 
490  template <typename T, std::size_t N>
491  utl::Branch FindRoot(const T (&path)[N]) const;
492 
504  utl::Branch FindModelBranch(const utl::Branch& componentModels,
505  const utl::Branch& compBranch,
506  const std::string& name) const;
507 
511  template<typename T>
513  GetDataInternal(T& t,
514  const std::string& prop,
515  const std::string& name,
516  const det::VManager::IndexMap& m) const;
517 
525  void Initialize();
526 
533  template<typename T>
535  GetDataInternal(const utl::Branch& topB,
536  T& t,
537  const std::string& prop,
538  const std::string& name) const;
539 
548  template<typename T>
550  GetDataInternal(const utl::Branch& topB,
551  std::list<T>& t,
552  const std::string& componentName,
553  const std::string& name) const;
554  };
555 
556 
557  template<class Info>
558  void
560  {
561  /*
562  * At last, seems not to be needed.
563  * SStationListXMLManager assumes that is
564  * propery set, so we assume the same.
565  * Init(Info::kManagerName);
566  *
567  * TODO A list for managed properties may be used here.
568  * // for fast decission if the manager can provided data
569  * // for a specific property
570  * std::set<std::string> fPropertiesList;
571  */
572  //DEBUGLOG("Initializing.");
573  }
574 
575 
576  template<class Info>
577  template <typename T, std::size_t N>
579  XXMLManager<Info>::FindRoot(const T (&path)[N])
580  const
581  {
582  using namespace utl;
583  using namespace std;
584  /*
585  * XXX All this look-up could be done just once, or least not
586  * everytime (beware of fBranch changes, of course).
587  * Also, now, it will be necesary to take into account the configuration
588  * number.
589  */
590  Branch result; // empty by now
591  // Be it mono or multiple, this has to be the case: the root
592  // element has it's name equal to the first element in the path;
593  // then in the multiple case we will allow some stutter and the
594  // first path element will be searched for once again.
595  if (fBranch.GetName() != path[0]) {
596  /*
597  * It's a requirement to have at least one value on the path.
598  * We could ignore it or do this check. In the supposedly
599  * case of zero-size array argument, the complier would
600  * complain about the calls to Size: it's not legal (in
601  * the standard sense) to have zero sized arrays.
602  */
603  std::ostringstream warn;
604  warn << "No root branch found, wrong path: started with "
605  << fBranch.GetName()
606  << " but "
607  << path[0]
608  << " was configured as first element of the path.";
609  WARNING(warn);
610  return result; // none: empty return value.
611  }
612  // Handle according to multi or mono configuration.
613  // b is an output parameter.
614  Branch b;
615  const bool found = ConfigHandler<Info::kAllowMultiConfig>::Handle(*this, b, path);
616  if (found)
617  result = b;
618  // May return empty. Loggin' has been done within Handle.
619  return result;
620  }
621 
622 
623  template<class Info>
624  template<class Matcher>
627  const std::string& compName,
628  Matcher& matcher,
629  bool isReportingErrors)
630  {
631  using namespace std;
632  using namespace utl;
633  const char kInterRange = ',';
634  const char kIntraRange = '-';
635  // Typedefs related to tokenization.
636  typedef boost::char_separator<char> Sep;
637  typedef boost::tokenizer<Sep> Tokenizer;
638  typedef Tokenizer::const_iterator It;
639  // Separators used inside the following loops.
640  const Sep interSep(string(1, kInterRange).c_str());
641  const Sep intraSep(string(1, kIntraRange).c_str());
642  // Now peform a look up based on ranges.
643  //DEBUGLOG("Loop over childs of");
644  //DEBUGLOG(b.GetName());
645  //DEBUGLOG("looking for");
646  //DEBUGLOG(compName);
647  for (Branch cB = b.GetFirstChild(); cB; cB = cB.GetNextSibling()) {
648  //DEBUGLOG("On the loop...");
649  //DEBUGLOG(cB.GetName());
650  // First /match by element name
651  if (cB.GetName() == compName) {
652  //DEBUGLOG("Branch match for:");
653  //DEBUGLOG(compName);
654  const AttributeMap branchAtt = cB.GetAttributes();
655  const AttributeMap::const_iterator i = branchAtt.find(Info::kIdAtt);
656  // Check to have the id; and then something used to define ranges,
657  // if nothing range.
658  if (branchAtt.end() != i) {
659  //DEBUGLOG("Att found");
660  //DEBUGLOG(i->second);
661  if (i->second.find(kIntraRange) != string::npos ||
662  i->second.find(kInterRange) != string::npos) {
663  //DEBUGLOG("Range matching:");
664  // First split among different ranges and...
665  Tokenizer ranges(i->second, interSep);
666  // ...loop over them.
667  for (It rangesIt = ranges.begin(); rangesIt != ranges.end(); ++rangesIt) {
668  const string& rangeStr = *rangesIt;
669  Tokenizer range(rangeStr, intraSep);
670  //DEBUGLOG("Iteration over ranges:");
671  //DEBUGLOG(rangeStr);
672  // Start empty.
673  string lower;
674  string upper;
675  // Over the range.
676  for (It rangeIt = range.begin(); rangeIt != range.end(); ++rangeIt) {
677  const string& rangeVal = *rangeIt;
678  //DEBUGLOG("Iteration inside range.");
679  //DEBUGLOG(rangeVal);
680  // Fill in order...
681  if (lower.empty())
682  lower = rangeVal;
683  else if (upper.empty())
684  upper = rangeVal;
685  else if (isReportingErrors) {
686  ostringstream warn;
687  warn << "The additional elements in the range "
688  << rangeVal
689  << " specified for the component "
690  << compName
691  << " were ignored.";
692  WARNING(warn);
693  }
694  } // intra range
695  if (upper.empty())
696  upper = lower; // Allow single value ranges.
697  // check if the bounds were actually found for the current range.
698  // The check for upper isn't neccesary (see previous if).
699  if (lower.size() /*&& upper.size()*/) {
700  int lb = 0;
701  int ub = 0;
702  istringstream ls(lower);
703  istringstream us(upper);
704  if (ls >> lb && us >> ub) {
705  if (matcher(lb, ub)) {
706  //DEBUGLOG("Range match.");
707  return cB;
708  }
709  } else if (isReportingErrors) {
710  ostringstream warn;
711  warn << "The elements in the range "
712  << rangeStr
713  << " specified for the component "
714  << compName
715  << " were ignored as they couldn't be interpreted as integers.";
716  WARNING(warn);
717  }
718  } else if (isReportingErrors) {
719  ostringstream warn;
720  warn << "The range "
721  << rangeStr
722  << " specified for the component "
723  << compName
724  << " wasn't completely specified.";
725  WARNING(warn);
726  }
727  } // inter range loop.
728  } else {
729  //DEBUGLOG("Specific matching.");
730  // plain ol'id: no range.
731  int id = 0;
732  istringstream is(i->second);
733  if (is >> id) {
734  if (matcher(id)) {
735  //DEBUGLOG("Specific id match");
736  return cB;
737  }
738  } else if (isReportingErrors) {
739  ostringstream warn;
740  warn << "The id specified ("
741  << i->second
742  << ") specified for the component "
743  << compName
744  << " was ignored as it couldn't be interpreted as integer.";
745  WARNING(warn);
746  }
747  }
748  } else { // end had attribute.
749  // No attribute was found.
750  //DEBUGLOG("Implicit matching.");
751  /*
752  * This is an special case.
753  *
754  * Mainly meant for those cases where
755  * the contained element is unique (at the cpp level) whithin its
756  * container: ie there's a one-to-one relationship.
757  *
758  * What we do here is that if no attribute is found, then the
759  * identifying attribute is supposed to be 1.
760  * In this way, for those aforementioned cases there's no need
761  * to code in the XML the, let's say it, fictious attribute.
762  * I say fictious because given the one-to-one relationship there's
763  * no need of an identifying value. The need of an identifying attributes
764  * comes from that within the attribute map, the name of the
765  * component has to be included (and so the attribute has to have some
766  * definitive value). Also note that in those cases, at the cpp level,
767  * the value of the identifying attribute is hardcoded (as a parameter
768  * passed by the containing class upon construction of the contained
769  * objects).
770  */
771  if (matcher(1)) {
772  //DEBUGLOG("Implicit identifying attribute equal to 1 match (no attribute was found in the branch).");
773  return cB;
774  }
775  }
776  } // end had element.
777  }
778  //DEBUGLOG("End of loop over the childs.");
779  return matcher(b);
780  }
781 
782 
783  template<class Info>
786  const utl::Branch& compBranch,
787  const std::string& name)
788  const
789  {
790  using namespace utl;
791  using namespace std;
792  string modelName;
793  // First look for an specific model at the component branch level.
794  // XXX Use the same tag, or create another one.
795  const Branch specificModel = compBranch.GetChild(Info::kModelsTag);
796  if (specificModel) {
797  // The model is the content of the branch, load it.
798  specificModel.GetData(modelName);
799  } else {
800  // If not, then look for the general models specified at the root level,
801  // with the models branch and an element for each component (with
802  // the component name as an attribute).
803  // XXX It may be better to specify the model name in the same way.
804  // It the previous case, putting an element in between seems ugly.
805  // And in this case I don't want to change the former way; in this
806  // case, nevertheless, the model could be perfectly put as the branch
807  // content.
808  // Search for the particular model, if we have them.
809  if (componentModels) {
810  //DEBUGLOG(componentModels.GetName());
811  /*
812  * Retrieve the model for the component, specified under an
813  * element with name equal to the one of the component.
814  */
815  Branch model;
816  // Need to match w/o attributes, only by name:
817  // the id is looked for.
818  for (Branch cB = componentModels.GetFirstChild(); cB; cB = cB.GetNextSibling()) {
819  if (cB.GetName() == name) {
820  model = cB;
821  break;
822  }
823  }
824  if (model) {
825  //DEBUGLOG(model.GetName());
826  // Look up the name of the model used for the component.
827  // Note that we're also using the template parameter.
828  /*
829  * Caveat emptor: GetAttributes return _BY COPY_
830  * so you better make your own copy, instead of chaining
831  * like
832  * i = model.GetAttributes().find...
833  * if (i != model.GetAttributes().end())
834  */
835  const AttributeMap att = model.GetAttributes();
836  // Again the attribute name comes from the template arg.
837  const AttributeMap::const_iterator i = att.find(Info::kIdAtt);
838  if (i != att.end()) {
839  //DEBUGLOG("Found attribute:");
840  //DEBUGLOG(i->first);
841  //DEBUGLOG(i->second);
842  // We have the name of the model on the iterator.
843  modelName = i->second;
844 
845  } else if (IsReportingErrors()) {
846  ostringstream warn;
847  warn << "The actual models found for the component "
848  << name
849  << " don't have an identification attribute.";
850  WARNING(warn);
851  }
852  } else if (IsReportingErrors()) {
853  ostringstream warn;
854  warn << "No actual models were found for the component " << name << ".";
855  WARNING(warn);
856  }
857  } else if (IsReportingErrors()) {
858  ostringstream warn;
859  warn << "No actual models were found " << name << ".";
860  WARNING(warn);
861  }
862  } // End of model name look-up.
863  // Retrieve the branch where the data for models is specified.
864  const Branch modelsData = FindRoot(Info::kModelsRootPath);
865  //DEBUGLOG(modelName);
866  // FindRoot takes care of reporting.
867  if (modelsData && modelName.size()) {
868  //DEBUGLOG(modelsData.GetName());
869  /*
870  * Build attributes map (I prefer this
871  * over the string with = in between, seems cleaner
872  * for my taste).
873  */
874  AttributeMap a;
875  // Look up for the model specified by the name.
876  a.insert(AttributeMap::value_type(Info::kIdAtt, modelName));
877  /*
878  * LookUp for the branch with the data for the model:
879  * the name is again the one taht comes from the component
880  * and we have set up attributes with the name of the
881  * particular model.
882  *
883  * Simply return the value, the caller has to
884  * take care if it's empty or not.
885  */
886  return modelsData.GetChild(name, a);
887  }
888  // No match, empty branch.
889  return Branch();
890  }
891 
892 
893  template<class Info>
894  template<typename T>
897  T& /*t*/,
898  const std::string& /*prop*/,
899  const std::string& /*name*/)
900  const
901  {
902  std::ostringstream err;
903  err << "Information without attributes was required with an scalar type.";
904  ERROR(err);
905  return VManager::eNotFound;
906  }
907 
908 
909  template<class Info>
910  template<typename T>
913  std::list<T>& t,
914  const std::string& componentName,
915  const std::string& /*name*/)
916  const
917  {
918  const utl::AttributeMap atts = topB.GetAttributes();
920  // Ignore the result.
921  // In this particular case the property name is a component name, so the
922  // name parameter is ignored.
923  FindMatchingBranch(topB, componentName, matcher, IsReportingErrors());
924  /*
925  * The original function taken as reference
926  *
927  * VManager::Status
928  * SStationListXMLManager::GetFullStationListXML(
929  * list<int>& returnList,
930  * const string& componentProperty,
931  * const string& componentName,
932  * const IndexMap& componentIndex)
933  *
934  * upon each insertion performed a lower_bound look to do an ordered
935  * insertion and to check for reps.
936  *
937  * It seems better to check that thing upon finalization instead of
938  * in each insertion.
939  */
940  /* First do a simple check, it's likely to have
941  * the list already ordered.
942  * Of course, if it's empty we don't have to bother at all.
943  */
944  if (t.size() &&
945  std::adjacent_find(t.begin(), t.end(), boost::lambda::_1 >= boost::lambda::_2) != t.end()) {
946  // Bad luck, it needs to be sorted.
947  /*
948  * No, no: this needs random access iterators:
949  * std::sort(t.begin(), t.end());
950  */
951  t.sort(); // This is O(N log(N)) anyway.
952  // Check against repetitions.
953  typename std::list<T>::const_iterator i =
954  std::adjacent_find(t.begin(), t.end(), boost::lambda::_1 == boost::lambda::_2);
955  if (i != t.end()) {
956  // The function from SStationListXMLManager did this unconditionally.
957  if (IsReportingErrors()) {
958  std::ostringstream warn;
959  warn << "The id = " << *i << " "
960  "appears more than once in the XML file list. "
961  "This and other repetitions will be ignored.";
962  WARNING(warn);
963  }
964  // Modify the list to have no reps.
965  std::unique(t.begin(), t.end());
966  }
967  }
968  return matcher.IsModified() ? VManager::eFound : VManager::eNotFound;
969  }
970 
971 
972  template<class Info>
973  template<typename T>
975  XXMLManager<Info>:: // split line
976  GetDataInternal(T& t, const std::string& prop, const std::string& name, const det::VManager::IndexMap& m)
977  const
978  {
979  using namespace utl;
980  using namespace det;
981  using namespace std;
982  //DEBUGLOG(Info::kManagerName);
983  //DEBUGLOG(name);
984  //DEBUGLOG(prop);
985  const bool handleModels = ! string(Info::kModelsTag).empty();
986  /*
987  * This call discards cv-qualifiers over 'this'
988  * if (!fIsInitialized)
989  * Init(Info::kManagerName);
990  *
991  * Can't remember nor find from where I took this
992  * previous code that was done here (I believe I
993  * took it from some other manager):
994  * Anyway put it in the initialize, and that's it.
995  */
996  /*
997  * By this time, fBranch is already initialized (during configuration of
998  * the register).
999  */
1000  // Retrieve the branch were the actual data resides.
1001  Branch dataRoot = FindRoot(Info::kDataRootPath);
1002  // Check if the root was actually found.
1003  if (dataRoot) {
1004  // Retrieve once and for all the total number of attributes.
1005  const unsigned int nAttTotal = m.size();
1006  /*
1007  * Transverse among siblings, for non model-like configuration
1008  * a single sibling will exist; for model-like multiple ones
1009  * will exist, and the particular element name will correspond
1010  * to the configuration (this element name is ignored for the
1011  * matters of this class, it's simply a label within the XML).
1012  */
1013  if (handleModels) {
1014  //DEBUGLOG("Handling models");
1015  /*
1016  * If there are models, then there's an element
1017  * in between groups the child branches belonging
1018  * to a particular model configuration.
1019  */
1021  }
1022  for (Branch cB = dataRoot; cB; cB = cB.GetNextSibling()) {
1023  unsigned int nAttFound = 0;
1024  Branch curr = cB;
1025  //DEBUGLOG(cB.GetName());
1026  /*
1027  * Whenever the path transversed brakes, then abort
1028  * the loop: that path is kept in curr.
1029  *
1030  * See comments inside to tell why i is compared with <=.
1031  */
1032  for (unsigned int i = 0; curr && i <= Size(Info::kComponentsIds); ++i) {
1033  /*
1034  * Here we check if the last component was in the match: if
1035  * that's the case then given that the components exhausted, then
1036  * the look-up for the (non existing) component id is equivalent
1037  * to a not found id in the map m.
1038  * If i is over the Size then the iterators gets initialized directly
1039  * with the end, and so we go over the else.
1040  * if the total number of attributes isn't reached then we'll try
1041  * another loop, but then the condition over i will break the loop:
1042  * that's correct. If we haven't reached the total number of ids
1043  * but the path in the branches ends first, we have to abort the search,
1044  * there's no match in/under this branch.
1045  */
1046  const IndexMap::const_iterator attIt = i < Size(Info::kComponentsIds) ?
1047  m.find(Info::kComponentsIds[i]) :
1048  m.end();
1049  //DEBUGLOG(i < Size(Info::kComponentsIds) ? Info::kComponentsIds[i] : "Past last component.");
1050  if (attIt != m.end()) {
1051  // If we enter here then i is a valid index.
1052  const string compName(Info::kComponentsNames[i]);
1053  // The match for specific id could be done directly with look up,
1054  // but I preferred to call FindMatchingBranch and have a common code.
1055  IdMatcher matcher(attIt->second, compName, IsReportingErrors());
1056  // Proceed to further levels.
1057  curr = FindMatchingBranch(curr, compName, matcher, IsReportingErrors());
1058  //DEBUGLOG(curr ? "Match found" : "No match found");
1059  nAttFound++;
1060  } else {
1061  if (nAttFound == nAttTotal) {
1062  //DEBUGLOG("Exhausted attributes.");
1063  // Do a linear search starting from i 'til the end (or 'til find).
1064  bool isComponent = false;
1065  /*
1066  * Note that when i is past the number of components, then this loop never
1067  * enters and, so, isComponent is false. That's correct, if the match
1068  * is the last in the component array, then it's a leaf in the hierarchy,
1069  * and so no further component will be under it. Remember also, that
1070  * if the list of these last component is desired then no id should
1071  * be specified in the map, and so we wouldn't reach this line of code
1072  * for i past the total number of components.
1073  * See then comment inside the isComponent condition.
1074  * At last, note that, precisely, the index i is never used again anymore.
1075  */
1076  for (unsigned int j = i; !isComponent && j < Size(Info::kComponentsIds); ++j)
1077  isComponent = Info::kComponentsNames[j] == prop;
1078  if (isComponent) {
1079  // Found a leaf of the hierarchy where we're looking for.
1080  /*
1081  * If the property is the same as a component name, we
1082  * should not have an id for that level on the attribute
1083  * map (this is not actually checked, but it's implied
1084  * since we have reached nAttTotal and here we're in the
1085  * case where attIt == m.end).
1086  * What is meant is to retrieve the list of all
1087  * the component's ids on that level.
1088  */
1089  // The attributes maps is needed, in fact we have already
1090  // consumed all its data.
1091  // Call the overloaded method.
1092  //DEBUGLOG("Searching for a component.");
1093  return GetDataInternal(curr, t, prop, name);
1094  } else {
1095  /*
1096  * It's indeed a property, get the specific prop;
1097  * but not so quick dude, maybe there shall be
1098  * a "model" indirection, that's, with all this
1099  * loops we have just determined the models that
1100  * correspond to the desired component.
1101  */
1102  if (handleModels) {
1103  //DEBUGLOG("Searching via models.");
1104  //DEBUGLOG(Info::kModelsTag);
1105  /*
1106  * Yes, we have models cause the specified tag
1107  * is not empty: so, retrive'em.
1108  */
1109  const Branch componentModels = cB.GetChild(Info::kModelsTag);
1110  /*
1111  * Look-up the branch with the data according to the models
1112  * we found.
1113  *
1114  * XXX Put even this in a policy? No, at least for now.
1115  */
1116  curr = FindModelBranch(componentModels, curr, name);
1117  if (!curr) {
1118  //DEBUGLOG("No model found.");
1119  // Normally the models should be found.
1120  // The called function takes care of the reporting.
1121  return VManager::eNotFound;
1122  }
1123  }
1124  // In any case, prop should (if existing) hang form curr.
1125  curr = curr.GetChild(prop);
1126  if (curr) {
1127  curr.GetData(t);
1128  return VManager::eFound;
1129  }
1130  //XXX Here we are allowing to go on the logic and match other branches.
1131  }
1132  }
1133  /* else {
1134  * Go on with the loop haven't examined all the attributes
1135  * in the map.
1136  * If we don't find a particular idName in m that means
1137  * that we are looking for something that's not
1138  * in the particular branch of the detector that
1139  * contains that idName.
1140  * i < j => idNames[j] doesn't come before idNames[i]
1141  * in the hierarchy of the detector.
1142  * So in this case, we can skip the particular one.
1143  * }
1144  */
1145  }
1146  }
1147  }
1148  // Not found in any of the siblings.
1149  if (IsReportingErrors()) {
1150  string msg = QueryInfoMessage(prop, name, m);
1151  msg += " not Found.";
1152  WARNING(msg);
1153  }
1154  } else if (IsReportingErrors()) {
1155  ostringstream warn;
1156  warn << "No data branch found:";
1157  for (unsigned int i = 0; i < Size(Info::kDataRootPath); ++i)
1158  warn << " " << Info::kDataRootPath[i];
1159  warn << ".";
1160  WARNING(warn);
1161  }
1162  // Not found exit, in any of the cases.
1163  return VManager::eNotFound;
1164  }
1165 
1166 }
1167 
1168 
1169 #endif
General Manager for reading detectors descriptions in XML files.
Definition: XXMLManager.h:182
bool operator()(const int lowerBound, const int upperBound)
Matches for a range.
Definition: XXMLManager.h:374
unsigned int GetCurrentConfiguration() const
Number of configuration.
Definition: XXMLManager.h:54
VMANAGER_GETDATA_CALL(GetDataInternal, double)
Helper struct to handle MultiConfig &amp; MonoConfig cases.
Definition: XXMLManager.h:283
Base class for the case when multiconfiguration is allowed. Not meant to be used directly by client c...
Definition: XXMLManager.h:37
Matcher for accumulation.
Definition: XXMLManager.h:426
Class to hold collection (x,y) points and provide interpolation between them.
det::VManager::Status GetDataInternal(T &t, const std::string &prop, const std::string &name, const det::VManager::IndexMap &m) const
Common template method for all types.
bool is(const double a, const double b)
Definition: testlib.cc:113
std::map< std::string, std::string > AttributeMap
Definition: Branch.h:24
AccumulatorMatcher(Container &ids, const bool report)
Construct.
Definition: XXMLManager.h:429
Matcher for specific identificator.
Definition: XXMLManager.h:347
Interface for detector managers.
Definition: VManager.h:115
Branch GetChild(const std::string &childName) const
Get child of this Branch by child name.
Definition: Branch.cc:211
void Initialize()
Some inits for the objects of this class, apart from those from VManager.
Definition: XXMLManager.h:559
VMANAGER_GETDATA_DENIED(std::vector< std::string >)
AttributeMap GetAttributes() const
Get a map&lt;string, string&gt; containing all the attributes of this Branch.
Definition: Branch.cc:267
Branch GetNextSibling() const
Get next sibling of this branch.
Definition: Branch.cc:284
unsigned int fCurrentConfiguration
Definition: XXMLManager.h:62
Class representing a document branch.
Definition: Branch.h:107
bool operator()(const int lowerBound, const int upperBound)
Fill the range.
Definition: XXMLManager.h:441
Class to hold collection (x,y) points and provide interpolation between them, where y are complex num...
static std::string QueryInfoMessage(const Handle &returnData, const std::string &component)
Definition: VManager.cc:108
const Data result[]
virtual ~XXMLManager()
Definition: XXMLManager.h:191
IdMatcher(const std::string &i, const std::string &compName, bool report)
Construct.
Definition: XXMLManager.h:350
#define VMANAGER_GETDATA_HANDLE_DENIED
Definition: VManager.h:75
const std::string & fCompName
Definition: XXMLManager.h:418
void NextConfiguration()
Advances the current configuration index.
Definition: XXMLManager.h:49
unsigned int i
Definition: XXMLManager.h:254
#define WARNING(message)
Macro for logging warning messages.
Definition: ErrorLogger.h:163
void GetData(bool &b) const
Overloads of the GetData member template function.
Definition: Branch.cc:644
std::string GetName() const
function to get the Branch name
Definition: Branch.cc:374
boost::mpl::empty_base MonoConfigBase
Base class for the case when multiconfiguration isn&#39;t allowed. Not meant to be used directly by clien...
Definition: XXMLManager.h:71
utl::Branch operator()(const utl::Branch &b)
Matches against the specific Branch.
Definition: XXMLManager.h:358
Branch dataRoot
Definition: XXMLManager.h:1001
bool operator()(const int id)
Matches for an specific id.
Definition: XXMLManager.h:396
void SetCurrentConfiguration(unsigned int n)
Set an specific configuration number.
Definition: XXMLManager.h:59
utl::Branch FindModelBranch(const utl::Branch &componentModels, const utl::Branch &compBranch, const std::string &name) const
Helper function which retrieves the data branch that corresponds to the models specified in component...
Definition: XXMLManager.h:785
utl::Branch FindRoot(const T(&path)[N]) const
Helper function from transversal from the configured branch until the desired roots.
Definition: XXMLManager.h:579
MultiConfigBase()
Configuration number start in one.
Definition: XXMLManager.h:40
std::map< std::string, std::string > IndexMap
Definition: VManager.h:133
static utl::Branch FindMatchingBranch(const utl::Branch &parent, const std::string &compName, Matcher &matcher, bool isReportingErrors)
Finds the matching branch among parent according to id.
Definition: XXMLManager.h:626
const bool handleModels
Definition: XXMLManager.h:985
static bool Handle(const XXMLManager &m, utl::Branch &dest, const T(&path)[N])
Definition: XXMLManager.h:339
utl::Branch operator()(const utl::Branch &)
Never matches.
Definition: XXMLManager.h:436
bool IsReportingErrors() const
Definition: VManager.h:338
Branch GetFirstChild() const
Get first child of this Branch.
Definition: Branch.cc:98
utl::Branch fBranch
Definition: VManager.h:360
bool operator()(const int id)
Add the id.
Definition: XXMLManager.h:452
#define ERROR(message)
Macro for logging error messages.
Definition: ErrorLogger.h:165
constexpr double m
Definition: AugerUnits.h:121
bool IsModified() const
Returns if there were additions.
Definition: XXMLManager.h:460
const std::string & fId
Definition: XXMLManager.h:417
Status
Specifies success or (eventually) various possible failure modes.
Definition: VManager.h:127

, generated on Tue Sep 26 2023.