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 16588387 : 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 :
166 : /** @brief Tries to read the SUMOTime 'period' attribute
167 : *
168 : * If 'period' cannot be found, tries 'freq' as an alias.
169 : *
170 : * If both attributes do not exist in the current element, the default value is returned.
171 : * If an error occurs on parsing (the attribute is empty, it is not numeric), "ok" is
172 : * set to false. If report is true an error message is written to MsgHandler::getErrorInstance.
173 : *
174 : * Otherwise, "ok" is not changed.
175 : *
176 : * In dependence to the used time representation, either get<int> or get<double>
177 : * is used.
178 : *
179 : * @param[in] objectid The name of the parsed object; used for error message generation
180 : * @param[out] ok Whether the value could be read
181 : * @param[in] defaultValue The value to return if the attribute is not within the element
182 : * @param[in] report Whether errors shall be written to msg handler's error instance
183 : * @return The read value if given and correct; the default value if the attribute does not exist; -1 if an error occurred
184 : */
185 : SUMOTime getOptPeriod(const char* objectid, bool& ok, SUMOTime defaultValue, bool report = true) const;
186 :
187 :
188 :
189 : /// @name virtual methods for retrieving attribute values
190 : /// @{
191 :
192 : /** @brief Returns the information whether the named (by its enum-value) attribute is within the current list
193 : *
194 : * @param[in] id The id of the attribute to search for
195 : * @return Whether the attribute is within the attributes
196 : */
197 : virtual bool hasAttribute(int id) const = 0;
198 :
199 :
200 : /** @brief Returns the information whether the named attribute is within the current list
201 : *
202 : * @param[in] id The name of the attribute to search for
203 : * @return Whether the named attribute is within the attributes
204 : */
205 : virtual bool hasAttribute(const std::string& id) const = 0;
206 :
207 :
208 : /**
209 : * @brief Returns the bool-value of the named (by its enum-value) attribute
210 : *
211 : * Tries to retrieve the attribute from the the attribute list. The retrieved
212 : * attribute (which may be 0) is then parsed using TplConvert<XMLCh>::_2bool.
213 : * If the attribute is empty or ==0, TplConvert<XMLCh>::_2bool throws an
214 : * EmptyData-exception which is passed.
215 : * If the value can not be parsed to a bool, TplConvert<XMLCh>::_2bool throws a
216 : * BoolFormatException-exception which is passed.
217 : *
218 : * @param[in] id The id of the attribute to return the value of
219 : * @return The attribute's value as a bool, if it could be read and parsed
220 : * @exception EmptyData If the attribute is not known or the attribute value is an empty string
221 : * @exception BoolFormatException If the attribute value can not be parsed to a bool
222 : */
223 : inline bool getBool(int id) const {
224 : return StringUtils::toBool(getString(id));
225 : }
226 :
227 : /**
228 : * @brief Returns the int-value of the named (by its enum-value) attribute
229 : *
230 : * Tries to retrieve the attribute from the the attribute list. The retrieved
231 : * attribute (which may be 0) is then parsed using TplConvert<XMLCh>::_2int.
232 : * If the attribute is empty or ==0, TplConvert<XMLCh>::_2int throws an
233 : * EmptyData-exception which is passed.
234 : * If the value can not be parsed to an int, TplConvert<XMLCh>::_2int throws a
235 : * NumberFormatException-exception which is passed.
236 : *
237 : * @param[in] id The id of the attribute to return the value of
238 : * @return The attribute's value as an int, if it could be read and parsed
239 : * @exception EmptyData If the attribute is not known or the attribute value is an empty string
240 : * @exception NumberFormatException If the attribute value can not be parsed to an int
241 : */
242 2549 : inline int getInt(int id) const {
243 5098 : return StringUtils::toInt(getString(id));
244 : }
245 :
246 :
247 : /**
248 : * @brief Returns the long-value of the named (by its enum-value) attribute
249 : *
250 : * Tries to retrieve the attribute from the the attribute list. The retrieved
251 : * attribute (which may be 0) is then parsed using TplConvert<XMLCh>::_2long.
252 : * If the attribute is empty or ==0, TplConvert<XMLCh>::_2long throws an
253 : * EmptyData-exception which is passed.
254 : * If the value can not be parsed to a long, TplConvert<XMLCh>::_2long throws a
255 : * NumberFormatException-exception which is passed.
256 : *
257 : * @param[in] id The id of the attribute to return the value of
258 : * @return The attribute's value as an int, if it could be read and parsed
259 : * @exception EmptyData If the attribute is not known or the attribute value is an empty string
260 : * @exception NumberFormatException If the attribute value can not be parsed to an int
261 : */
262 10 : virtual long long int getLong(int id) const {
263 20 : return StringUtils::toLong(getString(id));
264 : }
265 :
266 :
267 : /**
268 : * @brief Returns the string-value of the named (by its enum-value) attribute
269 : *
270 : * Tries to retrieve the attribute from the the attribute list. The retrieved
271 : * attribute (which may be 0) is then parsed using TplConvert<XMLCh>::_2str.
272 : * If the attribute is ==0, TplConvert<XMLCh>::_2str throws an
273 : * EmptyData-exception which is passed.
274 : *
275 : * @param[in] id The id of the attribute to return the value of
276 : * @return The attribute's value as a string, if it could be read and parsed
277 : * @exception EmptyData If the attribute is not known or the attribute value is an empty string
278 : */
279 : virtual std::string getString(int id, bool* isPresent = nullptr) const = 0;
280 :
281 :
282 : /**
283 : * @brief Returns the string-value of the named (by its enum-value) attribute
284 : *
285 : * Tries to retrieve the attribute from the the attribute list. The retrieved
286 : * attribute (which may be 0) is then parsed using TplConvert<XMLCh>::_2strSec.
287 : * If the attribute is ==0, TplConvert<XMLCh>::_2strSec returns the default value.
288 : *
289 : * @param[in] id The id of the attribute to return the value of
290 : * @param[in] def The default value to return if the attribute is not in attributes
291 : * @return The attribute's value as a string, if it could be read and parsed
292 : * @exception EmptyData If the attribute is not known or the attribute value is an empty string
293 : */
294 : virtual std::string getStringSecure(int id, const std::string& def) const = 0;
295 :
296 :
297 : /**
298 : * @brief Returns the double-value of the named (by its enum-value) attribute
299 : *
300 : * Tries to retrieve the attribute from the the attribute list. The retrieved
301 : * attribute (which may be 0) is then parsed using TplConvert<XMLCh>::_2double.
302 : * If the attribute is empty or ==0, TplConvert<XMLCh>::_2double throws an
303 : * EmptyData-exception which is passed.
304 : * If the value can not be parsed to a double, TplConvert<XMLCh>::_2double throws a
305 : * NumberFormatException-exception which is passed.
306 : *
307 : * @param[in] id The id of the attribute to return the value of
308 : * @return The attribute's value as a float, if it could be read and parsed
309 : * @exception EmptyData If the attribute is not known or the attribute value is an empty string
310 : * @exception NumberFormatException If the attribute value can not be parsed to an double
311 : */
312 15676 : inline double getFloat(int id) const {
313 31352 : return StringUtils::toDouble(getString(id));
314 : }
315 :
316 :
317 : /**
318 : * @brief Returns the double-value of the named attribute
319 : *
320 : * Tries to retrieve the attribute from the the attribute list. The retrieved
321 : * attribute (which may be 0) is then parsed using TplConvert<XMLCh>::_2double.
322 : * If the attribute is empty or ==0, TplConvert<XMLCh>::_2double throws an
323 : * EmptyData-exception which is passed.
324 : * If the value can not be parsed to a double, TplConvert<XMLCh>::_2double throws a
325 : * NumberFormatException-exception which is passed.
326 : *
327 : * @param[in] id The name of the attribute to return the value of
328 : * @return The attribute's value as a float, if it could be read and parsed
329 : * @exception EmptyData If the attribute is not known or the attribute value is an empty string
330 : * @exception NumberFormatException If the attribute value can not be parsed to an double
331 : */
332 : virtual double getFloat(const std::string& id) const = 0;
333 :
334 :
335 : /**
336 : * @brief Returns the string-value of the named (by its enum-value) attribute
337 : *
338 : * Tries to retrieve the attribute from the the attribute list.
339 : * If the attribute is ==0, TplConvert<XMLCh>::_2strSec returns the default value.
340 : * @param[in] id The name of the attribute to return the value of
341 : * @param[in] def The default value to return if the attribute is not in attributes
342 : * @return The attribute's value as a string, if it could be read and parsed
343 : */
344 : virtual std::string getStringSecure(const std::string& id,
345 : const std::string& def) const = 0;
346 : //}
347 :
348 :
349 : /** @brief Converts the given attribute id into a man readable string
350 : *
351 : * @param[in] attr The id of the attribute to return the name of
352 : * @return The name of the described attribute
353 : */
354 : virtual std::string getName(int attr) const = 0;
355 :
356 : /** @brief Prints all attribute names and values into the given stream
357 : *
358 : * @param[in] os The stream to use
359 : */
360 : virtual void serialize(std::ostream& os) const = 0;
361 :
362 : /** @brief Retrieves all attribute names
363 : */
364 : virtual std::vector<std::string> getAttributeNames() const = 0;
365 :
366 : /// @brief return the objecttype to which these attributes belong
367 : const std::string& getObjectType() const {
368 10928 : return myObjectType;
369 : }
370 :
371 : friend std::ostream& operator<<(std::ostream& os, const SUMOSAXAttributes& src);
372 :
373 : /// @brief return a new deep-copy attributes object
374 : virtual SUMOSAXAttributes* clone() const = 0;
375 :
376 : /** @brief The encoding of parsed strings */
377 : static const std::string ENCODING;
378 :
379 :
380 : protected:
381 : template <typename T> T fromString(const std::string& value) const;
382 : void emitUngivenError(const std::string& attrname, const char* objectid) const;
383 : void emitEmptyError(const std::string& attrname, const char* objectid) const;
384 : void emitFormatError(const std::string& attrname, const std::string& type, const char* objectid) const;
385 :
386 : private:
387 : /// @brief Invalidated copy constructor.
388 : SUMOSAXAttributes(const SUMOSAXAttributes& src) = delete;
389 :
390 : /// @brief Invalidated assignment operator.
391 : SUMOSAXAttributes& operator=(const SUMOSAXAttributes& src) = delete;
392 :
393 : /// @brief the object type to use in error reporting
394 : std::string myObjectType;
395 :
396 : };
397 :
398 :
399 : inline std::ostream& operator<<(std::ostream& os, const SUMOSAXAttributes& src) {
400 136 : src.serialize(os);
401 : return os;
402 : }
403 :
404 :
405 : template<typename X> struct invalid_return {
406 : static const X value;
407 : };
408 :
409 : #define INVALID_RETURN(TYPE) \
410 : template<> struct invalid_return<TYPE> { \
411 : static const TYPE value; \
412 : }
413 : INVALID_RETURN(std::string);
414 : INVALID_RETURN(int);
415 : INVALID_RETURN(long long int);
416 : INVALID_RETURN(double);
417 : INVALID_RETURN(bool);
418 : INVALID_RETURN(RGBColor);
419 : INVALID_RETURN(Position);
420 : INVALID_RETURN(PositionVector);
421 : INVALID_RETURN(Boundary);
422 : INVALID_RETURN(SumoXMLEdgeFunc);
423 : INVALID_RETURN(SumoXMLNodeType);
424 : INVALID_RETURN(RightOfWay);
425 : INVALID_RETURN(FringeType);
426 : INVALID_RETURN(ParkingType);
427 : INVALID_RETURN(std::vector<std::string>);
428 : INVALID_RETURN(std::vector<int>);
429 : INVALID_RETURN(std::vector<double>);
430 :
431 :
432 : template <typename T>
433 48975036 : T SUMOSAXAttributes::get(int attr, const char* objectid,
434 : bool& ok, bool report) const {
435 : try {
436 48975036 : bool isPresent = true;
437 48975036 : const std::string& strAttr = getString(attr, &isPresent);
438 48975036 : if (isPresent) {
439 48974591 : return fromString<T>(strAttr);
440 : }
441 445 : if (report) {
442 15389 : emitUngivenError(getName(attr), objectid);
443 : }
444 14959 : } catch (const FormatException& e) {
445 418 : if (report) {
446 960 : emitFormatError(getName(attr), e.what(), objectid);
447 : }
448 28246 : } catch (EmptyData&) {
449 14123 : if (report) {
450 1142 : emitEmptyError(getName(attr), objectid);
451 : }
452 : }
453 14986 : ok = false;
454 13893 : return invalid_return<T>::value;
455 : }
456 :
457 :
458 : template <typename T>
459 53284254 : T SUMOSAXAttributes::getOpt(int attr, const char* objectid,
460 : bool& ok, T defaultValue, bool report) const {
461 : try {
462 53284254 : bool isPresent = true;
463 53284254 : const std::string& strAttr = getString(attr, &isPresent);
464 53284254 : if (isPresent) {
465 8369526 : return fromString<T>(strAttr);
466 : }
467 26804 : return defaultValue;
468 647 : } catch (const FormatException& e) {
469 74 : if (report) {
470 222 : emitFormatError(getName(attr), e.what(), objectid);
471 : }
472 998 : } catch (EmptyData&) {
473 499 : if (report) {
474 184 : emitEmptyError(getName(attr), objectid);
475 : }
476 : }
477 573 : ok = false;
478 100 : return invalid_return<T>::value;
479 : }
|