preCICE v3.2.0
Loading...
Searching...
No Matches
XMLTag.cpp
Go to the documentation of this file.
1#include "xml/XMLTag.hpp"
2#include <Eigen/Core>
3#include <utility>
5#include "utils/String.hpp"
6#include "utils/assertion.hpp"
8
9namespace precice::xml {
10
12 Listener &listener,
13 std::string tagName,
14 Occurrence occurrence,
15 std::string xmlNamespace)
16 : _listener(listener),
17 _name(std::move(tagName)),
18 _namespace(std::move(xmlNamespace)),
19 _occurrence(occurrence)
20{
22 if (not _namespace.empty()) {
23 _fullName = _namespace + ":" + _name;
24 } else {
26 }
27}
28
30{
31 _doc = documentation;
32 return *this;
33}
34
36{
37 _namespaces.push_back(namespaceName);
38 return *this;
39}
40
42{
45 if (not tag._namespace.empty()) {
47 }
48
49 _subtags.push_back(std::make_shared<XMLTag>(tag));
50 return *this;
51}
52
54{
55 const auto &name = attribute.getName();
56 PRECICE_TRACE(name);
57 PRECICE_ASSERT(!hasAttribute(name) && _attributeHints.count(name) == 0);
58 _attributes.emplace_back(attribute);
59 return *this;
60}
61
63{
64 const auto &name = attribute.getName();
65 PRECICE_TRACE(name);
66 PRECICE_ASSERT(!hasAttribute(name) && _attributeHints.count(name) == 0);
67 _attributes.emplace_back(attribute);
68 return *this;
69}
70
72{
73 const auto &name = attribute.getName();
74 PRECICE_TRACE(name);
75 PRECICE_ASSERT(!hasAttribute(name) && _attributeHints.count(name) == 0);
76 _attributes.emplace_back(attribute);
77 return *this;
78}
79
81{
82 const auto &name = attribute.getName();
83 PRECICE_TRACE(name);
84 PRECICE_ASSERT(!hasAttribute(name) && _attributeHints.count(name) == 0);
85 _attributes.emplace_back(attribute);
86 return *this;
87}
88
90{
91 const auto &name = attribute.getName();
92 PRECICE_TRACE(name);
93 PRECICE_ASSERT(!hasAttribute(name) && _attributeHints.count(name) == 0);
94 _attributes.emplace_back(attribute);
95 return *this;
96}
97
99{
100 PRECICE_TRACE(name);
101 PRECICE_ASSERT(!hasAttribute(name) && _attributeHints.count(name) == 0);
102 _attributeHints.emplace(std::move(name), std::move(message));
103}
104
105namespace {
106auto findAttribute(const XMLTag::Attributes &attributes, const std::string &name)
107{
108 return std::find_if(attributes.begin(), attributes.end(), [&name](const auto &attribute) { return getName(attribute) == name; });
109}
110} // namespace
111
112bool XMLTag::hasAttribute(const std::string &attributeName) const
113{
114 return findAttribute(_attributes, attributeName) != _attributes.end();
115}
116
118{
119 PRECICE_TRACE(name);
120 if (auto iter = findAttribute(_attributes, name);
121 iter != _attributes.end()) {
123 return std::get<XMLAttribute<double>>(*iter).getValue();
124 }
125 if (default_value) {
126 return default_value.value();
127 }
128 PRECICE_UNREACHABLE("The XMLAttribute doesn't exist, check its default.");
129}
130
132{
133 PRECICE_TRACE(name);
134 if (auto iter = findAttribute(_attributes, name);
135 iter != _attributes.end()) {
137 return std::get<XMLAttribute<int>>(*iter).getValue();
138 }
139 if (default_value) {
140 return default_value.value();
141 }
142 PRECICE_UNREACHABLE("The XMLAttribute doesn't exist, check its default.");
143}
144
146{
147 PRECICE_TRACE(name);
148 if (auto iter = findAttribute(_attributes, name);
149 iter != _attributes.end()) {
151 return std::get<XMLAttribute<std::string>>(*iter).getValue();
152 }
153 if (default_value) {
154 return default_value.value();
155 }
156 PRECICE_UNREACHABLE("The XMLAttribute doesn't exist, check its default.");
157}
158
160{
161 PRECICE_TRACE(name);
162 if (auto iter = findAttribute(_attributes, name);
163 iter != _attributes.end()) {
165 return std::get<XMLAttribute<bool>>(*iter).getValue();
166 }
167 if (default_value) {
168 return default_value.value();
169 }
170 PRECICE_UNREACHABLE("The XMLAttribute doesn't exist, check its default.");
171}
172
173Eigen::VectorXd XMLTag::getEigenVectorXdAttributeValue(const std::string &name) const
174{
175 PRECICE_TRACE(name);
176 if (auto iter = findAttribute(_attributes, name);
177 iter != _attributes.end()) {
179 return std::get<XMLAttribute<Eigen::VectorXd>>(*iter).getValue();
180 }
181 PRECICE_UNREACHABLE("The XMLAttribute doesn't exist, check its default.");
182}
183
185{
187
188 // Check for unexpected attributes and hints
189 for (const auto &element : aAttributes) {
190 const auto &name = element.first;
191 if (hasAttribute(name)) {
192 continue;
193 }
194
195 // check existing hints
196 if (auto pos = _attributeHints.find(name);
197 pos != _attributeHints.end()) {
198 PRECICE_ERROR("The tag <{}> in the configuration contains the attribute \"{}\". {}", _fullName, name, pos->second);
199 }
200
201 auto expected = getAttributeNames();
202 auto matches = utils::computeMatches(name, expected);
203 if (!matches.empty() && matches.front().distance < 3) {
204 matches.erase(std::remove_if(matches.begin(), matches.end(), [](auto &m) { return m.distance > 2; }), matches.end());
205 std::vector<std::string> stringMatches;
206 std::transform(matches.begin(), matches.end(), std::back_inserter(stringMatches), [](auto &m) { return m.name; });
207 PRECICE_ERROR("The tag <{}> in the configuration contains an unknown attribute \"{}\". Did you mean \"{}\"?", _fullName, name, fmt::join(stringMatches, ", "));
208 }
209 PRECICE_ERROR("The tag <{}> in the configuration contains an unknown attribute \"{}\". Expected attributes are {}.", _fullName, name, fmt::join(expected, ", "));
210 }
211
212 // Read all attributes
213 for (auto &attribute : _attributes) {
215 [&aAttributes](auto &attribute) { attribute.readValue(aAttributes); },
216 attribute);
217 }
218}
219
221{
223 for (const auto &attribute : _attributes) {
224 names.push_back(xml::getName(attribute));
225 }
226 return names;
227}
228
230{
231 for (const auto &tag : _subtags) {
232 std::string ns = tag->_namespace;
233 bool configured = tag->isConfigured();
234
235 bool occurOnce = tag->getOccurrence() == OCCUR_ONCE;
236 bool occurOnceOrMore = tag->getOccurrence() == OCCUR_ONCE_OR_MORE;
237
238 if (not ns.empty()) {
239 auto nsIter = _configuredNamespaces.find(ns);
240 PRECICE_ASSERT(nsIter != _configuredNamespaces.end());
241 configured |= nsIter->second;
242 }
243
244 if ((not configured) && (occurOnce || occurOnceOrMore)) {
245
246 if (tag->getNamespace().empty()) {
247 PRECICE_ERROR("Tag <{}> was not found but is required to occur at least once.", tag->getName());
248 } else {
249 PRECICE_ERROR("Tag <{}:... > was not found but is required to occur at least once.", tag->getNamespace());
250 }
251 }
252 }
253}
254
256{
257 _configured = false;
258
259 for (auto &pair : _configuredNamespaces) {
260 pair.second = false;
261 }
262 for (auto &attribute : _attributes) {
264 [](auto &attribute) { attribute.setRead(false); },
265 attribute);
266 }
267 for (auto &tag : _subtags) {
268 tag->_configured = false;
269 tag->resetAttributes();
270 }
271}
272
274{
275 return std::visit([](auto &attribute) { return attribute.getName(); }, attribute);
276}
277
279{
280 static NoPListener listener;
281 return XMLTag(listener, "configuration", XMLTag::OCCUR_ONCE);
282}
283
285 XMLTag &tag,
287 std::string_view configurationFilename)
288{
289 logging::Logger _log("xml");
290 PRECICE_TRACE(tag.getFullName(), configurationFilename);
291
292 NoPListener nopListener;
293 XMLTag root(nopListener, "", XMLTag::OCCUR_ONCE);
294
295 precice::xml::ConfigParser p(configurationFilename, context, std::make_shared<XMLTag>(tag));
296
297 root.addSubtag(tag);
298
299 return p.hash();
300}
301
303{
304 if (occurrence == XMLTag::OCCUR_ARBITRARY) {
305 return "0..*";
306 } else if (occurrence == XMLTag::OCCUR_NOT_OR_ONCE) {
307 return "0..1";
308 } else if (occurrence == XMLTag::OCCUR_ONCE) {
309 return "1";
310 } else if (occurrence == XMLTag::OCCUR_ONCE_OR_MORE) {
311 return "1..*";
312 }
313 return "";
314}
315} // namespace precice::xml
#define PRECICE_ERROR(...)
Definition LogMacros.hpp:16
#define PRECICE_TRACE(...)
Definition LogMacros.hpp:92
#define PRECICE_ASSERT(...)
Definition assertion.hpp:85
#define PRECICE_UNREACHABLE(...)
Definition assertion.hpp:93
T back_inserter(T... args)
This class provides a lightweight logger.
Definition Logger.hpp:17
std::string hash() const
returns the hash of the processed XML file
const std::string & getName() const
Represents an XML tag to be configured automatically.
Definition XMLTag.hpp:28
Eigen::VectorXd getEigenVectorXdAttributeValue(const std::string &name) const
Definition XMLTag.cpp:173
std::string _fullName
Combination of name and namespace: _namespace + ":" + _name.
Definition XMLTag.hpp:217
std::map< std::string, bool > _configuredNamespaces
Definition XMLTag.hpp:229
bool hasAttribute(const std::string &attributeName) const
Definition XMLTag.cpp:112
std::string getStringAttributeValue(const std::string &name, std::optional< std::string > default_value=std::nullopt) const
Definition XMLTag.cpp:145
Occurrence _occurrence
Definition XMLTag.hpp:223
bool getBooleanAttributeValue(const std::string &name, std::optional< bool > default_value=std::nullopt) const
Definition XMLTag.cpp:159
void readAttributes(const std::map< std::string, std::string > &aAttributes)
reads all attributes of this tag
Definition XMLTag.cpp:184
Namespaces _namespaces
Definition XMLTag.hpp:225
std::string _namespace
XML namespace of the tag.
Definition XMLTag.hpp:214
Listener & _listener
Definition XMLTag.hpp:208
XMLTag & setDocumentation(std::string_view documentation)
Adds a description of the purpose of this XML tag.
Definition XMLTag.cpp:29
static std::string_view getOccurrenceString(Occurrence occurrence)
Definition XMLTag.cpp:302
typename std::vector< Attribute > Attributes
Definition XMLTag.hpp:43
const std::string & getFullName() const
Returns full name consisting of xml namespace + ":" + name.
Definition XMLTag.hpp:170
Occurrence
Types of occurrences of an XML tag.
Definition XMLTag.hpp:70
void addAttributeHint(std::string name, std::string message)
Adds a hint for missing attributes, which will be displayed along the error message.
Definition XMLTag.cpp:98
XMLTag(Listener &listener, std::string name, Occurrence occurrence, std::string xmlNamespace="")
Standard constructor.
Definition XMLTag.cpp:11
std::map< std::string, std::string > _attributeHints
Definition XMLTag.hpp:233
std::string _name
Name of the tag.
Definition XMLTag.hpp:211
int getIntAttributeValue(const std::string &name, std::optional< int > default_value=std::nullopt) const
Definition XMLTag.cpp:131
std::string _doc
Definition XMLTag.hpp:219
XMLTag & addNamespace(const std::string &namespaceName)
Adds a namespace to the tag.
Definition XMLTag.cpp:35
std::vector< std::string > getAttributeNames() const
Definition XMLTag.cpp:220
Attributes _attributes
Definition XMLTag.hpp:231
double getDoubleAttributeValue(const std::string &name, std::optional< double > default_value=std::nullopt) const
Definition XMLTag.cpp:117
XMLTag & addAttribute(const XMLAttribute< double > &attribute)
Adds a XML attribute by making a copy of the given attribute.
Definition XMLTag.cpp:53
XMLTag & addSubtag(const XMLTag &tag)
Adds an XML tag as subtag by making a copy of the given tag.
Definition XMLTag.cpp:41
void areAllSubtagsConfigured() const
Definition XMLTag.cpp:229
std::variant< XMLAttribute< double >, XMLAttribute< int >, XMLAttribute< std::string >, XMLAttribute< bool >, XMLAttribute< Eigen::VectorXd > > Attribute
Definition XMLTag.hpp:36
T empty(T... args)
T find_if(T... args)
T holds_alternative(T... args)
T make_shared(T... args)
bool isKebabStyle(std::string_view sv)
Definition String.cpp:103
std::vector< StringMatch > computeMatches(std::string_view given, const Container &expected)
Definition String.hpp:95
contains the XML configuration parser.
XMLTag getRootTag()
Returns an empty root tag with name "configuration".
Definition XMLTag.cpp:278
std::string getName(const XMLTag::Attribute &attribute)
Returns the name of an Attribute.
Definition XMLTag.cpp:273
std::string configure(XMLTag &tag, const precice::xml::ConfigurationContext &context, std::string_view configurationFilename)
Configures the given configuration from file configurationFilename.
Definition XMLTag.cpp:284
STL namespace.
static precice::logging::Logger _log("precicec")
T push_back(T... args)
T remove_if(T... args)
Tightly coupled to the parameters of Participant()
Definition XMLTag.hpp:21
No operation listener for tests.
Definition XMLTag.hpp:246
Callback interface for configuration classes using XMLTag.
Definition XMLTag.hpp:46
T transform(T... args)
T value(T... args)
T visit(T... args)