Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/utils/xml/SUMOSAXAttributes.cpp
169678 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2007-2025 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
SUMOSAXAttributes::SUMOSAXAttributes(const std::string& objectType):
46
myObjectType(objectType) {}
47
48
49
const std::string invalid_return<std::string>::value = "";
50
template<>
51
std::string SUMOSAXAttributes::fromString(const std::string& value) const {
52
if (value == "") {
53
throw EmptyData();
54
}
55
return value;
56
}
57
58
59
SUMOTime
60
SUMOSAXAttributes::getSUMOTimeReporting(int attr, const char* objectid,
61
bool& ok, bool report) const {
62
try {
63
bool isPresent = true;
64
const std::string& val = getString(attr, &isPresent);
65
if (!isPresent) {
66
if (report) {
67
emitUngivenError(getName(attr), objectid);
68
}
69
ok = false;
70
return -1;
71
}
72
return string2time(val);
73
} catch (EmptyData&) {
74
if (report) {
75
emitEmptyError(getName(attr), objectid);
76
}
77
} catch (ProcessError&) {
78
if (report) {
79
emitFormatError(getName(attr), "is not a valid time value", objectid);
80
}
81
}
82
ok = false;
83
return -1;
84
}
85
86
87
SUMOTime
88
SUMOSAXAttributes::getPeriod(const char* objectid, bool& ok, bool report) const {
89
int attr = SUMO_ATTR_PERIOD;
90
try {
91
bool isPresent = true;
92
const std::string& val = getString(attr, &isPresent);
93
if (!isPresent) {
94
// try 'freq' as alias for 'period'
95
attr = SUMO_ATTR_FREQUENCY;
96
isPresent = true;
97
const std::string& valFreq = getString(attr, &isPresent);
98
if (!isPresent) {
99
if (report) {
100
emitUngivenError(getName(SUMO_ATTR_PERIOD), objectid);
101
}
102
ok = false;
103
return -1;
104
}
105
return string2time(valFreq);
106
}
107
return string2time(val);
108
} catch (EmptyData&) {
109
if (report) {
110
emitEmptyError(getName(attr), objectid);
111
}
112
} catch (ProcessError&) {
113
if (report) {
114
emitFormatError(getName(attr), "is not a valid time value", objectid);
115
}
116
}
117
ok = false;
118
return -1;
119
}
120
121
122
SUMOTime
123
SUMOSAXAttributes::getOptSUMOTimeReporting(int attr, const char* objectid,
124
bool& ok, SUMOTime defaultValue, bool report) const {
125
try {
126
bool isPresent = true;
127
const std::string& val = getString(attr, &isPresent);
128
if (!isPresent) {
129
return defaultValue;
130
}
131
return string2time(val);
132
} catch (EmptyData&) {
133
if (report) {
134
emitEmptyError(getName(attr), objectid);
135
}
136
} catch (ProcessError&) {
137
if (report) {
138
emitFormatError(getName(attr), "is not a valid time value", objectid);
139
}
140
}
141
ok = false;
142
return -1;
143
}
144
145
146
SUMOTime
147
SUMOSAXAttributes::getOptOffsetReporting(int attr, const char* objectid,
148
bool& ok, SUMOTime defaultValue, bool report) const {
149
try {
150
bool isPresent = true;
151
const std::string& val = getString(attr, &isPresent);
152
if (!isPresent) {
153
return defaultValue;
154
}
155
if (val == "begin") {
156
return SUMOTime_MAX;
157
} else {
158
return string2time(val);
159
}
160
} catch (EmptyData&) {
161
if (report) {
162
emitEmptyError(getName(attr), objectid);
163
}
164
} catch (ProcessError&) {
165
if (report) {
166
emitFormatError(getName(attr), "is not a valid time value", objectid);
167
}
168
}
169
ok = false;
170
return -1;
171
}
172
173
174
SUMOTime
175
SUMOSAXAttributes::getOptPeriod(const char* objectid, bool& ok, SUMOTime defaultValue, bool report) const {
176
int attr = SUMO_ATTR_PERIOD;
177
try {
178
bool isPresent = true;
179
const std::string& val = getString(attr, &isPresent);
180
if (!isPresent) {
181
// try 'freq' as alias for 'period'
182
attr = SUMO_ATTR_FREQUENCY;
183
isPresent = true;
184
const std::string& valFreq = getString(attr, &isPresent);
185
if (!isPresent) {
186
return defaultValue;
187
}
188
return string2time(valFreq);
189
}
190
return string2time(val);
191
} catch (EmptyData&) {
192
if (report) {
193
emitEmptyError(getName(attr), objectid);
194
}
195
} catch (ProcessError&) {
196
if (report) {
197
emitFormatError(getName(attr), "is not a valid time value", objectid);
198
}
199
}
200
ok = false;
201
return -1;
202
}
203
204
205
void
206
SUMOSAXAttributes::emitUngivenError(const std::string& attrname, const char* objectid) const {
207
std::ostringstream oss;
208
oss << "Attribute '" << attrname << "' is missing in definition of ";
209
if (objectid == nullptr || objectid[0] == 0) {
210
oss << "a " << myObjectType;
211
} else {
212
oss << myObjectType << " '" << objectid << "'";
213
}
214
oss << ".";
215
WRITE_ERROR(oss.str());
216
}
217
218
219
void
220
SUMOSAXAttributes::emitEmptyError(const std::string& attrname, const char* objectid) const {
221
std::ostringstream oss;
222
oss << "Attribute '" << attrname << "' in definition of ";
223
if (objectid == nullptr || objectid[0] == 0) {
224
oss << "a " << myObjectType;
225
} else {
226
oss << myObjectType << " '" << objectid << "'";
227
}
228
oss << " is empty.";
229
WRITE_ERROR(oss.str());
230
}
231
232
233
void
234
SUMOSAXAttributes::emitFormatError(const std::string& attrname, const std::string& type, const char* objectid) const {
235
std::ostringstream oss;
236
oss << "Attribute '" << attrname << "' in definition of ";
237
if (objectid == nullptr || objectid[0] == 0) {
238
oss << "a " << myObjectType;
239
} else {
240
oss << myObjectType << " '" << objectid << "'";
241
}
242
oss << " " << type << ".";
243
WRITE_ERROR(oss.str());
244
}
245
246
247
const int invalid_return<int>::value = -1;
248
template<>
249
int SUMOSAXAttributes::fromString(const std::string& value) const {
250
return StringUtils::toInt(value);
251
}
252
253
254
const long long int invalid_return<long long int>::value = -1;
255
template<>
256
long long int SUMOSAXAttributes::fromString(const std::string& value) const {
257
return StringUtils::toLong(value);
258
}
259
260
261
const double invalid_return<double>::value = -1;
262
template<>
263
double SUMOSAXAttributes::fromString(const std::string& value) const {
264
return StringUtils::toDouble(value);
265
}
266
267
268
const bool invalid_return<bool>::value = false;
269
template<>
270
bool SUMOSAXAttributes::fromString(const std::string& value) const {
271
return StringUtils::toBool(value);
272
}
273
274
275
const RGBColor invalid_return<RGBColor>::value = RGBColor();
276
template<>
277
RGBColor SUMOSAXAttributes::fromString(const std::string& value) const {
278
return RGBColor::parseColor(value);
279
}
280
281
282
const Position invalid_return<Position>::value = Position();
283
template<>
284
Position SUMOSAXAttributes::fromString(const std::string& value) const {
285
StringTokenizer st(value);
286
// check StringTokenizer
287
while (st.hasNext()) {
288
// obtain position
289
StringTokenizer pos(st.next(), ",");
290
// check that position has X-Y or X-Y-Z
291
if ((pos.size() != 2) && (pos.size() != 3)) {
292
throw FormatException("is not a valid position");
293
}
294
// obtain x and y
295
double x = StringUtils::toDouble(pos.next());
296
double y = StringUtils::toDouble(pos.next());
297
// check if return a X-Y or a X-Y-Z Position
298
if (pos.size() == 2) {
299
return Position(x, y);
300
} else {
301
// obtain z
302
double z = StringUtils::toDouble(pos.next());
303
return Position(x, y, z);
304
}
305
}
306
// empty positions aren't allowed
307
throw FormatException("is not a valid position");
308
}
309
310
311
const PositionVector invalid_return<PositionVector>::value = PositionVector();
312
template<>
313
PositionVector SUMOSAXAttributes::fromString(const std::string& value) const {
314
StringTokenizer st(value);
315
PositionVector shape;
316
while (st.hasNext()) {
317
StringTokenizer pos(st.next(), ",");
318
if (pos.size() != 2 && pos.size() != 3) {
319
throw FormatException("is not a valid list of positions");
320
}
321
double x = StringUtils::toDouble(pos.next());
322
double y = StringUtils::toDouble(pos.next());
323
if (pos.size() == 2) {
324
shape.push_back(Position(x, y));
325
} else {
326
double z = StringUtils::toDouble(pos.next());
327
shape.push_back(Position(x, y, z));
328
}
329
}
330
return shape;
331
}
332
333
334
const Boundary invalid_return<Boundary>::value = Boundary();
335
template<>
336
Boundary SUMOSAXAttributes::fromString(const std::string& value) const {
337
StringTokenizer st(value, ",");
338
if (st.size() != 4) {
339
throw FormatException("is not a valid boundary");
340
}
341
const double xmin = StringUtils::toDouble(st.next());
342
const double ymin = StringUtils::toDouble(st.next());
343
const double xmax = StringUtils::toDouble(st.next());
344
const double ymax = StringUtils::toDouble(st.next());
345
return Boundary(xmin, ymin, xmax, ymax);
346
}
347
348
349
const SumoXMLEdgeFunc invalid_return<SumoXMLEdgeFunc>::value = SumoXMLEdgeFunc::NORMAL;
350
template<>
351
SumoXMLEdgeFunc SUMOSAXAttributes::fromString(const std::string& value) const {
352
if (SUMOXMLDefinitions::EdgeFunctions.hasString(value)) {
353
return SUMOXMLDefinitions::EdgeFunctions.get(value);
354
}
355
throw FormatException("is not a valid edge function");
356
}
357
358
359
const SumoXMLNodeType invalid_return<SumoXMLNodeType>::value = SumoXMLNodeType::UNKNOWN;
360
template<>
361
SumoXMLNodeType SUMOSAXAttributes::fromString(const std::string& value) const {
362
if (SUMOXMLDefinitions::NodeTypes.hasString(value)) {
363
return SUMOXMLDefinitions::NodeTypes.get(value);
364
}
365
throw FormatException("is not a valid node type");
366
}
367
368
369
const RightOfWay invalid_return<RightOfWay>::value = RightOfWay::DEFAULT;
370
template<>
371
RightOfWay SUMOSAXAttributes::fromString(const std::string& value) const {
372
if (SUMOXMLDefinitions::RightOfWayValues.hasString(value)) {
373
return SUMOXMLDefinitions::RightOfWayValues.get(value);
374
}
375
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
FringeType SUMOSAXAttributes::fromString(const std::string& value) const {
382
if (SUMOXMLDefinitions::FringeTypeValues.hasString(value)) {
383
return SUMOXMLDefinitions::FringeTypeValues.get(value);
384
}
385
throw FormatException("is not a valid fringe type");
386
}
387
388
389
const ParkingType invalid_return<ParkingType>::value = ParkingType::ONROAD;
390
template<>
391
ParkingType SUMOSAXAttributes::fromString(const std::string& value) const {
392
if (value == toString(ParkingType::OPPORTUNISTIC)) {
393
return ParkingType::OPPORTUNISTIC;
394
} else {
395
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
std::vector<std::string> SUMOSAXAttributes::fromString(const std::string& value) const {
403
const std::vector<std::string>& ret = StringTokenizer(value).getVector();
404
if (ret.empty()) {
405
throw EmptyData();
406
}
407
return ret;
408
}
409
410
411
const std::vector<int> invalid_return<std::vector<int> >::value = std::vector<int>();
412
template<>
413
std::vector<int> SUMOSAXAttributes::fromString(const std::string& value) const {
414
const std::vector<std::string>& tmp = StringTokenizer(value).getVector();
415
if (tmp.empty()) {
416
throw EmptyData();
417
}
418
std::vector<int> ret;
419
for (const std::string& s : tmp) {
420
ret.push_back(StringUtils::toInt(s));
421
}
422
return ret;
423
}
424
425
426
const std::vector<double> invalid_return<std::vector<double> >::value = std::vector<double>();
427
template<>
428
std::vector<double> SUMOSAXAttributes::fromString(const std::string& value) const {
429
const std::vector<std::string>& tmp = StringTokenizer(value).getVector();
430
if (tmp.empty()) {
431
throw EmptyData();
432
}
433
std::vector<double> ret;
434
for (const std::string& s : tmp) {
435
ret.push_back(StringUtils::toDouble(s));
436
}
437
return ret;
438
}
439
440
/****************************************************************************/
441
442