Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2007-2024 German Aerospace Center (DLR) and others.
4 : // This program and the accompanying materials are made available under the
5 : // terms of the Eclipse Public License 2.0 which is available at
6 : // https://www.eclipse.org/legal/epl-2.0/
7 : // This Source Code may also be made available under the following Secondary
8 : // Licenses when the conditions for such availability set forth in the Eclipse
9 : // Public License 2.0 are satisfied: GNU General Public License, version 2
10 : // or later which is available at
11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 : /****************************************************************************/
14 : /// @file SUMOSAXAttributes.h
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Michael Behrisch
18 : /// @date Fri, 30 Mar 2007
19 : ///
20 : // Encapsulated SAX-Attributes
21 : /****************************************************************************/
22 : #pragma once
23 : #include <config.h>
24 :
25 : #include <string>
26 : #include <vector>
27 : #include <set>
28 :
29 : #include <utils/common/StringUtils.h>
30 : #include <utils/common/SUMOTime.h>
31 : #include <utils/common/ToString.h>
32 : #include <utils/common/UtilExceptions.h>
33 : #include "SUMOXMLDefinitions.h"
34 :
35 :
36 : // ===========================================================================
37 : // class declarations
38 : // ===========================================================================
39 : class Position;
40 : class PositionVector;
41 : class Boundary;
42 : class RGBColor;
43 :
44 :
45 : // ===========================================================================
46 : // class definitions
47 : // ===========================================================================
48 : /**
49 : * @class SUMOSAXAttributes
50 : * @brief Encapsulated SAX-Attributes
51 : *
52 : * This class is an interface for using encapsulated SAX-attributes.
53 : * Encapsulation is done to allow a common access without the need to
54 : * import all the Xerces-definitions.
55 : */
56 : class SUMOSAXAttributes {
57 : public:
58 : /* @brief Constructor
59 : * @param[in] tagName The name of the parsed object type; used for error message generation
60 : */
61 : SUMOSAXAttributes(const std::string& objectType);
62 :
63 :
64 : /// @brief Destructor
65 16875618 : virtual ~SUMOSAXAttributes() { }
66 :
67 :
68 : /** @brief Tries to read given attribute assuming it is an int
69 : *
70 : * If an error occurs (the attribute is not there, it is not numeric), "ok" is
71 : * set to false. If report is true an error message is written to MsgHandler::getErrorInstance.
72 : *
73 : * If the value could be read, "ok" is not changed, and the value is returned.
74 : *
75 : * @param[in] attr The id of the attribute to read
76 : * @param[in] objectid The name of the parsed object; used for error message generation
77 : * @param[out] ok Whether the value could be read
78 : * @param[in] report Whether errors shall be written to msg handler's error instance
79 : * @return The read value if given and correct; -1 if an error occurred
80 : */
81 : template <typename T>
82 : T get(int attr, const char* objectid, bool& ok, bool report = true) const;
83 :
84 :
85 : /** @brief Tries to read given attribute assuming it is an int
86 : *
87 : * If the attribute is not existing in the current element, the default value is returned.
88 : * If an error occurs on parsing (the attribute is empty, it is not numeric), "ok" is
89 : * set to false. If report is true an error message is written to MsgHandler::getErrorInstance.
90 : *
91 : * If the value could be read, "ok" is not changed, and the value is returned.
92 : *
93 : * @param[in] attr The id of the attribute to read
94 : * @param[in] objectid The name of the parsed object; used for error message generation
95 : * @param[out] ok Whether the value could be read
96 : * @param[in] defaultValue The value to return if the attribute is not within the element
97 : * @param[in] report Whether errors shall be written to msg handler's error instance
98 : * @return The read value if given and correct; the default value if the attribute does not exist; -1 if an error occurred
99 : */
100 : template <typename T>
101 : T getOpt(int attr, const char* objectid, bool& ok, T defaultValue = T(), bool report = true) const;
102 :
103 :
104 : /** @brief Tries to read given attribute assuming it is a SUMOTime
105 : *
106 : * If an error occurs (the attribute is not there, it is not numeric), "ok" is
107 : * set to false and an error message is written to MsgHandler::getErrorInstance.
108 : *
109 : * Otherwise, "ok" is not changed.
110 : *
111 : * In dependence to the used time representation, either get<int> or get<double>
112 : * is used.
113 : *
114 : * @param[in] attr The id of the attribute to read
115 : * @param[in] objectid The name of the parsed object; used for error message generation
116 : * @param[out] ok Whether the value could be read
117 : * @param[in] report Whether errors shall be written to msg handler's error instance
118 : * @return The read value if given and correct; -1 if an error occurred
119 : */
120 : SUMOTime getSUMOTimeReporting(int attr, const char* objectid, bool& ok,
121 : bool report = true) const;
122 :
123 :
124 : /** @brief Tries to read the SUMOTime 'period' attribute
125 : *
126 : * If 'period' cannot be found, tries 'freq' as an alias.
127 : *
128 : * If an error occurs (the attribute is not there, it is not numeric), "ok" is
129 : * set to false and an error message is written to MsgHandler::getErrorInstance.
130 : *
131 : * Otherwise, "ok" is not changed.
132 : *
133 : * In dependence to the used time representation, either get<int> or get<double>
134 : * is used.
135 : *
136 : * @param[in] objectid The name of the parsed object; used for error message generation
137 : * @param[out] ok Whether the value could be read
138 : * @param[in] report Whether errors shall be written to msg handler's error instance
139 : * @return The read value if given and correct; -1 if an error occurred
140 : */
141 : SUMOTime getPeriod(const char* objectid, bool& ok, bool report = true) const;
142 :
143 :
144 : /** @brief Tries to read given attribute assuming it is a SUMOTime
145 : *
146 : * If the attribute is not existing in the current element, the default value is returned.
147 : * If an error occurs on parsing (the attribute is empty, it is not numeric), "ok" is
148 : * set to false. If report is true an error message is written to MsgHandler::getErrorInstance.
149 : *
150 : * Otherwise, "ok" is not changed.
151 : *
152 : * In dependence to the used time representation, either get<int> or get<double>
153 : * is used.
154 : *
155 : * @param[in] attr The id of the attribute to read
156 : * @param[in] objectid The name of the parsed object; used for error message generation
157 : * @param[out] ok Whether the value could be read
158 : * @param[in] defaultValue The value to return if the attribute is not within the element
159 : * @param[in] report Whether errors shall be written to msg handler's error instance
160 : * @return The read value if given and correct; the default value if the attribute does not exist; -1 if an error occurred
161 : */
162 : SUMOTime getOptSUMOTimeReporting(int attr, const char* objectid, bool& ok,
163 : SUMOTime defaultValue, bool report = true) const;
164 :
165 : /** @brief Tries to read given attribute assuming it is a tls offset
166 : * (SUMOTime or "begin")
167 : *
168 : * If the attribute is not existing in the current element, the default value is returned.
169 : * If an error occurs on parsing (the attribute is empty, it is not numeric), "ok" is
170 : * set to false. If report is true an error message is written to MsgHandler::getErrorInstance.
171 : *
172 : * Otherwise, "ok" is not changed.
173 : *
174 : * In dependence to the used time representation, either get<int> or get<double>
175 : * is used.
176 : *
177 : * @param[in] attr The id of the attribute to read
178 : * @param[in] objectid The name of the parsed object; used for error message generation
179 : * @param[out] ok Whether the value could be read
180 : * @param[in] defaultValue The value to return if the attribute is not within the element
181 : * @param[in] report Whether errors shall be written to msg handler's error instance
182 : * @return The read value if given and correct; the default value if the attribute does not exist; -1 if an error occurred
183 : */
184 : SUMOTime getOptOffsetReporting(int attr, const char* objectid, bool& ok,
185 : SUMOTime defaultValue, bool report = true) const;
186 :
187 : /** @brief Tries to read the SUMOTime 'period' attribute
188 : *
189 : * If 'period' cannot be found, tries 'freq' as an alias.
190 : *
191 : * If both attributes do not exist in the current element, the default value is returned.
192 : * If an error occurs on parsing (the attribute is empty, it is not numeric), "ok" is
193 : * set to false. If report is true an error message is written to MsgHandler::getErrorInstance.
194 : *
195 : * Otherwise, "ok" is not changed.
196 : *
197 : * In dependence to the used time representation, either get<int> or get<double>
198 : * is used.
199 : *
200 : * @param[in] objectid The name of the parsed object; used for error message generation
201 : * @param[out] ok Whether the value could be read
202 : * @param[in] defaultValue The value to return if the attribute is not within the element
203 : * @param[in] report Whether errors shall be written to msg handler's error instance
204 : * @return The read value if given and correct; the default value if the attribute does not exist; -1 if an error occurred
205 : */
206 : SUMOTime getOptPeriod(const char* objectid, bool& ok, SUMOTime defaultValue, bool report = true) const;
207 :
208 :
209 :
210 : /// @name virtual methods for retrieving attribute values
211 : /// @{
212 :
213 : /** @brief Returns the information whether the named (by its enum-value) attribute is within the current list
214 : *
215 : * @param[in] id The id of the attribute to search for
216 : * @return Whether the attribute is within the attributes
217 : */
218 : virtual bool hasAttribute(int id) const = 0;
219 :
220 :
221 : /** @brief Returns the information whether the named attribute is within the current list
222 : *
223 : * @param[in] id The name of the attribute to search for
224 : * @return Whether the named attribute is within the attributes
225 : */
226 : virtual bool hasAttribute(const std::string& id) const = 0;
227 :
228 :
229 : /**
230 : * @brief Returns the bool-value of the named (by its enum-value) attribute
231 : *
232 : * Tries to retrieve the attribute from the attribute list. The retrieved
233 : * attribute (which may be 0) is then parsed using TplConvert<XMLCh>::_2bool.
234 : * If the attribute is empty or ==0, TplConvert<XMLCh>::_2bool throws an
235 : * EmptyData-exception which is passed.
236 : * If the value can not be parsed to a bool, TplConvert<XMLCh>::_2bool throws a
237 : * BoolFormatException-exception which is passed.
238 : *
239 : * @param[in] id The id of the attribute to return the value of
240 : * @return The attribute's value as a bool, if it could be read and parsed
241 : * @exception EmptyData If the attribute is not known or the attribute value is an empty string
242 : * @exception BoolFormatException If the attribute value can not be parsed to a bool
243 : */
244 : inline bool getBool(int id) const {
245 : return StringUtils::toBool(getString(id));
246 : }
247 :
248 : /**
249 : * @brief Returns the int-value of the named (by its enum-value) attribute
250 : *
251 : * Tries to retrieve the attribute from the attribute list. The retrieved
252 : * attribute (which may be 0) is then parsed using TplConvert<XMLCh>::_2int.
253 : * If the attribute is empty or ==0, TplConvert<XMLCh>::_2int throws an
254 : * EmptyData-exception which is passed.
255 : * If the value can not be parsed to an int, TplConvert<XMLCh>::_2int throws a
256 : * NumberFormatException-exception which is passed.
257 : *
258 : * @param[in] id The id of the attribute to return the value of
259 : * @return The attribute's value as an int, if it could be read and parsed
260 : * @exception EmptyData If the attribute is not known or the attribute value is an empty string
261 : * @exception NumberFormatException If the attribute value can not be parsed to an int
262 : */
263 2053 : inline int getInt(int id) const {
264 4106 : return StringUtils::toInt(getString(id));
265 : }
266 :
267 :
268 : /**
269 : * @brief Returns the long-value of the named (by its enum-value) attribute
270 : *
271 : * Tries to retrieve the attribute from the attribute list. The retrieved
272 : * attribute (which may be 0) is then parsed using TplConvert<XMLCh>::_2long.
273 : * If the attribute is empty or ==0, TplConvert<XMLCh>::_2long throws an
274 : * EmptyData-exception which is passed.
275 : * If the value can not be parsed to a long, TplConvert<XMLCh>::_2long throws a
276 : * NumberFormatException-exception which is passed.
277 : *
278 : * @param[in] id The id of the attribute to return the value of
279 : * @return The attribute's value as an int, if it could be read and parsed
280 : * @exception EmptyData If the attribute is not known or the attribute value is an empty string
281 : * @exception NumberFormatException If the attribute value can not be parsed to an int
282 : */
283 185 : virtual long long int getLong(int id) const {
284 370 : return StringUtils::toLong(getString(id));
285 : }
286 :
287 :
288 : /**
289 : * @brief Returns the string-value of the named (by its enum-value) attribute
290 : *
291 : * Tries to retrieve the attribute from the attribute list. The retrieved
292 : * attribute (which may be 0) is then parsed using TplConvert<XMLCh>::_2str.
293 : * If the attribute is ==0, TplConvert<XMLCh>::_2str throws an
294 : * EmptyData-exception which is passed.
295 : *
296 : * @param[in] id The id of the attribute to return the value of
297 : * @return The attribute's value as a string, if it could be read and parsed
298 : * @exception EmptyData If the attribute is not known or the attribute value is an empty string
299 : */
300 : virtual std::string getString(int id, bool* isPresent = nullptr) const = 0;
301 :
302 :
303 : /**
304 : * @brief Returns the string-value of the named (by its enum-value) attribute
305 : *
306 : * Tries to retrieve the attribute from the attribute list. The retrieved
307 : * attribute (which may be 0) is then parsed using TplConvert<XMLCh>::_2strSec.
308 : * If the attribute is ==0, TplConvert<XMLCh>::_2strSec returns the default value.
309 : *
310 : * @param[in] id The id of the attribute to return the value of
311 : * @param[in] def The default value to return if the attribute is not in attributes
312 : * @return The attribute's value as a string, if it could be read and parsed
313 : * @exception EmptyData If the attribute is not known or the attribute value is an empty string
314 : */
315 : virtual std::string getStringSecure(int id, const std::string& def) const = 0;
316 :
317 :
318 : /**
319 : * @brief Returns the double-value of the named (by its enum-value) attribute
320 : *
321 : * Tries to retrieve the attribute from the attribute list. The retrieved
322 : * attribute (which may be 0) is then parsed using TplConvert<XMLCh>::_2double.
323 : * If the attribute is empty or ==0, TplConvert<XMLCh>::_2double throws an
324 : * EmptyData-exception which is passed.
325 : * If the value can not be parsed to a double, TplConvert<XMLCh>::_2double throws a
326 : * NumberFormatException-exception which is passed.
327 : *
328 : * @param[in] id The id of the attribute to return the value of
329 : * @return The attribute's value as a float, if it could be read and parsed
330 : * @exception EmptyData If the attribute is not known or the attribute value is an empty string
331 : * @exception NumberFormatException If the attribute value can not be parsed to an double
332 : */
333 13984 : inline double getFloat(int id) const {
334 27968 : return StringUtils::toDouble(getString(id));
335 : }
336 :
337 :
338 : /**
339 : * @brief Returns the double-value of the named attribute
340 : *
341 : * Tries to retrieve the attribute from the attribute list. The retrieved
342 : * attribute (which may be 0) is then parsed using TplConvert<XMLCh>::_2double.
343 : * If the attribute is empty or ==0, TplConvert<XMLCh>::_2double throws an
344 : * EmptyData-exception which is passed.
345 : * If the value can not be parsed to a double, TplConvert<XMLCh>::_2double throws a
346 : * NumberFormatException-exception which is passed.
347 : *
348 : * @param[in] id The name of the attribute to return the value of
349 : * @return The attribute's value as a float, if it could be read and parsed
350 : * @exception EmptyData If the attribute is not known or the attribute value is an empty string
351 : * @exception NumberFormatException If the attribute value can not be parsed to an double
352 : */
353 : virtual double getFloat(const std::string& id) const = 0;
354 :
355 :
356 : /**
357 : * @brief Returns the string-value of the named (by its enum-value) attribute
358 : *
359 : * Tries to retrieve the attribute from the attribute list.
360 : * If the attribute is ==0, TplConvert<XMLCh>::_2strSec returns the default value.
361 : * @param[in] id The name of the attribute to return the value of
362 : * @param[in] def The default value to return if the attribute is not in attributes
363 : * @return The attribute's value as a string, if it could be read and parsed
364 : */
365 : virtual std::string getStringSecure(const std::string& id,
366 : const std::string& def) const = 0;
367 : //}
368 :
369 :
370 : /** @brief Converts the given attribute id into a man readable string
371 : *
372 : * @param[in] attr The id of the attribute to return the name of
373 : * @return The name of the described attribute
374 : */
375 : virtual std::string getName(int attr) const = 0;
376 :
377 : /** @brief Prints all attribute names and values into the given stream
378 : *
379 : * @param[in] os The stream to use
380 : */
381 : virtual void serialize(std::ostream& os) const = 0;
382 :
383 : /** @brief Retrieves all attribute names
384 : */
385 : virtual std::vector<std::string> getAttributeNames() const = 0;
386 :
387 : /// @brief return the objecttype to which these attributes belong
388 : const std::string& getObjectType() const {
389 10236 : return myObjectType;
390 : }
391 :
392 : friend std::ostream& operator<<(std::ostream& os, const SUMOSAXAttributes& src);
393 :
394 : /// @brief return a new deep-copy attributes object
395 : virtual SUMOSAXAttributes* clone() const = 0;
396 :
397 : /** @brief The encoding of parsed strings */
398 : static const std::string ENCODING;
399 :
400 :
401 : protected:
402 : template <typename T> T fromString(const std::string& value) const;
403 : void emitUngivenError(const std::string& attrname, const char* objectid) const;
404 : void emitEmptyError(const std::string& attrname, const char* objectid) const;
405 : void emitFormatError(const std::string& attrname, const std::string& type, const char* objectid) const;
406 :
407 : private:
408 : /// @brief Invalidated copy constructor.
409 : SUMOSAXAttributes(const SUMOSAXAttributes& src) = delete;
410 :
411 : /// @brief Invalidated assignment operator.
412 : SUMOSAXAttributes& operator=(const SUMOSAXAttributes& src) = delete;
413 :
414 : /// @brief the object type to use in error reporting
415 : std::string myObjectType;
416 :
417 : };
418 :
419 :
420 : inline std::ostream& operator<<(std::ostream& os, const SUMOSAXAttributes& src) {
421 136 : src.serialize(os);
422 : return os;
423 : }
424 :
425 :
426 : template<typename X> struct invalid_return {
427 : static const X value;
428 : };
429 :
430 : #define INVALID_RETURN(TYPE) \
431 : template<> struct invalid_return<TYPE> { \
432 : static const TYPE value; \
433 : }
434 : INVALID_RETURN(std::string);
435 : INVALID_RETURN(int);
436 : INVALID_RETURN(long long int);
437 : INVALID_RETURN(double);
438 : INVALID_RETURN(bool);
439 : INVALID_RETURN(RGBColor);
440 : INVALID_RETURN(Position);
441 : INVALID_RETURN(PositionVector);
442 : INVALID_RETURN(Boundary);
443 : INVALID_RETURN(SumoXMLEdgeFunc);
444 : INVALID_RETURN(SumoXMLNodeType);
445 : INVALID_RETURN(RightOfWay);
446 : INVALID_RETURN(FringeType);
447 : INVALID_RETURN(ParkingType);
448 : INVALID_RETURN(std::vector<std::string>);
449 : INVALID_RETURN(std::vector<int>);
450 : INVALID_RETURN(std::vector<double>);
451 :
452 :
453 : template <typename T>
454 55283002 : T SUMOSAXAttributes::get(int attr, const char* objectid,
455 : bool& ok, bool report) const {
456 : try {
457 55283002 : bool isPresent = true;
458 55283002 : const std::string& strAttr = getString(attr, &isPresent);
459 55283002 : if (isPresent) {
460 55282702 : return fromString<T>(strAttr);
461 : }
462 300 : if (report) {
463 9903 : emitUngivenError(getName(attr), objectid);
464 : }
465 9589 : } catch (const FormatException& e) {
466 244 : if (report) {
467 352 : emitFormatError(getName(attr), e.what(), objectid);
468 : }
469 18202 : } catch (EmptyData&) {
470 9101 : if (report) {
471 868 : emitEmptyError(getName(attr), objectid);
472 : }
473 : }
474 9645 : ok = false;
475 8886 : return invalid_return<T>::value;
476 : }
477 :
478 :
479 : template <typename T>
480 62599521 : T SUMOSAXAttributes::getOpt(int attr, const char* objectid,
481 : bool& ok, T defaultValue, bool report) const {
482 : try {
483 62599521 : bool isPresent = true;
484 62599521 : const std::string& strAttr = getString(attr, &isPresent);
485 62599521 : if (isPresent) {
486 8893178 : return fromString<T>(strAttr);
487 : }
488 28331978 : return defaultValue;
489 417 : } catch (const FormatException& e) {
490 58 : if (report) {
491 116 : emitFormatError(getName(attr), e.what(), objectid);
492 : }
493 602 : } catch (EmptyData&) {
494 301 : if (report) {
495 168 : emitEmptyError(getName(attr), objectid);
496 : }
497 : }
498 359 : ok = false;
499 84 : return invalid_return<T>::value;
500 : }
|