tue_config
sdf.cpp
Go to the documentation of this file.
1 #include <fstream>
2 #include <sstream>
3 #include <set>
4 #include <tinyxml2.h>
5 
9 #include "tue/config/read.h"
10 #include "tue/config/node_type.h"
11 
12 #include "tue/filesystem/path.h"
13 
14 namespace tue
15 {
16 
17 namespace config
18 {
19 
20 // ----------------------------------------------------------------------------------------------------
21 // all tags which should be an array(list)
22 static const std::set<std::string> SDF_ARRAY_SET {"collision", "include", "joint", "link", "model", "point", "visual",
23  "virtual_volume"};
24 
25 // all tags which should be an group(dict)
26 static const std::set<std::string> SDF_MAP_SET {"atmosphere", "audio", "blend", "box", "camera", "cylinder", "geometry",
27  "gripper", "gui", "heightmap", "image", "mesh", "plane", "plugin",
28  "polyline", "pose", "sdf", "sphere", "texture", "track_visual", "wind",
29  "world" };
30 // all tags which should be an value
31 static const std::set<std::string> SDF_VALUE_SET {"device", "diffuse", "empty", "fade_dist", "filename", "fullscreen",
32  "gravity", "height", "inherit_yaw", "length", "linear_velocity",
33  "magnetic_field", "max_dist", "min_dist", "min_height", "name",
34  "normal", "pos", "pose", "pressure", "projection_type", "radius",
35  "sampling", "size", "static", "temperature", "temperature_gradient",
36  "type", "uri", "use_model_frame", "view_controller", "xyz" };
37 
38 
39 // ----------------------------------------------------------------------------------------------------
40 
42 {
43  // check if the element name is in the array set
45  if (it != SDF_ARRAY_SET.end())
46  return ARRAY;
47 
48  static std::set<std::string> already_printed;
49 
50  // check if the element name is in the map set
51  if (SDF_MAP_SET.find(element_name) == SDF_MAP_SET.end() && already_printed.find(element_name) == already_printed.end())
52  {
53  already_printed.insert(element_name);
54  std::cout << "Element: '" << element_name << "' not in SDF ARRAY or MAP list. Will return MAP as Node type." << std::endl;
55  }
56 
57  // return MAP, even if it is not in the map set.
58  return MAP;
59 }
60 
61 // ----------------------------------------------------------------------------------------------------
62 
63 bool loadFromSDFElement(const tinyxml2::XMLElement& element, ReaderWriter& config, const NodeType node_type)
64 {
65  // Attributes aren't read, if element doesn't have any child elements
66  if (element.FirstChildElement() == nullptr)
67  {
68  if (node_type == MAP)
69  return loadFromXMLText(element, config);
70  else
71  {
73  if (!loadFromXMLText(element, config))
74  return false;
76  }
77  }
78  else
79  {
80  // Start new group or array item
81  // in case of array the array is opened on parent level. Only need to add array items on this level.
82  if (node_type == ARRAY)
84  else
85  // Start a new group
86  config.writeGroup(element.Value());
87 
88 
89  // Iterate through attributes
90  // if this element does not contain children, we don't end up here
91  for (const tinyxml2::XMLAttribute* attribute = element.FirstAttribute(); attribute != nullptr; attribute = attribute->Next())
92  {
93  setValue(attribute->Name(), attribute->Value(), config);
94  }
95 
96  // Iterate through elements
97  for(const tinyxml2::XMLElement* e = element.FirstChildElement(); e != nullptr; e = e->NextSiblingElement())
98  {
99  std::string candidate_name = e->Value();
100  tue::config::NodeType candidate_node_type = getSDFNodeType(candidate_name);
101  // Because potentially childs of same type could be read, alternated by an other type.
102  // Hence opening and closing of the array is needed for each child.
103  // wirteArray will open the array if existing.
104  if (candidate_node_type == ARRAY && !config.writeArray(candidate_name))
105  {
106  std::stringstream error;
107  error << "Could not write or read array: " << candidate_name;
108  config.addError(error.str());
109  return false;
110  }
111 
112  // load child element
113  if (!loadFromSDFElement(*e, config, candidate_node_type))
114  {
115  std::stringstream error;
116  error << "Error parsing " << candidate_name;
117  config.addError(error.str());
118  return false;
119  }
120 
121  // end array
122  if (candidate_node_type == ARRAY)
123  config.endArray();
124  }
125  // Ending array item or group
126  if (node_type == ARRAY)
128  else
129  config.endGroup();
130  }
131 
132  return true;
133 
134 }
135 
136 // ----------------------------------------------------------------------------------------------------
137 
138 bool loadFromSDFDocument(const tinyxml2::XMLDocument& doc, ReaderWriter& config)
139 {
140  const tinyxml2::XMLElement* root = doc.FirstChildElement();
141 
142  if (root->NextSibling() != nullptr)
143  {
144  throw tue::config::ParseException("A valid XML file should only contain one root element");
145  }
146 
147  return loadFromSDFElement(*root, config, MAP);
148 }
149 
150 // ----------------------------------------------------------------------------------------------------
151 
153 {
154  tinyxml2::XMLDocument doc;
155  std::string stream_string;
156  stream >> stream_string;
157  doc.Parse(stream_string.c_str());
158  if (doc.Error())
159  {
160  std::stringstream error;
161  error << "Error loading stream:" << std::endl << stream.rdbuf() << std::endl;
162  error << doc.ErrorStr() << " at line " << doc.ErrorLineNum();
163  config.addError(error.str());
164  return false;
165  }
166  return loadFromSDFDocument(doc, config);
167 }
168 
169 // ----------------------------------------------------------------------------------------------------
170 
172 {
173  tinyxml2::XMLDocument doc;
174  doc.Parse(string.c_str());
175  if (doc.Error())
176  {
177  std::stringstream error;
178  error << "Error loading string:" << std::endl << string << std::endl;
179  error << doc.ErrorStr() << " at line" << doc.ErrorLineNum();
180  config.addError(error.str());
181  return false;
182  }
183  return loadFromSDFDocument(doc, config);
184 }
185 
186 // ----------------------------------------------------------------------------------------------------
187 
189 {
190  config.setSource(filename);
191 
192  tue::filesystem::Path path(filename);
193  if (!path.exists())
194  {
195  std::stringstream error;
196  error << "[loadFromSDFFile] file '" << filename << "' doesn't exist." << std::endl;
197  config.addError(error.str());
198  return false;
199  }
200 
201  // Load the file
202  tinyxml2::XMLDocument doc;
203  doc.LoadFile(filename.c_str());
204  if (doc.Error())
205  {
206  std::stringstream error;
207  error << "Error loading " << filename << ": ";
208  error << doc.ErrorStr() << " at line " << doc.ErrorLineNum();
209  config.addError(error.str());
210  return false;
211  }
212 
213  // read the document
214  return loadFromSDFDocument(doc, config);
215 }
216 
217 // ----------------------------------------------------------------------------------------------------
218 
219 } // End of namespace config
220 
221 } // End of namespace tue
tue::config::loadFromSDFElement
bool loadFromSDFElement(const tinyxml2::XMLElement &element, ReaderWriter &config, const NodeType node_type)
Definition: sdf.cpp:63
sstream
tue::config::loadFromSDFString
bool loadFromSDFString(const std::string &string, ReaderWriter &config)
loadFromSDFString loads a sdf string into a ReaderWriter class
Definition: sdf.cpp:171
tue::config::SDF_MAP_SET
static const std::set< std::string > SDF_MAP_SET
Definition: sdf.cpp:26
std::istream::rdbuf
T rdbuf(T... args)
fstream
std::string
tue::config::loadFromXMLText
bool loadFromXMLText(const tinyxml2::XMLElement &element, ReaderWriter &config)
loadFromXMLText writes a value from xml element into config object. Stored as double,...
Definition: xml.cpp:48
tue::config::ReaderWriter::setSource
void setSource(const std::string &source)
setSource set the source file of the data in this object
Definition: reader_writer.h:193
tue::config::ReaderWriter::endArrayItem
bool endArrayItem()
endArrayItem go back to the array level
Definition: reader_writer.cpp:245
tue::filesystem::Path
std::set::find
T find(T... args)
std::stringstream
tue::config::ReaderWriter::writeArray
bool writeArray(const std::string &name)
writeArray starts writing an array. Or start extending it, if it already exists.
Definition: reader_writer.cpp:202
tue::filesystem::Path::exists
bool exists() const
tue::config::loadFromSDFDocument
bool loadFromSDFDocument(const tinyxml2::XMLDocument &doc, ReaderWriter &config)
Definition: sdf.cpp:138
tue::config::ParseException
Definition: read.h:17
tue::config::ReaderWriter::writeGroup
bool writeGroup(const std::string &name)
writeGroup starts writing a group. Or start extending it, if it already exists.
Definition: reader_writer.cpp:181
xml.h
tue::config::ReaderWriter::addArrayItem
bool addArrayItem()
addArrayItem create a new item in the array
Definition: reader_writer.cpp:223
std::cout
tue::config::ReaderWriter
Definition: reader_writer.h:26
tue::config::SDF_VALUE_SET
static const std::set< std::string > SDF_VALUE_SET
Definition: sdf.cpp:31
std::string::c_str
T c_str(T... args)
tue::config::ReaderWriter::endGroup
bool endGroup()
endGroup go to the parrent of current group, wrapping end() for readbility
Definition: reader_writer.h:104
tue::config::setValue
bool setValue(const std::string &key, const std::string &value, ReaderWriter &config)
setValue sets the value as a double, int or string
Definition: xml.cpp:18
tue::config::loadFromSDFFile
bool loadFromSDFFile(const std::string &filename, ReaderWriter &config)
loadFromSDFFile loads a sdf file into a ReaderWriter class
Definition: sdf.cpp:188
tue::config::ReaderWriter::endArray
bool endArray()
endArray go to parrent of current array, wrapping end() for readibility
Definition: reader_writer.h:98
tue::config::loadFromSDFStream
bool loadFromSDFStream(std::istream &stream, ReaderWriter &config)
loadFromSDFStream loads a sdf stream into a ReaderWriter class
Definition: sdf.cpp:152
tue::config::ARRAY
@ ARRAY
Definition: node_type.h:13
tue::config::ReaderWriter::addError
void addError(const std::string &msg)
Definition: reader_writer.cpp:136
path.h
tue::config::MAP
@ MAP
Definition: node_type.h:12
std::endl
T endl(T... args)
tue::config::getSDFNodeType
tue::config::NodeType getSDFNodeType(const std::string &element_name)
Definition: sdf.cpp:41
tue::config::SDF_ARRAY_SET
static const std::set< std::string > SDF_ARRAY_SET
Definition: sdf.cpp:22
std::set::insert
T insert(T... args)
configuration.h
tue::config::NodeType
NodeType
Definition: node_type.h:10
node_type.h
std::stringstream::str
T str(T... args)
std::set::end
T end(T... args)
std::istream
sdf.h
set
tue
read.h
config
tue::config::ReaderWriter config
Definition: sdf_gtest.cpp:9