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.cpp
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 : #include <config.h>
23 :
24 : #include <string>
25 : #include <iostream>
26 : #include <sstream>
27 : #include <utils/common/MsgHandler.h>
28 : #include <utils/common/RGBColor.h>
29 : #include <utils/common/StringTokenizer.h>
30 : #include <utils/common/StringUtils.h>
31 : #include <utils/geom/Boundary.h>
32 : #include <utils/geom/PositionVector.h>
33 : #include "SUMOSAXAttributes.h"
34 :
35 :
36 : // ===========================================================================
37 : // static members
38 : // ===========================================================================
39 : const std::string SUMOSAXAttributes::ENCODING = " encoding=\"UTF-8\"";
40 :
41 :
42 : // ===========================================================================
43 : // method definitions
44 : // ===========================================================================
45 16705363 : SUMOSAXAttributes::SUMOSAXAttributes(const std::string& objectType):
46 16705363 : myObjectType(objectType) {}
47 :
48 :
49 : const std::string invalid_return<std::string>::value = "";
50 : template<>
51 34383631 : std::string SUMOSAXAttributes::fromString(const std::string& value) const {
52 34383631 : if (value == "") {
53 683 : throw EmptyData();
54 : }
55 34382948 : return value;
56 : }
57 :
58 :
59 : SUMOTime
60 551120 : SUMOSAXAttributes::getSUMOTimeReporting(int attr, const char* objectid,
61 : bool& ok, bool report) const {
62 : try {
63 551120 : bool isPresent = true;
64 551120 : const std::string& val = getString(attr, &isPresent);
65 551120 : if (!isPresent) {
66 13 : if (report) {
67 50 : emitUngivenError(getName(attr), objectid);
68 : }
69 13 : ok = false;
70 13 : return -1;
71 : }
72 551107 : return string2time(val);
73 24 : } catch (EmptyData&) {
74 12 : if (report) {
75 24 : emitEmptyError(getName(attr), objectid);
76 : }
77 24 : } catch (ProcessError&) {
78 12 : if (report) {
79 24 : emitFormatError(getName(attr), "is not a valid time value", objectid);
80 : }
81 12 : }
82 24 : ok = false;
83 24 : return -1;
84 : }
85 :
86 :
87 : SUMOTime
88 559 : SUMOSAXAttributes::getPeriod(const char* objectid, bool& ok, bool report) const {
89 : int attr = SUMO_ATTR_PERIOD;
90 : try {
91 559 : bool isPresent = true;
92 559 : const std::string& val = getString(attr, &isPresent);
93 559 : if (!isPresent) {
94 : // try 'freq' as alias for 'period'
95 : attr = SUMO_ATTR_FREQUENCY;
96 528 : isPresent = true;
97 528 : const std::string& valFreq = getString(attr, &isPresent);
98 528 : if (!isPresent) {
99 528 : if (report) {
100 0 : emitUngivenError(getName(SUMO_ATTR_PERIOD), objectid);
101 : }
102 528 : ok = false;
103 528 : return -1;
104 : }
105 0 : return string2time(valFreq);
106 : }
107 31 : return string2time(val);
108 0 : } catch (EmptyData&) {
109 0 : if (report) {
110 0 : emitEmptyError(getName(attr), objectid);
111 : }
112 0 : } catch (ProcessError&) {
113 0 : if (report) {
114 0 : emitFormatError(getName(attr), "is not a valid time value", objectid);
115 : }
116 0 : }
117 0 : ok = false;
118 0 : return -1;
119 : }
120 :
121 :
122 : SUMOTime
123 4728267 : SUMOSAXAttributes::getOptSUMOTimeReporting(int attr, const char* objectid,
124 : bool& ok, SUMOTime defaultValue, bool report) const {
125 : try {
126 4728267 : bool isPresent = true;
127 4728267 : const std::string& val = getString(attr, &isPresent);
128 4728267 : if (!isPresent) {
129 : return defaultValue;
130 : }
131 72340 : return string2time(val);
132 36 : } catch (EmptyData&) {
133 0 : if (report) {
134 0 : emitEmptyError(getName(attr), objectid);
135 : }
136 36 : } catch (ProcessError&) {
137 36 : if (report) {
138 72 : emitFormatError(getName(attr), "is not a valid time value", objectid);
139 : }
140 36 : }
141 36 : ok = false;
142 36 : return -1;
143 : }
144 :
145 :
146 : SUMOTime
147 110601 : SUMOSAXAttributes::getOptOffsetReporting(int attr, const char* objectid,
148 : bool& ok, SUMOTime defaultValue, bool report) const {
149 : try {
150 110601 : bool isPresent = true;
151 110601 : const std::string& val = getString(attr, &isPresent);
152 110601 : if (!isPresent) {
153 : return defaultValue;
154 : }
155 110495 : if (val == "begin") {
156 : return SUMOTime_MAX;
157 : } else {
158 110492 : return string2time(val);
159 : }
160 0 : } catch (EmptyData&) {
161 0 : if (report) {
162 0 : emitEmptyError(getName(attr), objectid);
163 : }
164 0 : } catch (ProcessError&) {
165 0 : if (report) {
166 0 : emitFormatError(getName(attr), "is not a valid time value", objectid);
167 : }
168 0 : }
169 0 : ok = false;
170 0 : return -1;
171 : }
172 :
173 :
174 : SUMOTime
175 30434 : SUMOSAXAttributes::getOptPeriod(const char* objectid, bool& ok, SUMOTime defaultValue, bool report) const {
176 : int attr = SUMO_ATTR_PERIOD;
177 : try {
178 30434 : bool isPresent = true;
179 30434 : const std::string& val = getString(attr, &isPresent);
180 30434 : if (!isPresent) {
181 : // try 'freq' as alias for 'period'
182 : attr = SUMO_ATTR_FREQUENCY;
183 9424 : isPresent = true;
184 9424 : const std::string& valFreq = getString(attr, &isPresent);
185 9424 : if (!isPresent) {
186 : return defaultValue;
187 : }
188 7718 : return string2time(valFreq);
189 : }
190 21010 : return string2time(val);
191 40 : } catch (EmptyData&) {
192 20 : if (report) {
193 40 : emitEmptyError(getName(attr), objectid);
194 : }
195 40 : } catch (ProcessError&) {
196 20 : if (report) {
197 40 : emitFormatError(getName(attr), "is not a valid time value", objectid);
198 : }
199 20 : }
200 40 : ok = false;
201 40 : return -1;
202 : }
203 :
204 :
205 : void
206 292 : SUMOSAXAttributes::emitUngivenError(const std::string& attrname, const char* objectid) const {
207 292 : std::ostringstream oss;
208 292 : oss << "Attribute '" << attrname << "' is missing in definition of ";
209 292 : if (objectid == nullptr || objectid[0] == 0) {
210 : oss << "a " << myObjectType;
211 : } else {
212 160 : oss << myObjectType << " '" << objectid << "'";
213 : }
214 292 : oss << ".";
215 292 : WRITE_ERROR(oss.str());
216 292 : }
217 :
218 :
219 : void
220 550 : SUMOSAXAttributes::emitEmptyError(const std::string& attrname, const char* objectid) const {
221 550 : std::ostringstream oss;
222 550 : oss << "Attribute '" << attrname << "' in definition of ";
223 550 : if (objectid == nullptr || objectid[0] == 0) {
224 : oss << "a " << myObjectType;
225 : } else {
226 392 : oss << myObjectType << " '" << objectid << "'";
227 : }
228 550 : oss << " is empty.";
229 550 : WRITE_ERROR(oss.str());
230 550 : }
231 :
232 :
233 : void
234 302 : SUMOSAXAttributes::emitFormatError(const std::string& attrname, const std::string& type, const char* objectid) const {
235 302 : std::ostringstream oss;
236 302 : oss << "Attribute '" << attrname << "' in definition of ";
237 302 : if (objectid == nullptr || objectid[0] == 0) {
238 : oss << "a " << myObjectType;
239 : } else {
240 282 : oss << myObjectType << " '" << objectid << "'";
241 : }
242 302 : oss << " " << type << ".";
243 302 : WRITE_ERROR(oss.str());
244 302 : }
245 :
246 :
247 : const int invalid_return<int>::value = -1;
248 : template<>
249 12573098 : int SUMOSAXAttributes::fromString(const std::string& value) const {
250 12573098 : return StringUtils::toInt(value);
251 : }
252 :
253 :
254 : const long long int invalid_return<long long int>::value = -1;
255 : template<>
256 993121 : long long int SUMOSAXAttributes::fromString(const std::string& value) const {
257 993121 : return StringUtils::toLong(value);
258 : }
259 :
260 :
261 : const double invalid_return<double>::value = -1;
262 : template<>
263 9082975 : double SUMOSAXAttributes::fromString(const std::string& value) const {
264 9082975 : return StringUtils::toDouble(value);
265 : }
266 :
267 :
268 : const bool invalid_return<bool>::value = false;
269 : template<>
270 960118 : bool SUMOSAXAttributes::fromString(const std::string& value) const {
271 960118 : return StringUtils::toBool(value);
272 : }
273 :
274 :
275 : const RGBColor invalid_return<RGBColor>::value = RGBColor();
276 : template<>
277 65210 : RGBColor SUMOSAXAttributes::fromString(const std::string& value) const {
278 130412 : return RGBColor::parseColor(value);
279 : }
280 :
281 :
282 : const Position invalid_return<Position>::value = Position();
283 : template<>
284 0 : Position SUMOSAXAttributes::fromString(const std::string& value) const {
285 0 : StringTokenizer st(value);
286 : // check StringTokenizer
287 0 : while (st.hasNext()) {
288 : // obtain position
289 0 : StringTokenizer pos(st.next(), ",");
290 : // check that position has X-Y or X-Y-Z
291 0 : if ((pos.size() != 2) && (pos.size() != 3)) {
292 0 : throw FormatException("is not a valid position");
293 : }
294 : // obtain x and y
295 0 : double x = StringUtils::toDouble(pos.next());
296 0 : double y = StringUtils::toDouble(pos.next());
297 : // check if return a X-Y or a X-Y-Z Position
298 0 : if (pos.size() == 2) {
299 : return Position(x, y);
300 : } else {
301 : // obtain z
302 0 : double z = StringUtils::toDouble(pos.next());
303 : return Position(x, y, z);
304 : }
305 0 : }
306 : // empty positions aren't allowed
307 0 : throw FormatException("is not a valid position");
308 0 : }
309 :
310 :
311 : const PositionVector invalid_return<PositionVector>::value = PositionVector();
312 : template<>
313 3270968 : PositionVector SUMOSAXAttributes::fromString(const std::string& value) const {
314 3270968 : StringTokenizer st(value);
315 3270968 : PositionVector shape;
316 14915304 : while (st.hasNext()) {
317 23288888 : StringTokenizer pos(st.next(), ",");
318 11644444 : if (pos.size() != 2 && pos.size() != 3) {
319 84 : throw FormatException("is not a valid list of positions");
320 : }
321 11644402 : double x = StringUtils::toDouble(pos.next());
322 11644466 : double y = StringUtils::toDouble(pos.next());
323 11644336 : if (pos.size() == 2) {
324 11616681 : shape.push_back(Position(x, y));
325 : } else {
326 27655 : double z = StringUtils::toDouble(pos.next());
327 27655 : shape.push_back(Position(x, y, z));
328 : }
329 11644444 : }
330 3270860 : return shape;
331 3271076 : }
332 :
333 :
334 : const Boundary invalid_return<Boundary>::value = Boundary();
335 : template<>
336 107624 : Boundary SUMOSAXAttributes::fromString(const std::string& value) const {
337 322872 : StringTokenizer st(value, ",");
338 107624 : if (st.size() != 4) {
339 0 : throw FormatException("is not a valid boundary");
340 : }
341 107624 : const double xmin = StringUtils::toDouble(st.next());
342 107624 : const double ymin = StringUtils::toDouble(st.next());
343 107624 : const double xmax = StringUtils::toDouble(st.next());
344 107624 : const double ymax = StringUtils::toDouble(st.next());
345 215248 : return Boundary(xmin, ymin, xmax, ymax);
346 107624 : }
347 :
348 :
349 : const SumoXMLEdgeFunc invalid_return<SumoXMLEdgeFunc>::value = SumoXMLEdgeFunc::NORMAL;
350 : template<>
351 1398596 : SumoXMLEdgeFunc SUMOSAXAttributes::fromString(const std::string& value) const {
352 : if (SUMOXMLDefinitions::EdgeFunctions.hasString(value)) {
353 1398586 : return SUMOXMLDefinitions::EdgeFunctions.get(value);
354 : }
355 20 : throw FormatException("is not a valid edge function");
356 : }
357 :
358 :
359 : const SumoXMLNodeType invalid_return<SumoXMLNodeType>::value = SumoXMLNodeType::UNKNOWN;
360 : template<>
361 721388 : SumoXMLNodeType SUMOSAXAttributes::fromString(const std::string& value) const {
362 : if (SUMOXMLDefinitions::NodeTypes.hasString(value)) {
363 721358 : return SUMOXMLDefinitions::NodeTypes.get(value);
364 : }
365 60 : throw FormatException("is not a valid node type");
366 : }
367 :
368 :
369 : const RightOfWay invalid_return<RightOfWay>::value = RightOfWay::DEFAULT;
370 : template<>
371 4 : RightOfWay SUMOSAXAttributes::fromString(const std::string& value) const {
372 : if (SUMOXMLDefinitions::RightOfWayValues.hasString(value)) {
373 4 : return SUMOXMLDefinitions::RightOfWayValues.get(value);
374 : }
375 0 : throw FormatException("is not a valid right of way value");
376 : }
377 :
378 :
379 : const FringeType invalid_return<FringeType>::value = FringeType::DEFAULT;
380 : template<>
381 232 : FringeType SUMOSAXAttributes::fromString(const std::string& value) const {
382 : if (SUMOXMLDefinitions::FringeTypeValues.hasString(value)) {
383 232 : return SUMOXMLDefinitions::FringeTypeValues.get(value);
384 : }
385 0 : throw FormatException("is not a valid fringe type");
386 : }
387 :
388 :
389 : const ParkingType invalid_return<ParkingType>::value = ParkingType::ONROAD;
390 : template<>
391 959 : ParkingType SUMOSAXAttributes::fromString(const std::string& value) const {
392 959 : if (value == toString(ParkingType::OPPORTUNISTIC)) {
393 : return ParkingType::OPPORTUNISTIC;
394 : } else {
395 959 : return StringUtils::toBool(value) ? ParkingType::OFFROAD : ParkingType::ONROAD;
396 : }
397 : }
398 :
399 :
400 : const std::vector<std::string> invalid_return<std::vector<std::string> >::value = std::vector<std::string>();
401 : template<>
402 47952 : std::vector<std::string> SUMOSAXAttributes::fromString(const std::string& value) const {
403 95904 : const std::vector<std::string>& ret = StringTokenizer(value).getVector();
404 47952 : if (ret.empty()) {
405 8634 : throw EmptyData();
406 : }
407 78636 : return ret;
408 47952 : }
409 :
410 :
411 : const std::vector<int> invalid_return<std::vector<int> >::value = std::vector<int>();
412 : template<>
413 299 : std::vector<int> SUMOSAXAttributes::fromString(const std::string& value) const {
414 598 : const std::vector<std::string>& tmp = StringTokenizer(value).getVector();
415 299 : if (tmp.empty()) {
416 0 : throw EmptyData();
417 : }
418 : std::vector<int> ret;
419 721 : for (const std::string& s : tmp) {
420 422 : ret.push_back(StringUtils::toInt(s));
421 : }
422 299 : return ret;
423 299 : }
424 :
425 :
426 : const std::vector<double> invalid_return<std::vector<double> >::value = std::vector<double>();
427 : template<>
428 0 : std::vector<double> SUMOSAXAttributes::fromString(const std::string& value) const {
429 0 : const std::vector<std::string>& tmp = StringTokenizer(value).getVector();
430 0 : if (tmp.empty()) {
431 0 : throw EmptyData();
432 : }
433 : std::vector<double> ret;
434 0 : for (const std::string& s : tmp) {
435 0 : ret.push_back(StringUtils::toDouble(s));
436 : }
437 0 : return ret;
438 0 : }
439 :
440 : /****************************************************************************/
|