knowrob  2.1.0
A Knowledge Base System for Cognition-enabled Robots
PropertyTree.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of KnowRob, please consult
3  * https://github.com/knowrob/knowrob for license details.
4  */
5 
6 #include <boost/property_tree/json_parser.hpp>
7 #include "knowrob/PropertyTree.h"
8 #include "knowrob/terms/Function.h"
9 #include "knowrob/integration/python/utils.h"
10 #include "knowrob/terms/String.h"
11 #include "knowrob/terms/ListTerm.h"
12 #include <iostream>
13 #include <utility>
14 
15 
16 using namespace knowrob;
17 
19  : ptree_(nullptr),
20  delimiter_(".") {}
21 
22 PropertyTree::PropertyTree(std::shared_ptr<const boost::property_tree::ptree> ptree)
23  : ptree_(std::move(ptree)),
24  delimiter_(".") {
25  init();
26 }
27 
28 PropertyTree::PropertyTree(const std::string_view json_str)
29  : PropertyTree() {
30  std::istringstream ss(json_str.data());
31  boost::property_tree::ptree tree;
32  boost::property_tree::read_json(ss, tree);
33  // assign the variable with a new memory allocation as shared_ptr
34  ptree_ = std::make_shared<boost::property_tree::ptree>(tree);
35  init();
36 }
37 
39  static const std::string formatDefault = {};
40 
41  // process list of data sources that should be imported into the reasoner backend.
42  auto data_sources = ptree_->get_child_optional("imports");
43  if (!data_sources) {
44  data_sources = ptree_->get_child_optional("data-sources");
45  }
46  if (data_sources) {
47  for (const auto &pair: data_sources.value()) {
48  auto &subtree = pair.second;
49  URI dataSourceURI(subtree);
50  auto dataFormat = subtree.get("format", formatDefault);
51  auto source = std::make_shared<DataSource>(dataSourceURI, dataFormat, DataSourceType::UNSPECIFIED);
52  dataSources_.push_back(source);
53  }
54  }
55 }
56 
57 TermPtr PropertyTree::get(std::string_view key, const TermPtr &defaultValue) {
58  try {
59  return get_value_recursive(*ptree_, std::string(key));
60  } catch (const std::runtime_error &e) {
61  return defaultValue;
62  }
63 }
64 
65 TermPtr PropertyTree::get_value_recursive(const boost::property_tree::ptree &node, const std::string &path) {
66  if (path.empty()) {
67  try {
68  return std::make_shared<String>(node.get_value<std::string>());
69  } catch (const boost::property_tree::ptree_bad_data &) {
70  throw std::runtime_error("The found child is not a leaf node");
71  }
72  }
73 
74  // Find the position of the first dot or bracket
75  size_t dot_pos = path.find('.');
76  size_t bracket_pos = path.find('[');
77  size_t next_pos = (dot_pos == std::string::npos) ? bracket_pos : ((bracket_pos == std::string::npos) ? dot_pos
78  : std::min(
79  dot_pos, bracket_pos));
80 
81  // Extract the current key
82  std::string key = (next_pos == std::string::npos) ? path : path.substr(0, next_pos);
83  std::string remaining_path = (next_pos == std::string::npos) ? "" : path.substr(next_pos);
84 
85  // Check for array indexing
86  if (!remaining_path.empty() && remaining_path[0] == '[') {
87  size_t end_bracket_pos = remaining_path.find(']');
88  if (end_bracket_pos == std::string::npos) {
89  throw std::runtime_error("Invalid path syntax: unmatched '['");
90  }
91 
92  // Extract the index inside the brackets
93  std::string index_str = remaining_path.substr(1, end_bracket_pos - 1);
94  size_t index = std::stoi(index_str);
95  remaining_path = remaining_path.substr(end_bracket_pos + 1);
96 
97  // Remove leading dot if it exists
98  if (!remaining_path.empty() && remaining_path[0] == '.') {
99  remaining_path = remaining_path.substr(1);
100  }
101 
102  // Find the child array and access the element at the specified index
103  try {
104  const boost::property_tree::ptree &child_array = node.get_child(key);
105  auto it = child_array.begin();
106  std::advance(it, index);
107  if (it == child_array.end()) {
108  throw std::out_of_range("Index out of range");
109  }
110 
111  // Recursively call with the selected child and remaining path
112  return get_value_recursive(it->second, remaining_path);
113  } catch (const boost::property_tree::ptree_bad_path &) {
114  throw std::runtime_error("Invalid path (array): '" + key + "'");
115  }
116  } else {
117  // Normal key, recursively call with the next child
118  try {
119  // Remove leading dot if it exists
120  if (!remaining_path.empty() && remaining_path[0] == '.') {
121  remaining_path = remaining_path.substr(1);
122  }
123  // Attempt to fetch the child node
124  const boost::property_tree::ptree &child_node = node.get_child(key);
125  // Recursively call with the selected child and remaining path
126  return get_value_recursive(child_node, remaining_path);
127  } catch (const boost::property_tree::ptree_bad_path &) {
128  throw std::runtime_error("Invalid path (key): '" + key + "'");
129  }
130  }
131 }
132 
133 TermPtr PropertyTree::createKeyTerm(std::string_view key) const {
134  TermPtr last_key, next_key;
135 
136  size_t pos_start = 0, pos_end, delim_len = delimiter_.length();
137  std::string_view token;
138  std::vector<std::string_view> res;
139 
140  while ((pos_end = key.find(delimiter_, pos_start)) != std::string::npos) {
141  token = key.substr(pos_start, pos_end - pos_start);
142  pos_start = pos_end + delim_len;
143  next_key = Atom::Tabled(token);
144  if (last_key) {
145  last_key = std::make_shared<Function>(Function(delimiter_, {last_key, next_key}));
146  } else {
147  last_key = next_key;
148  }
149  res.push_back(token);
150  }
151  if (!last_key) {
152  last_key = Atom::Tabled(key);
153  }
154 
155  return last_key;
156 }
157 
158 namespace knowrob::py {
159  template<>
161  using namespace boost::python;
162  class_<PropertyTree, std::shared_ptr<PropertyTree>>("PropertyTree", init<>())
163  .def(init<const std::string &>())
164  .def("__iter__", range(&PropertyTree::begin, &PropertyTree::end))
165  .def("get", &PropertyTree::get)
166  .def("dataSources", &PropertyTree::dataSources, return_value_policy<copy_const_reference>());
167  }
168 }
static std::shared_ptr< knowrob::Atom > Tabled(std::string_view stringForm)
Definition: Atom.cpp:40
TermPtr createKeyTerm(std::string_view key) const
auto begin() const
Definition: PropertyTree.h:73
auto & dataSources() const
Definition: PropertyTree.h:83
TermPtr get(std::string_view key, const TermPtr &defaultValue)
TermRule & string()
Definition: terms.cpp:63
void createType< PropertyTree >()
const IRIAtomPtr range
Definition: rdfs.h:20
std::shared_ptr< Term > TermPtr
Definition: Term.h:117