ConfigPath.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2018 HPCC Systems®.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #include "ConfigPath.hpp"
  14. #include "Exceptions.hpp"
  15. #include "Utils.hpp"
  16. bool ConfigPathItem::checkValueAgainstValueList(const std::string val, bool returnTrueIfValueListEmpty) const
  17. {
  18. bool found = false;
  19. if (m_attributeValues.empty())
  20. {
  21. return returnTrueIfValueListEmpty;
  22. }
  23. for (auto it=m_attributeValues.begin(); it!=m_attributeValues.end() && !found; ++it)
  24. {
  25. found = (*it == val);
  26. }
  27. return found == m_presentInList;
  28. }
  29. std::shared_ptr<ConfigPathItem> ConfigPath::getNextPathItem()
  30. {
  31. std::shared_ptr<ConfigPathItem> pPathItem;
  32. //
  33. // If notheing left, return an empty pointer
  34. if (m_path.empty())
  35. {
  36. return pPathItem;
  37. }
  38. //
  39. // There is more to do, allocate a pointer and get to work
  40. pPathItem = std::make_shared<ConfigPathItem>();
  41. //
  42. // Root
  43. if (m_path[0] == '/')
  44. {
  45. parsePathElement(1, pPathItem);
  46. pPathItem->setIsRoot(true);
  47. updatePath(1);
  48. }
  49. //
  50. // Parent (MUST be done before current element test)
  51. else if (m_path.substr(0,2) == "..")
  52. {
  53. pPathItem->setIsParentPathItemn(true);
  54. updatePath(2);
  55. }
  56. //
  57. // Current element?
  58. else if (m_path[0] == '.')
  59. {
  60. pPathItem->setIsCurrentPathItem(true);
  61. updatePath(1);
  62. }
  63. //
  64. // Otherwise, need to parse it out
  65. else
  66. {
  67. parsePathElement(0, pPathItem);
  68. updatePath(0);
  69. }
  70. return pPathItem;
  71. }
  72. void ConfigPath::parsePathElement(std::size_t start, const std::shared_ptr<ConfigPathItem> &pPathItem)
  73. {
  74. std::size_t slashPos = m_path.find_first_of('/', start);
  75. std::size_t len = (slashPos != std::string::npos) ? (slashPos-start) : std::string::npos;
  76. std::string element = m_path.substr(start, len);
  77. //
  78. // The attribute definition is enclosed by the brackets, extract it if present
  79. std::string attr;
  80. if (extractEnclosedString(element, attr, '[', ']', true))
  81. {
  82. //
  83. // Make sure valid
  84. if (attr.empty())
  85. {
  86. throw(ParseException("Bad path, missng attribute definition at or around: " + element));
  87. }
  88. //
  89. // The attribute must begin with a '@' or '#'. The '#' is an extension for config manager that allows the selection
  90. // of elements based on schema value properties as opposed to attribute values. So, for a '#', the name is that of a
  91. // schema item property and not an attribute in the environment. Useful for selecting all elements of a particular
  92. // type, for example, when elements have nothing in the environment that can be used to determine type such as ecl watch.
  93. if (attr[0] == '@' || attr[0] == '#')
  94. {
  95. pPathItem->setIsSchemaItem(attr[0] == '#');
  96. std::size_t notEqualPos = attr.find("!=");
  97. std::size_t equalPos = attr.find_first_of('=');
  98. std::size_t comparePos = (notEqualPos != std::string::npos) ? notEqualPos : equalPos;
  99. if (comparePos != std::string::npos)
  100. {
  101. pPathItem->setAttributeName(attr.substr(1, comparePos-1));
  102. std::size_t valPos = attr.find_first_of("('", comparePos);
  103. if (valPos != std::string::npos)
  104. {
  105. std::string valueStr;
  106. extractEnclosedString(attr.substr(valPos), valueStr, '(', ')', true);
  107. std::vector<std::string> values = splitString(valueStr, ",");
  108. for (auto &valstr : values)
  109. {
  110. std::string value;
  111. extractEnclosedString(valstr, value, '\'', '\'', false);
  112. pPathItem->addAttributeValue(value);
  113. }
  114. pPathItem->setExcludeValueList(notEqualPos != std::string::npos);
  115. }
  116. else
  117. {
  118. throw(ParseException("Bad path, missng attribute values at or around: " + element));
  119. }
  120. }
  121. else
  122. {
  123. pPathItem->setAttributeName(attr.substr(1));
  124. }
  125. }
  126. else
  127. {
  128. throw(ParseException("Bad attribute, expected '@' or '#' at or around: " + element));
  129. }
  130. std::size_t bracketPos = element.find_first_of('[');
  131. pPathItem->setElementName(element.substr(0, bracketPos));
  132. }
  133. else
  134. {
  135. pPathItem->setElementName(element);
  136. }
  137. }
  138. void ConfigPath::updatePath(std::size_t startPos)
  139. {
  140. std::size_t nextPos = m_path.find_first_of('/', startPos);
  141. if (nextPos != std::string::npos)
  142. {
  143. m_path = m_path.substr(nextPos+1);
  144. }
  145. else
  146. {
  147. m_path.clear();
  148. }
  149. }