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 16588388 : SUMOSAXAttributes::SUMOSAXAttributes(const std::string& objectType):
46 16588388 : myObjectType(objectType) {}
47 :
48 :
49 : const std::string invalid_return<std::string>::value = "";
50 : template<>
51 31683916 : std::string SUMOSAXAttributes::fromString(const std::string& value) const {
52 31683916 : if (value == "") {
53 998 : throw EmptyData();
54 : }
55 31682918 : return value;
56 : }
57 :
58 :
59 : SUMOTime
60 587791 : SUMOSAXAttributes::getSUMOTimeReporting(int attr, const char* objectid,
61 : bool& ok, bool report) const {
62 : try {
63 587791 : bool isPresent = true;
64 587791 : const std::string& val = getString(attr, &isPresent);
65 587791 : if (!isPresent) {
66 13 : if (report) {
67 50 : emitUngivenError(getName(attr), objectid);
68 : }
69 13 : ok = false;
70 13 : return -1;
71 : }
72 587778 : 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 36 : 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 1071 : SUMOSAXAttributes::getPeriod(const char* objectid, bool& ok, bool report) const {
89 : int attr = SUMO_ATTR_PERIOD;
90 : try {
91 1071 : bool isPresent = true;
92 1071 : const std::string& val = getString(attr, &isPresent);
93 1071 : if (!isPresent) {
94 : // try 'freq' as alias for 'period'
95 : attr = SUMO_ATTR_FREQUENCY;
96 1046 : isPresent = true;
97 1046 : const std::string& valFreq = getString(attr, &isPresent);
98 1046 : if (!isPresent) {
99 1046 : if (report) {
100 0 : emitUngivenError(getName(SUMO_ATTR_PERIOD), objectid);
101 : }
102 1046 : ok = false;
103 1046 : return -1;
104 : }
105 0 : return string2time(valFreq);
106 : }
107 25 : 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 5261420 : SUMOSAXAttributes::getOptSUMOTimeReporting(int attr, const char* objectid,
124 : bool& ok, SUMOTime defaultValue, bool report) const {
125 : try {
126 5261420 : bool isPresent = true;
127 5261420 : const std::string& val = getString(attr, &isPresent);
128 5261420 : if (!isPresent) {
129 : return defaultValue;
130 : }
131 157203 : 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 108 : 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 15187 : SUMOSAXAttributes::getOptPeriod(const char* objectid, bool& ok, SUMOTime defaultValue, bool report) const {
148 : int attr = SUMO_ATTR_PERIOD;
149 : try {
150 15187 : bool isPresent = true;
151 15187 : const std::string& val = getString(attr, &isPresent);
152 15187 : if (!isPresent) {
153 : // try 'freq' as alias for 'period'
154 : attr = SUMO_ATTR_FREQUENCY;
155 11417 : isPresent = true;
156 11417 : const std::string& valFreq = getString(attr, &isPresent);
157 11417 : if (!isPresent) {
158 : return defaultValue;
159 : }
160 10107 : return string2time(valFreq);
161 : }
162 3770 : return string2time(val);
163 40 : } catch (EmptyData&) {
164 20 : if (report) {
165 40 : emitEmptyError(getName(attr), objectid);
166 : }
167 40 : } catch (ProcessError&) {
168 20 : if (report) {
169 60 : emitFormatError(getName(attr), "is not a valid time value", objectid);
170 : }
171 20 : }
172 40 : ok = false;
173 40 : return -1;
174 : }
175 :
176 :
177 : void
178 437 : SUMOSAXAttributes::emitUngivenError(const std::string& attrname, const char* objectid) const {
179 437 : std::ostringstream oss;
180 437 : oss << "Attribute '" << attrname << "' is missing in definition of ";
181 437 : if (objectid == nullptr || objectid[0] == 0) {
182 : oss << "a " << myObjectType;
183 : } else {
184 240 : oss << myObjectType << " '" << objectid << "'";
185 : }
186 437 : oss << ".";
187 437 : WRITE_ERROR(oss.str());
188 437 : }
189 :
190 :
191 : void
192 695 : SUMOSAXAttributes::emitEmptyError(const std::string& attrname, const char* objectid) const {
193 695 : std::ostringstream oss;
194 695 : oss << "Attribute '" << attrname << "' in definition of ";
195 695 : if (objectid == nullptr || objectid[0] == 0) {
196 : oss << "a " << myObjectType;
197 : } else {
198 452 : oss << myObjectType << " '" << objectid << "'";
199 : }
200 695 : oss << " is empty.";
201 695 : WRITE_ERROR(oss.str());
202 695 : }
203 :
204 :
205 : void
206 462 : SUMOSAXAttributes::emitFormatError(const std::string& attrname, const std::string& type, const char* objectid) const {
207 462 : std::ostringstream oss;
208 462 : oss << "Attribute '" << attrname << "' in definition of ";
209 462 : if (objectid == nullptr || objectid[0] == 0) {
210 : oss << "a " << myObjectType;
211 : } else {
212 442 : oss << myObjectType << " '" << objectid << "'";
213 : }
214 462 : oss << " " << type << ".";
215 462 : WRITE_ERROR(oss.str());
216 462 : }
217 :
218 :
219 : const int invalid_return<int>::value = -1;
220 : template<>
221 10776349 : int SUMOSAXAttributes::fromString(const std::string& value) const {
222 10776349 : return StringUtils::toInt(value);
223 : }
224 :
225 :
226 : const long long int invalid_return<long long int>::value = -1;
227 : template<>
228 1556383 : long long int SUMOSAXAttributes::fromString(const std::string& value) const {
229 1556383 : return StringUtils::toLong(value);
230 : }
231 :
232 :
233 : const double invalid_return<double>::value = -1;
234 : template<>
235 8121206 : double SUMOSAXAttributes::fromString(const std::string& value) const {
236 8121206 : return StringUtils::toDouble(value);
237 : }
238 :
239 :
240 : const bool invalid_return<bool>::value = false;
241 : template<>
242 766598 : bool SUMOSAXAttributes::fromString(const std::string& value) const {
243 766598 : return StringUtils::toBool(value);
244 : }
245 :
246 :
247 : const RGBColor invalid_return<RGBColor>::value = RGBColor();
248 : template<>
249 66231 : RGBColor SUMOSAXAttributes::fromString(const std::string& value) const {
250 132454 : return RGBColor::parseColor(value);
251 : }
252 :
253 :
254 : const Position invalid_return<Position>::value = Position();
255 : template<>
256 0 : Position SUMOSAXAttributes::fromString(const std::string& value) const {
257 0 : StringTokenizer st(value);
258 : // check StringTokenizer
259 0 : while (st.hasNext()) {
260 : // obtain position
261 0 : StringTokenizer pos(st.next(), ",");
262 : // check that position has X-Y or X-Y-Z
263 0 : if ((pos.size() != 2) && (pos.size() != 3)) {
264 0 : throw FormatException("is not a valid position");
265 : }
266 : // obtain x and y
267 0 : double x = StringUtils::toDouble(pos.next());
268 0 : double y = StringUtils::toDouble(pos.next());
269 : // check if return a X-Y or a X-Y-Z Position
270 0 : if (pos.size() == 2) {
271 : return Position(x, y);
272 : } else {
273 : // obtain z
274 0 : double z = StringUtils::toDouble(pos.next());
275 : return Position(x, y, z);
276 : }
277 0 : }
278 : // empty positions aren't allowed
279 0 : throw FormatException("is not a valid position");
280 0 : }
281 :
282 :
283 : const PositionVector invalid_return<PositionVector>::value = PositionVector();
284 : template<>
285 2560212 : PositionVector SUMOSAXAttributes::fromString(const std::string& value) const {
286 2560212 : StringTokenizer st(value);
287 2560212 : PositionVector shape;
288 11775990 : while (st.hasNext()) {
289 18431972 : StringTokenizer pos(st.next(), ",");
290 9215986 : if (pos.size() != 2 && pos.size() != 3) {
291 164 : throw FormatException("is not a valid list of positions");
292 : }
293 9215904 : double x = StringUtils::toDouble(pos.next());
294 9216028 : double y = StringUtils::toDouble(pos.next());
295 9215778 : if (pos.size() == 2) {
296 9187916 : shape.push_back(Position(x, y));
297 : } else {
298 27862 : double z = StringUtils::toDouble(pos.next());
299 27862 : shape.push_back(Position(x, y, z));
300 : }
301 9215986 : }
302 2560004 : return shape;
303 2560420 : }
304 :
305 :
306 : const Boundary invalid_return<Boundary>::value = Boundary();
307 : template<>
308 83756 : Boundary SUMOSAXAttributes::fromString(const std::string& value) const {
309 251268 : StringTokenizer st(value, ",");
310 83756 : if (st.size() != 4) {
311 0 : throw FormatException("is not a valid boundary");
312 : }
313 83756 : const double xmin = StringUtils::toDouble(st.next());
314 83756 : const double ymin = StringUtils::toDouble(st.next());
315 83756 : const double xmax = StringUtils::toDouble(st.next());
316 83756 : const double ymax = StringUtils::toDouble(st.next());
317 167512 : return Boundary(xmin, ymin, xmax, ymax);
318 83756 : }
319 :
320 :
321 : const SumoXMLEdgeFunc invalid_return<SumoXMLEdgeFunc>::value = SumoXMLEdgeFunc::NORMAL;
322 : template<>
323 1093751 : SumoXMLEdgeFunc SUMOSAXAttributes::fromString(const std::string& value) const {
324 1093751 : if (SUMOXMLDefinitions::EdgeFunctions.hasString(value)) {
325 1093731 : return SUMOXMLDefinitions::EdgeFunctions.get(value);
326 : }
327 40 : throw FormatException("is not a valid edge function");
328 : }
329 :
330 :
331 : const SumoXMLNodeType invalid_return<SumoXMLNodeType>::value = SumoXMLNodeType::UNKNOWN;
332 : template<>
333 600675 : SumoXMLNodeType SUMOSAXAttributes::fromString(const std::string& value) const {
334 600675 : if (SUMOXMLDefinitions::NodeTypes.hasString(value)) {
335 600615 : return SUMOXMLDefinitions::NodeTypes.get(value);
336 : }
337 120 : throw FormatException("is not a valid node type");
338 : }
339 :
340 :
341 : const RightOfWay invalid_return<RightOfWay>::value = RightOfWay::DEFAULT;
342 : template<>
343 4 : RightOfWay SUMOSAXAttributes::fromString(const std::string& value) const {
344 4 : if (SUMOXMLDefinitions::RightOfWayValues.hasString(value)) {
345 4 : return SUMOXMLDefinitions::RightOfWayValues.get(value);
346 : }
347 0 : throw FormatException("is not a valid right of way value");
348 : }
349 :
350 :
351 : const FringeType invalid_return<FringeType>::value = FringeType::DEFAULT;
352 : template<>
353 190 : FringeType SUMOSAXAttributes::fromString(const std::string& value) const {
354 190 : if (SUMOXMLDefinitions::FringeTypeValues.hasString(value)) {
355 190 : return SUMOXMLDefinitions::FringeTypeValues.get(value);
356 : }
357 0 : throw FormatException("is not a valid fringe type");
358 : }
359 :
360 :
361 : const ParkingType invalid_return<ParkingType>::value = ParkingType::ONROAD;
362 : template<>
363 892 : ParkingType SUMOSAXAttributes::fromString(const std::string& value) const {
364 892 : if (value == toString(ParkingType::OPPORTUNISTIC)) {
365 : return ParkingType::OPPORTUNISTIC;
366 : } else {
367 892 : return StringUtils::toBool(value) ? ParkingType::OFFROAD : ParkingType::ONROAD;
368 : }
369 : }
370 :
371 :
372 : const std::vector<std::string> invalid_return<std::vector<std::string> >::value = std::vector<std::string>();
373 : template<>
374 33739 : std::vector<std::string> SUMOSAXAttributes::fromString(const std::string& value) const {
375 42105 : const std::vector<std::string>& ret = StringTokenizer(value).getVector();
376 33739 : if (ret.empty()) {
377 13528 : throw EmptyData();
378 : }
379 40422 : return ret;
380 33739 : }
381 :
382 :
383 : const std::vector<int> invalid_return<std::vector<int> >::value = std::vector<int>();
384 : template<>
385 215 : std::vector<int> SUMOSAXAttributes::fromString(const std::string& value) const {
386 217 : const std::vector<std::string>& tmp = StringTokenizer(value).getVector();
387 215 : if (tmp.empty()) {
388 0 : throw EmptyData();
389 : }
390 : std::vector<int> ret;
391 525 : for (const std::string& s : tmp) {
392 310 : ret.push_back(StringUtils::toInt(s));
393 : }
394 215 : return ret;
395 215 : }
396 :
397 :
398 : const std::vector<double> invalid_return<std::vector<double> >::value = std::vector<double>();
399 : template<>
400 0 : std::vector<double> SUMOSAXAttributes::fromString(const std::string& value) const {
401 0 : const std::vector<std::string>& tmp = StringTokenizer(value).getVector();
402 0 : if (tmp.empty()) {
403 0 : throw EmptyData();
404 : }
405 : std::vector<double> ret;
406 0 : for (const std::string& s : tmp) {
407 0 : ret.push_back(StringUtils::toDouble(s));
408 : }
409 0 : return ret;
410 0 : }
411 :
412 : /****************************************************************************/
|