Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-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 RouteHandler.cpp
15 : /// @author Pablo Alvarez Lopez
16 : /// @date Jun 2021
17 : ///
18 : // The XML-Handler for route elements loading
19 : /****************************************************************************/
20 : #include <config.h>
21 :
22 : #include <utils/common/MsgHandler.h>
23 : #include <utils/common/RGBColor.h>
24 : #include <utils/common/SUMOVehicleClass.h>
25 : #include <utils/options/OptionsCont.h>
26 : #include <utils/shapes/Shape.h>
27 : #include <utils/vehicle/SUMOVehicleParserHelper.h>
28 : #include <utils/xml/SUMOSAXHandler.h>
29 : #include <utils/xml/XMLSubSys.h>
30 : #include <utils/xml/NamespaceIDs.h>
31 :
32 : #include "RouteHandler.h"
33 :
34 :
35 : // ===========================================================================
36 : // method definitions
37 : // ===========================================================================
38 :
39 0 : RouteHandler::RouteHandler(const std::string& filename, const bool hardFail) :
40 0 : myFilename(filename),
41 0 : myHardFail(hardFail),
42 0 : myFlowBeginDefault(string2time(OptionsCont::getOptions().getString("begin"))),
43 0 : myFlowEndDefault(string2time(OptionsCont::getOptions().getString("end"))) {
44 0 : }
45 :
46 :
47 0 : RouteHandler::~RouteHandler() {}
48 :
49 :
50 : bool
51 0 : RouteHandler::beginParseAttributes(SumoXMLTag tag, const SUMOSAXAttributes& attrs) {
52 : // open SUMOBaseOBject
53 0 : myCommonXMLStructure.openSUMOBaseOBject();
54 : // check tag
55 : try {
56 0 : switch (tag) {
57 : // vTypes
58 0 : case SUMO_TAG_VTYPE:
59 0 : parseVType(attrs);
60 : break;
61 0 : case SUMO_TAG_VTYPE_DISTRIBUTION:
62 0 : parseVTypeDistribution(attrs);
63 : break;
64 : // routes
65 0 : case SUMO_TAG_ROUTE:
66 0 : parseRoute(attrs);
67 : break;
68 0 : case SUMO_TAG_ROUTE_DISTRIBUTION:
69 0 : parseRouteDistribution(attrs);
70 : break;
71 : // vehicles
72 0 : case SUMO_TAG_TRIP:
73 0 : parseTrip(attrs);
74 : break;
75 0 : case SUMO_TAG_VEHICLE:
76 0 : parseVehicle(attrs);
77 : break;
78 : // flows
79 0 : case SUMO_TAG_FLOW:
80 0 : parseFlow(attrs);
81 : break;
82 : // stop
83 0 : case SUMO_TAG_STOP:
84 0 : parseStop(attrs);
85 : break;
86 : // persons
87 0 : case SUMO_TAG_PERSON:
88 0 : parsePerson(attrs);
89 : break;
90 0 : case SUMO_TAG_PERSONFLOW:
91 0 : parsePersonFlow(attrs);
92 : break;
93 : // person plans
94 0 : case SUMO_TAG_PERSONTRIP:
95 0 : parsePersonTrip(attrs);
96 : break;
97 0 : case SUMO_TAG_RIDE:
98 0 : parseRide(attrs);
99 : break;
100 0 : case SUMO_TAG_WALK:
101 0 : parseWalk(attrs);
102 : break;
103 : // container
104 0 : case SUMO_TAG_CONTAINER:
105 0 : parseContainer(attrs);
106 : break;
107 0 : case SUMO_TAG_CONTAINERFLOW:
108 0 : parseContainerFlow(attrs);
109 : break;
110 : // container plans
111 0 : case SUMO_TAG_TRANSPORT:
112 0 : parseTransport(attrs);
113 : break;
114 0 : case SUMO_TAG_TRANSHIP:
115 0 : parseTranship(attrs);
116 : break;
117 : // parameters
118 0 : case SUMO_TAG_PARAM:
119 0 : parseParameters(attrs);
120 : break;
121 : // other
122 0 : case SUMO_TAG_INTERVAL: {
123 0 : parseInterval(attrs);
124 : break;
125 : }
126 0 : default:
127 : // get vehicle type Base object
128 0 : const auto vTypeObject = myCommonXMLStructure.getCurrentSumoBaseObject()->getParentSumoBaseObject();
129 : // parse embedded car following model information
130 0 : if (vTypeObject && (vTypeObject->getTag() == SUMO_TAG_VTYPE)) {
131 : // nested CFM attributes
132 0 : return parseNestedCFM(tag, attrs, vTypeObject);
133 : } else {
134 : // tag cannot be parsed in routeHandler
135 0 : myCommonXMLStructure.abortSUMOBaseOBject();
136 : return false;
137 : }
138 : }
139 0 : } catch (InvalidArgument& e) {
140 0 : WRITE_ERROR(e.what());
141 0 : }
142 : return true;
143 : }
144 :
145 :
146 : void
147 0 : RouteHandler::endParseAttributes() {
148 : // get last inserted object
149 0 : CommonXMLStructure::SumoBaseObject* obj = myCommonXMLStructure.getCurrentSumoBaseObject();
150 : // check tag
151 0 : if (obj) {
152 : // close SUMOBaseOBject
153 0 : myCommonXMLStructure.closeSUMOBaseOBject();
154 : // get parent tag (if exist)
155 0 : const auto parentTag = obj->getParentSumoBaseObject() ? obj->getParentSumoBaseObject()->getTag() : SUMO_TAG_NOTHING;
156 0 : switch (obj->getTag()) {
157 : // specia case for route (because can be embedded)
158 0 : case SUMO_TAG_ROUTE:
159 : // only parse non-embedded and without distributionsroutes
160 0 : if ((obj->getStringAttribute(SUMO_ATTR_ID).size() > 0) &&
161 : (parentTag != SUMO_TAG_ROUTE_DISTRIBUTION)) {
162 : // parse route and all their childrens
163 0 : parseSumoBaseObject(obj);
164 : // delete object (and all of their childrens)
165 0 : delete obj;
166 : }
167 : break;
168 : // demand elements
169 0 : case SUMO_TAG_VTYPE:
170 : // only parse vTypes without distributions
171 0 : if (parentTag != SUMO_TAG_VTYPE_DISTRIBUTION) {
172 : // parse vType and all their childrens
173 0 : parseSumoBaseObject(obj);
174 : // delete object (and all of their childrens)
175 0 : delete obj;
176 : }
177 : break;
178 0 : case SUMO_TAG_VTYPE_DISTRIBUTION:
179 : case SUMO_TAG_ROUTE_DISTRIBUTION:
180 : case SUMO_TAG_TRIP:
181 : case SUMO_TAG_VEHICLE:
182 : case SUMO_TAG_FLOW:
183 : case SUMO_TAG_PERSON:
184 : case SUMO_TAG_PERSONFLOW:
185 : case SUMO_TAG_CONTAINER:
186 : case SUMO_TAG_CONTAINERFLOW:
187 : // parse object and all their childrens
188 0 : parseSumoBaseObject(obj);
189 : // delete object (and all of their childrens)
190 0 : delete obj;
191 : break;
192 : default:
193 : break;
194 : }
195 : }
196 0 : }
197 :
198 :
199 : void
200 0 : RouteHandler::parseSumoBaseObject(CommonXMLStructure::SumoBaseObject* obj) {
201 : // switch tag
202 0 : switch (obj->getTag()) {
203 : // vTypes
204 0 : case SUMO_TAG_VTYPE:
205 0 : buildVType(obj,
206 : obj->getVehicleTypeParameter());
207 0 : break;
208 0 : case SUMO_TAG_VTYPE_DISTRIBUTION:
209 0 : buildVTypeDistribution(obj,
210 : obj->getStringAttribute(SUMO_ATTR_ID),
211 : obj->getIntAttribute(SUMO_ATTR_DETERMINISTIC),
212 : obj->getStringListAttribute(SUMO_ATTR_VTYPES),
213 : obj->getDoubleListAttribute(SUMO_ATTR_PROBS));
214 0 : break;
215 : // route
216 0 : case SUMO_TAG_ROUTE:
217 0 : if (obj->getStringAttribute(SUMO_ATTR_ID).empty()) {
218 0 : buildEmbeddedRoute(obj,
219 : obj->getStringListAttribute(SUMO_ATTR_EDGES),
220 : obj->getColorAttribute(SUMO_ATTR_COLOR),
221 : obj->getIntAttribute(SUMO_ATTR_REPEAT),
222 : obj->getTimeAttribute(SUMO_ATTR_CYCLETIME),
223 0 : obj->getParameters());
224 : } else {
225 0 : buildRoute(obj,
226 : obj->getStringAttribute(SUMO_ATTR_ID),
227 : obj->getVClass(),
228 : obj->getStringListAttribute(SUMO_ATTR_EDGES),
229 : obj->getColorAttribute(SUMO_ATTR_COLOR),
230 : obj->getIntAttribute(SUMO_ATTR_REPEAT),
231 : obj->getTimeAttribute(SUMO_ATTR_CYCLETIME),
232 : obj->getDoubleAttribute(SUMO_ATTR_PROB),
233 0 : obj->getParameters());
234 : }
235 : break;
236 0 : case SUMO_TAG_ROUTE_DISTRIBUTION:
237 0 : buildRouteDistribution(obj,
238 : obj->getStringAttribute(SUMO_ATTR_ID),
239 : obj->getStringListAttribute(SUMO_ATTR_ROUTES),
240 : obj->getDoubleListAttribute(SUMO_ATTR_PROBS));
241 0 : break;
242 : // vehicles
243 0 : case SUMO_TAG_TRIP:
244 0 : if (obj->hasStringAttribute(SUMO_ATTR_FROM_JUNCTION) &&
245 0 : obj->hasStringAttribute(SUMO_ATTR_TO_JUNCTION)) {
246 : // build trip with from-to junctions
247 0 : buildTripJunctions(obj,
248 : obj->getVehicleParameter(),
249 : obj->getStringAttribute(SUMO_ATTR_FROM_JUNCTION),
250 : obj->getStringAttribute(SUMO_ATTR_TO_JUNCTION));
251 0 : } else if (obj->hasStringAttribute(SUMO_ATTR_FROM_TAZ) &&
252 0 : obj->hasStringAttribute(SUMO_ATTR_TO_TAZ)) {
253 : // build trip with from-to TAZs
254 0 : buildTripTAZs(obj,
255 : obj->getVehicleParameter(),
256 : obj->getStringAttribute(SUMO_ATTR_FROM_TAZ),
257 : obj->getStringAttribute(SUMO_ATTR_TO_TAZ));
258 : } else {
259 : // build trip with from-to edges
260 0 : buildTrip(obj,
261 : obj->getVehicleParameter(),
262 0 : obj->hasStringAttribute(SUMO_ATTR_FROM) ? obj->getStringAttribute(SUMO_ATTR_FROM) : "",
263 0 : obj->hasStringAttribute(SUMO_ATTR_TO) ? obj->getStringAttribute(SUMO_ATTR_TO) : "");
264 : }
265 : break;
266 0 : case SUMO_TAG_VEHICLE:
267 0 : if (obj->hasStringAttribute(SUMO_ATTR_ROUTE)) {
268 0 : buildVehicleOverRoute(obj,
269 : obj->getVehicleParameter());
270 : }
271 : break;
272 : // flows
273 0 : case SUMO_TAG_FLOW:
274 0 : if (obj->hasStringAttribute(SUMO_ATTR_ROUTE)) {
275 : // build flow over route
276 0 : buildFlowOverRoute(obj,
277 : obj->getVehicleParameter());
278 0 : } else if (obj->hasStringAttribute(SUMO_ATTR_FROM_JUNCTION) &&
279 0 : obj->hasStringAttribute(SUMO_ATTR_TO_JUNCTION)) {
280 : // build flow with from-to junctions
281 0 : buildFlowJunctions(obj,
282 : obj->getVehicleParameter(),
283 : obj->getStringAttribute(SUMO_ATTR_FROM_JUNCTION),
284 : obj->getStringAttribute(SUMO_ATTR_TO_JUNCTION));
285 0 : } else if (obj->hasStringAttribute(SUMO_ATTR_FROM_TAZ) &&
286 0 : obj->hasStringAttribute(SUMO_ATTR_TO_TAZ)) {
287 : // build flow with from-to TAZs
288 0 : buildFlowTAZs(obj,
289 : obj->getVehicleParameter(),
290 : obj->getStringAttribute(SUMO_ATTR_FROM_TAZ),
291 : obj->getStringAttribute(SUMO_ATTR_TO_TAZ));
292 : } else {
293 : // build flow with from-to edges
294 0 : buildFlow(obj,
295 : obj->getVehicleParameter(),
296 0 : obj->hasStringAttribute(SUMO_ATTR_FROM) ? obj->getStringAttribute(SUMO_ATTR_FROM) : "",
297 0 : obj->hasStringAttribute(SUMO_ATTR_TO) ? obj->getStringAttribute(SUMO_ATTR_TO) : "");
298 : }
299 : break;
300 : // persons
301 0 : case SUMO_TAG_PERSON:
302 0 : buildPerson(obj,
303 : obj->getVehicleParameter());
304 0 : break;
305 0 : case SUMO_TAG_PERSONFLOW:
306 0 : buildPersonFlow(obj,
307 : obj->getVehicleParameter());
308 0 : break;
309 : // person plans
310 0 : case SUMO_TAG_PERSONTRIP:
311 0 : buildPersonTrip(obj,
312 : obj->getPlanParameters(),
313 : obj->getDoubleAttribute(SUMO_ATTR_ARRIVALPOS),
314 : obj->getStringListAttribute(SUMO_ATTR_VTYPES),
315 : obj->getStringListAttribute(SUMO_ATTR_MODES),
316 : obj->getStringListAttribute(SUMO_ATTR_LINES),
317 : obj->getDoubleAttribute(SUMO_ATTR_WALKFACTOR),
318 : obj->getStringAttribute(SUMO_ATTR_GROUP));
319 0 : break;
320 0 : case SUMO_TAG_RIDE:
321 0 : buildRide(obj,
322 : obj->getPlanParameters(),
323 : obj->getDoubleAttribute(SUMO_ATTR_ARRIVALPOS),
324 : obj->getStringListAttribute(SUMO_ATTR_LINES),
325 : obj->getStringAttribute(SUMO_ATTR_GROUP));
326 0 : break;
327 0 : case SUMO_TAG_WALK:
328 0 : buildWalk(obj,
329 : obj->getPlanParameters(),
330 : obj->getDoubleAttribute(SUMO_ATTR_ARRIVALPOS),
331 : obj->getDoubleAttribute(SUMO_ATTR_SPEED),
332 : obj->getTimeAttribute(SUMO_ATTR_DURATION));
333 0 : break;
334 : // container
335 0 : case SUMO_TAG_CONTAINER:
336 0 : buildContainer(obj,
337 : obj->getVehicleParameter());
338 0 : break;
339 0 : case SUMO_TAG_CONTAINERFLOW:
340 0 : buildContainerFlow(obj,
341 : obj->getVehicleParameter());
342 0 : break;
343 : // container plans
344 0 : case SUMO_TAG_TRANSPORT:
345 0 : buildTransport(obj,
346 : obj->getPlanParameters(),
347 : obj->getDoubleAttribute(SUMO_ATTR_ARRIVALPOS),
348 : obj->getStringListAttribute(SUMO_ATTR_LINES),
349 : obj->getStringAttribute(SUMO_ATTR_GROUP));
350 0 : break;
351 0 : case SUMO_TAG_TRANSHIP:
352 0 : buildTranship(obj,
353 : obj->getPlanParameters(),
354 : obj->getDoubleAttribute(SUMO_ATTR_ARRIVALPOS),
355 : obj->getDoubleAttribute(SUMO_ATTR_DEPARTPOS),
356 : obj->getDoubleAttribute(SUMO_ATTR_SPEED),
357 : obj->getTimeAttribute(SUMO_ATTR_DURATION));
358 0 : break;
359 : // stopss
360 0 : case SUMO_TAG_STOP:
361 0 : buildStop(obj,
362 : obj->getPlanParameters(),
363 : obj->getStopParameter());
364 0 : break;
365 : default:
366 : break;
367 : }
368 : // now iterate over childrens
369 0 : for (const auto& child : obj->getSumoBaseObjectChildren()) {
370 : // call this function recursively
371 0 : parseSumoBaseObject(child);
372 : }
373 0 : }
374 :
375 :
376 : bool
377 0 : RouteHandler::isErrorCreatingElement() const {
378 0 : return myErrorCreatingElement;
379 : }
380 :
381 :
382 : void
383 0 : RouteHandler::writeError(const std::string& error) {
384 0 : WRITE_ERROR(error);
385 0 : myErrorCreatingElement = true;
386 0 : }
387 :
388 :
389 : void
390 0 : RouteHandler::writeErrorInvalidID(const SumoXMLTag tag, const std::string& id) {
391 0 : WRITE_ERRORF(TL("Could not build % with ID '%' in netedit; ID contains invalid characters."), toString(tag), id);
392 0 : myErrorCreatingElement = true;
393 0 : }
394 :
395 :
396 : void
397 0 : RouteHandler::writeErrorInvalidDistribution(const SumoXMLTag tag, const std::string& id) {
398 0 : WRITE_ERRORF(TL("Could not build % with ID '%' in netedit; Distinct number of distribution values and probabilities."), toString(tag), id);
399 0 : myErrorCreatingElement = true;
400 0 : }
401 :
402 :
403 : void
404 0 : RouteHandler::parseVType(const SUMOSAXAttributes& attrs) {
405 : // parse vehicleType
406 0 : SUMOVTypeParameter* vehicleTypeParameter = SUMOVehicleParserHelper::beginVTypeParsing(attrs, myHardFail, myFilename);
407 0 : if (vehicleTypeParameter) {
408 : // set tag
409 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setTag(SUMO_TAG_VTYPE);
410 : // add all attributes
411 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setVehicleTypeParameter(vehicleTypeParameter);
412 : // delete vehicleType parameter (because in XMLStructure we have a copy)
413 0 : delete vehicleTypeParameter;
414 : }
415 0 : }
416 :
417 :
418 : void
419 0 : RouteHandler::parseVTypeDistribution(const SUMOSAXAttributes& attrs) {
420 : // declare Ok Flag
421 0 : bool parsedOk = true;
422 : // needed attributes
423 0 : const std::string id = attrs.get<std::string>(SUMO_ATTR_ID, "", parsedOk);
424 : // optional attributes
425 0 : const int deterministic = attrs.getOpt<int>(SUMO_ATTR_DETERMINISTIC, id.c_str(), parsedOk, -1);
426 0 : const std::vector<std::string> vTypes = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_VTYPES, id.c_str(), parsedOk);
427 0 : const std::vector<double> probabilities = attrs.getOpt<std::vector<double> >(SUMO_ATTR_PROBS, id.c_str(), parsedOk);
428 0 : if (parsedOk) {
429 0 : if (!SUMOXMLDefinitions::isValidVehicleID(id)) {
430 0 : writeErrorInvalidID(SUMO_TAG_VTYPE_DISTRIBUTION, id);
431 0 : } else if (vTypes.size() != probabilities.size()) {
432 0 : writeErrorInvalidDistribution(SUMO_TAG_VTYPE_DISTRIBUTION, id);
433 : } else {
434 : // set tag
435 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setTag(SUMO_TAG_VTYPE_DISTRIBUTION);
436 : // add all attributes
437 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addStringAttribute(SUMO_ATTR_ID, id);
438 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addIntAttribute(SUMO_ATTR_DETERMINISTIC, deterministic);
439 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addStringListAttribute(SUMO_ATTR_VTYPES, vTypes);
440 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addDoubleListAttribute(SUMO_ATTR_PROBS, probabilities);
441 : }
442 : }
443 0 : }
444 :
445 :
446 : void
447 0 : RouteHandler::parseRoute(const SUMOSAXAttributes& attrs) {
448 : // get embedded route flag
449 0 : const bool embeddedRoute = isEmbeddedRoute(attrs);
450 : // first check if this is an embedded route
451 0 : if ((embeddedRoute && attrs.hasAttribute(SUMO_ATTR_ID)) || (!embeddedRoute && !attrs.hasAttribute(SUMO_ATTR_ID))) {
452 0 : writeError(TL("a route must be defined either within a vehicle/flow or with an ID attribute"));
453 : } else {
454 : // declare Ok Flag
455 0 : bool parsedOk = true;
456 : // special case for ID
457 0 : const std::string id = attrs.getOpt<std::string>(SUMO_ATTR_ID, "", parsedOk, "");
458 : // needed attributes
459 0 : const std::vector<std::string> edges = attrs.get<std::vector<std::string> >(SUMO_ATTR_EDGES, id.c_str(), parsedOk);
460 : // optional attributes
461 0 : SUMOVehicleClass vClass = SUMOVehicleParserHelper::parseVehicleClass(attrs, id);
462 0 : const RGBColor color = attrs.getOpt<RGBColor>(SUMO_ATTR_COLOR, id.c_str(), parsedOk, RGBColor::INVISIBLE);
463 0 : const int repeat = attrs.getOpt<int>(SUMO_ATTR_REPEAT, id.c_str(), parsedOk, 0);
464 0 : const SUMOTime cycleTime = attrs.getOptSUMOTimeReporting(SUMO_ATTR_CYCLETIME, id.c_str(), parsedOk, 0);
465 0 : const double probability = attrs.getOpt<double>(SUMO_ATTR_PROB, id.c_str(), parsedOk, 0);
466 0 : if (parsedOk) {
467 0 : if (!id.empty() && !SUMOXMLDefinitions::isValidVehicleID(id)) {
468 0 : writeErrorInvalidID(SUMO_TAG_ROUTE, id);
469 0 : } else if (cycleTime < 0) {
470 0 : writeError(TLF("cycleTime of % must be equal or greater than 0", toString(SUMO_TAG_DEST_PROB_REROUTE)));
471 : } else {
472 : // set tag
473 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setTag(SUMO_TAG_ROUTE);
474 : // add all attributes
475 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addStringAttribute(SUMO_ATTR_ID, id);
476 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setVClass(vClass);
477 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addStringListAttribute(SUMO_ATTR_EDGES, edges);
478 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addColorAttribute(SUMO_ATTR_COLOR, color);
479 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addIntAttribute(SUMO_ATTR_REPEAT, repeat);
480 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addTimeAttribute(SUMO_ATTR_CYCLETIME, cycleTime);
481 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addDoubleAttribute(SUMO_ATTR_PROB, probability);
482 : }
483 : }
484 0 : }
485 0 : }
486 :
487 :
488 : void
489 0 : RouteHandler::parseRouteDistribution(const SUMOSAXAttributes& attrs) {
490 : // declare Ok Flag
491 0 : bool parsedOk = true;
492 : // needed attributes
493 0 : const std::string id = attrs.get<std::string>(SUMO_ATTR_ID, "", parsedOk);
494 : // optional attributes
495 0 : const std::vector<std::string> routes = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_ROUTES, id.c_str(), parsedOk);
496 0 : const std::vector<double> probabilities = attrs.getOpt<std::vector<double> >(SUMO_ATTR_PROBS, id.c_str(), parsedOk);
497 0 : if (parsedOk) {
498 0 : if (!SUMOXMLDefinitions::isValidVehicleID(id)) {
499 0 : writeErrorInvalidID(SUMO_TAG_ROUTE_DISTRIBUTION, id);
500 0 : } else if (routes.size() != probabilities.size()) {
501 0 : writeErrorInvalidDistribution(SUMO_TAG_ROUTE_DISTRIBUTION, id);
502 : } else {
503 : // set tag
504 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setTag(SUMO_TAG_ROUTE_DISTRIBUTION);
505 : // add all attributes
506 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addStringAttribute(SUMO_ATTR_ID, id);
507 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addStringListAttribute(SUMO_ATTR_ROUTES, routes);
508 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addDoubleListAttribute(SUMO_ATTR_PROBS, probabilities);
509 : }
510 : }
511 0 : }
512 :
513 :
514 : void
515 0 : RouteHandler::parseTrip(const SUMOSAXAttributes& attrs) {
516 : // declare Ok Flag
517 0 : bool parsedOk = true;
518 : // parse vehicle
519 0 : SUMOVehicleParameter* tripParameter = SUMOVehicleParserHelper::parseVehicleAttributes(SUMO_TAG_TRIP, attrs, myHardFail);
520 0 : if (tripParameter) {
521 : // check from/to edge/junction
522 0 : if ((attrs.hasAttribute(SUMO_ATTR_FROM) + attrs.hasAttribute(SUMO_ATTR_FROM_JUNCTION) + attrs.hasAttribute(SUMO_ATTR_FROM_TAZ)) > 1) {
523 0 : writeError(TL("Attributes 'from', 'fromJunction' and 'fromTaz' cannot be defined together"));
524 0 : } else if ((attrs.hasAttribute(SUMO_ATTR_TO) + attrs.hasAttribute(SUMO_ATTR_TO_JUNCTION) + attrs.hasAttribute(SUMO_ATTR_TO_TAZ)) > 1) {
525 0 : writeError(TL("Attributes 'to', 'toJunction' and 'toTaz' cannot be defined together"));
526 0 : } else if (attrs.hasAttribute(SUMO_ATTR_FROM_JUNCTION) && attrs.hasAttribute(SUMO_ATTR_TO_JUNCTION)) {
527 : // from-to attributes
528 0 : const std::string fromJunction = attrs.get<std::string>(SUMO_ATTR_FROM_JUNCTION, tripParameter->id.c_str(), parsedOk);
529 0 : const std::string toJunction = attrs.get<std::string>(SUMO_ATTR_TO_JUNCTION, tripParameter->id.c_str(), parsedOk);
530 0 : if (parsedOk) {
531 : // set tag
532 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setTag(SUMO_TAG_TRIP);
533 : // set vehicle parameters
534 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setVehicleParameter(tripParameter);
535 : // add other attributes
536 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addStringAttribute(SUMO_ATTR_FROM_JUNCTION, fromJunction);
537 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addStringAttribute(SUMO_ATTR_TO_JUNCTION, toJunction);
538 : }
539 0 : } else if (attrs.hasAttribute(SUMO_ATTR_FROM_TAZ) && attrs.hasAttribute(SUMO_ATTR_TO_TAZ)) {
540 : // from-to attributes
541 0 : const std::string fromJunction = attrs.get<std::string>(SUMO_ATTR_FROM_TAZ, tripParameter->id.c_str(), parsedOk);
542 0 : const std::string toJunction = attrs.get<std::string>(SUMO_ATTR_TO_TAZ, tripParameter->id.c_str(), parsedOk);
543 0 : if (parsedOk) {
544 : // set tag
545 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setTag(SUMO_TAG_TRIP);
546 : // set vehicle parameters
547 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setVehicleParameter(tripParameter);
548 : // add other attributes
549 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addStringAttribute(SUMO_ATTR_FROM_TAZ, fromJunction);
550 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addStringAttribute(SUMO_ATTR_TO_TAZ, toJunction);
551 : }
552 : } else {
553 : // from-to attributes
554 0 : const std::string from = attrs.getOpt<std::string>(SUMO_ATTR_FROM, tripParameter->id.c_str(), parsedOk, "");
555 0 : const std::string to = attrs.getOpt<std::string>(SUMO_ATTR_TO, tripParameter->id.c_str(), parsedOk, "");
556 : // optional attributes
557 0 : const std::vector<std::string> via = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_VIA, tripParameter->id.c_str(), parsedOk);
558 0 : if (parsedOk) {
559 : // set tag
560 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setTag(SUMO_TAG_TRIP);
561 : // set vehicle parameters
562 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setVehicleParameter(tripParameter);
563 : // add other attributes
564 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addStringAttribute(SUMO_ATTR_FROM, from);
565 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addStringAttribute(SUMO_ATTR_TO, to);
566 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addStringListAttribute(SUMO_ATTR_VIA, via);
567 : }
568 0 : }
569 : // delete trip parameter (because in XMLStructure we have a copy)
570 0 : delete tripParameter;
571 : }
572 0 : }
573 :
574 :
575 : void
576 0 : RouteHandler::parseVehicle(const SUMOSAXAttributes& attrs) {
577 : // first parse vehicle
578 0 : SUMOVehicleParameter* vehicleParameter = SUMOVehicleParserHelper::parseVehicleAttributes(SUMO_TAG_VEHICLE, attrs, myHardFail);
579 0 : if (vehicleParameter) {
580 : // set tag
581 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setTag(SUMO_TAG_VEHICLE);
582 : // set vehicle parameters
583 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setVehicleParameter(vehicleParameter);
584 : // delete vehicle parameter (because in XMLStructure we have a copy)
585 0 : delete vehicleParameter;
586 : }
587 0 : }
588 :
589 :
590 : void
591 0 : RouteHandler::parseFlow(const SUMOSAXAttributes& attrs) {
592 : // declare Ok Flag
593 0 : bool parsedOk = true;
594 : // first parse flow
595 0 : SUMOVehicleParameter* flowParameter = SUMOVehicleParserHelper::parseFlowAttributes(SUMO_TAG_FLOW, attrs, myHardFail, true, myFlowBeginDefault, myFlowEndDefault);
596 0 : if (flowParameter) {
597 : // set vehicle parameters
598 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setVehicleParameter(flowParameter);
599 : // check from/to edge/junction
600 0 : if ((attrs.hasAttribute(SUMO_ATTR_FROM) + attrs.hasAttribute(SUMO_ATTR_FROM_JUNCTION) + attrs.hasAttribute(SUMO_ATTR_FROM_TAZ)) > 1) {
601 0 : writeError(TL("Attributes 'from', 'fromJunction' and 'fromTaz' cannot be defined together"));
602 0 : } else if ((attrs.hasAttribute(SUMO_ATTR_TO) + attrs.hasAttribute(SUMO_ATTR_TO_JUNCTION) + attrs.hasAttribute(SUMO_ATTR_TO_TAZ)) > 1) {
603 0 : writeError(TL("Attributes 'to', 'toJunction' and 'toTaz' cannot be defined together"));
604 0 : } else if (attrs.hasAttribute(SUMO_ATTR_FROM) && attrs.hasAttribute(SUMO_ATTR_TO)) {
605 : // from-to attributes
606 0 : const std::string from = attrs.get<std::string>(SUMO_ATTR_FROM, flowParameter->id.c_str(), parsedOk);
607 0 : const std::string to = attrs.get<std::string>(SUMO_ATTR_TO, flowParameter->id.c_str(), parsedOk);
608 : // optional attributes
609 0 : const std::vector<std::string> via = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_VIA, flowParameter->id.c_str(), parsedOk);
610 0 : if (parsedOk) {
611 : // set tag
612 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setTag(SUMO_TAG_FLOW);
613 : // add other attributes
614 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addStringAttribute(SUMO_ATTR_FROM, from);
615 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addStringAttribute(SUMO_ATTR_TO, to);
616 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addStringListAttribute(SUMO_ATTR_VIA, via);
617 : }
618 0 : } else if (attrs.hasAttribute(SUMO_ATTR_FROM_JUNCTION) && attrs.hasAttribute(SUMO_ATTR_TO_JUNCTION)) {
619 : // from-to attributes
620 0 : const std::string fromJunction = attrs.get<std::string>(SUMO_ATTR_FROM_JUNCTION, flowParameter->id.c_str(), parsedOk);
621 0 : const std::string toJunction = attrs.get<std::string>(SUMO_ATTR_TO_JUNCTION, flowParameter->id.c_str(), parsedOk);
622 0 : if (parsedOk) {
623 : // set tag
624 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setTag(SUMO_TAG_FLOW);
625 : // add other attributes
626 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addStringAttribute(SUMO_ATTR_FROM_JUNCTION, fromJunction);
627 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addStringAttribute(SUMO_ATTR_TO_JUNCTION, toJunction);
628 : }
629 0 : } else if (attrs.hasAttribute(SUMO_ATTR_FROM_TAZ) && attrs.hasAttribute(SUMO_ATTR_TO_TAZ)) {
630 : // from-to attributes
631 0 : const std::string fromJunction = attrs.get<std::string>(SUMO_ATTR_FROM_TAZ, flowParameter->id.c_str(), parsedOk);
632 0 : const std::string toJunction = attrs.get<std::string>(SUMO_ATTR_TO_TAZ, flowParameter->id.c_str(), parsedOk);
633 0 : if (parsedOk) {
634 : // set tag
635 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setTag(SUMO_TAG_FLOW);
636 : // add other attributes
637 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addStringAttribute(SUMO_ATTR_FROM_TAZ, fromJunction);
638 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addStringAttribute(SUMO_ATTR_TO_TAZ, toJunction);
639 : }
640 0 : } else if (attrs.hasAttribute(SUMO_ATTR_ROUTE)) {
641 : // from-to attributes
642 0 : const std::string route = attrs.get<std::string>(SUMO_ATTR_ROUTE, flowParameter->id.c_str(), parsedOk);
643 0 : if (parsedOk) {
644 : // set tag
645 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setTag(SUMO_TAG_FLOW);
646 : // add other attributes
647 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addStringAttribute(SUMO_ATTR_ROUTE, route);
648 : }
649 : } else {
650 : // set tag
651 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setTag(SUMO_TAG_FLOW);
652 : }
653 : // delete flow parameter (because in XMLStructure we have a copy)
654 0 : delete flowParameter;
655 : }
656 0 : }
657 :
658 :
659 : void
660 0 : RouteHandler::parseStop(const SUMOSAXAttributes& attrs) {
661 : // declare Ok Flag
662 0 : bool parsedOk = true;
663 : // declare stop
664 0 : SUMOVehicleParameter::Stop stop;
665 : // plan parameters
666 0 : const auto planParameters = CommonXMLStructure::PlanParameters(myCommonXMLStructure.getCurrentSumoBaseObject(), attrs, parsedOk);
667 : // get parents
668 : std::vector<SumoXMLTag> stopParents;
669 0 : stopParents.insert(stopParents.end(), NamespaceIDs::vehicles.begin(), NamespaceIDs::vehicles.end());
670 0 : stopParents.insert(stopParents.end(), NamespaceIDs::routes.begin(), NamespaceIDs::routes.end());
671 0 : stopParents.insert(stopParents.end(), NamespaceIDs::persons.begin(), NamespaceIDs::persons.end());
672 0 : stopParents.insert(stopParents.end(), NamespaceIDs::containers.begin(), NamespaceIDs::containers.end());
673 : // check parents
674 0 : checkParent(SUMO_TAG_STOP, stopParents, parsedOk);
675 : // parse stop
676 0 : if (parsedOk && parseStopParameters(stop, attrs)) {
677 : // set tag
678 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setTag(SUMO_TAG_STOP);
679 : // add stop attributes
680 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setPlanParameters(planParameters);
681 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setStopParameter(stop);
682 : }
683 0 : }
684 :
685 :
686 : void
687 0 : RouteHandler::parsePerson(const SUMOSAXAttributes& attrs) {
688 : // first parse vehicle
689 0 : SUMOVehicleParameter* personParameter = SUMOVehicleParserHelper::parseVehicleAttributes(SUMO_TAG_PERSON, attrs, myHardFail);
690 0 : if (personParameter) {
691 : // set tag
692 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setTag(SUMO_TAG_PERSON);
693 : // set vehicle parameter
694 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setVehicleParameter(personParameter);
695 : // delete person parameter (because in XMLStructure we have a copy)
696 0 : delete personParameter;
697 : }
698 0 : }
699 :
700 :
701 : void
702 0 : RouteHandler::parsePersonFlow(const SUMOSAXAttributes& attrs) {
703 : // first parse flow
704 0 : SUMOVehicleParameter* personFlowParameter = SUMOVehicleParserHelper::parseFlowAttributes(SUMO_TAG_PERSONFLOW, attrs, myHardFail, true, myFlowBeginDefault, myFlowEndDefault);
705 0 : if (personFlowParameter) {
706 : // set tag
707 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setTag(SUMO_TAG_PERSONFLOW);
708 : // set vehicle parameter
709 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setVehicleParameter(personFlowParameter);
710 : // delete person flow parameter (because in XMLStructure we have a copy)
711 0 : delete personFlowParameter;
712 : }
713 0 : }
714 :
715 :
716 : void
717 0 : RouteHandler::parsePersonTrip(const SUMOSAXAttributes& attrs) {
718 : // declare Ok Flag
719 0 : bool parsedOk = true;
720 : // plan parameters
721 0 : const auto planParameters = CommonXMLStructure::PlanParameters(myCommonXMLStructure.getCurrentSumoBaseObject(), attrs, parsedOk);
722 : // optional attributes
723 0 : const std::vector<std::string> via = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_VIA, "", parsedOk);
724 0 : const std::vector<std::string> vTypes = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_VTYPES, "", parsedOk);
725 0 : const std::vector<std::string> lines = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_LINES, "", parsedOk);
726 0 : std::vector<std::string> modes = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_MODES, "", parsedOk);
727 0 : const double departPos = attrs.getOpt<double>(SUMO_ATTR_DEPARTPOS, "", parsedOk, -1);
728 0 : const double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, "", parsedOk, -1);
729 0 : const double walkFactor = attrs.getOpt<double>(SUMO_ATTR_WALKFACTOR, "", parsedOk, 0);
730 0 : const std::string group = attrs.getOpt<std::string>(SUMO_ATTR_GROUP, "", parsedOk, "");
731 : // check modes
732 : SVCPermissions dummyModeSet;
733 : std::string dummyError;
734 0 : if (!SUMOVehicleParameter::parsePersonModes(toString(modes), toString(SUMO_TAG_PERSONTRIP), "", dummyModeSet, dummyError)) {
735 0 : WRITE_WARNING(dummyError);
736 : modes.clear();
737 : }
738 0 : if (parsedOk) {
739 : // set tag
740 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setTag(SUMO_TAG_PERSONTRIP);
741 : // add all attributes
742 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setPlanParameters(planParameters);
743 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addStringListAttribute(SUMO_ATTR_VTYPES, vTypes);
744 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addStringListAttribute(SUMO_ATTR_MODES, modes);
745 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addStringListAttribute(SUMO_ATTR_LINES, lines);
746 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addDoubleAttribute(SUMO_ATTR_DEPARTPOS, departPos);
747 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addDoubleAttribute(SUMO_ATTR_ARRIVALPOS, arrivalPos);
748 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addDoubleAttribute(SUMO_ATTR_WALKFACTOR, walkFactor);
749 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addStringAttribute(SUMO_ATTR_GROUP, group);
750 : }
751 0 : }
752 :
753 :
754 : void
755 0 : RouteHandler::parseWalk(const SUMOSAXAttributes& attrs) {
756 0 : if (attrs.hasAttribute(SUMO_ATTR_SPEED) && attrs.hasAttribute(SUMO_ATTR_DURATION)) {
757 0 : WRITE_ERROR(TL("Speed and duration attributes cannot be defined together in walks"));
758 : } else {
759 : // declare Ok Flag
760 0 : bool parsedOk = true;
761 : // plan parameters
762 0 : const auto planParameters = CommonXMLStructure::PlanParameters(myCommonXMLStructure.getCurrentSumoBaseObject(), attrs, parsedOk);
763 : // optional attributes
764 0 : const double departPos = attrs.getOpt<double>(SUMO_ATTR_DEPARTPOS, "", parsedOk, -1);
765 0 : const double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, "", parsedOk, -1);
766 0 : const double speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, "", parsedOk, 1.39);
767 0 : const SUMOTime duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, "", parsedOk, 0);
768 0 : if (parsedOk) {
769 : // set tag
770 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setTag(SUMO_TAG_WALK);
771 : // add all attributes
772 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setPlanParameters(planParameters);
773 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addDoubleAttribute(SUMO_ATTR_DEPARTPOS, departPos);
774 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addDoubleAttribute(SUMO_ATTR_ARRIVALPOS, arrivalPos);
775 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addDoubleAttribute(SUMO_ATTR_SPEED, speed);
776 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addTimeAttribute(SUMO_ATTR_DURATION, duration);
777 : }
778 0 : }
779 0 : }
780 :
781 :
782 : void
783 0 : RouteHandler::parseRide(const SUMOSAXAttributes& attrs) {
784 : // declare Ok Flag
785 0 : bool parsedOk = true;
786 : // plan parameters
787 0 : const auto planParameters = CommonXMLStructure::PlanParameters(myCommonXMLStructure.getCurrentSumoBaseObject(), attrs, parsedOk);
788 : // optional attributes
789 0 : const std::vector<std::string> lines = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_LINES, "", parsedOk);
790 0 : const double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, "", parsedOk, -1);
791 0 : const std::string group = attrs.getOpt<std::string>(SUMO_ATTR_GROUP, "", parsedOk, "");
792 0 : if (parsedOk) {
793 : // set tag
794 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setTag(SUMO_TAG_RIDE);
795 : // add all attributes
796 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setPlanParameters(planParameters);
797 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addStringListAttribute(SUMO_ATTR_LINES, lines);
798 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addDoubleAttribute(SUMO_ATTR_ARRIVALPOS, arrivalPos);
799 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addStringAttribute(SUMO_ATTR_GROUP, group);
800 : }
801 0 : }
802 :
803 :
804 : void
805 0 : RouteHandler::parseContainer(const SUMOSAXAttributes& attrs) {
806 : // first parse container
807 0 : SUMOVehicleParameter* containerParameter = SUMOVehicleParserHelper::parseVehicleAttributes(SUMO_TAG_CONTAINER, attrs, myHardFail);
808 0 : if (containerParameter) {
809 : // set tag
810 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setTag(SUMO_TAG_CONTAINER);
811 : // set vehicle parameter
812 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setVehicleParameter(containerParameter);
813 : // delete container parameter (because in XMLStructure we have a copy)
814 0 : delete containerParameter;
815 : }
816 0 : }
817 :
818 :
819 : void
820 0 : RouteHandler::parseContainerFlow(const SUMOSAXAttributes& attrs) {
821 : // first parse flow
822 0 : SUMOVehicleParameter* containerFlowParameter = SUMOVehicleParserHelper::parseFlowAttributes(SUMO_TAG_CONTAINERFLOW, attrs, myHardFail, true, myFlowBeginDefault, myFlowEndDefault);
823 0 : if (containerFlowParameter) {
824 : // set tag
825 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setTag(SUMO_TAG_CONTAINERFLOW);
826 : // set vehicle parameter
827 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setVehicleParameter(containerFlowParameter);
828 : // delete container flow parameter (because in XMLStructure we have a copy)
829 0 : delete containerFlowParameter;
830 : }
831 0 : }
832 :
833 :
834 : void
835 0 : RouteHandler::parseTransport(const SUMOSAXAttributes& attrs) {
836 : // declare Ok Flag
837 0 : bool parsedOk = true;
838 : // plan parameters
839 0 : const auto planParameters = CommonXMLStructure::PlanParameters(myCommonXMLStructure.getCurrentSumoBaseObject(), attrs, parsedOk);
840 : // optional attributes
841 0 : const std::vector<std::string> lines = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_LINES, "", parsedOk);
842 0 : const double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, "", parsedOk, -1);
843 0 : const std::string group = attrs.getOpt<std::string>(SUMO_ATTR_GROUP, "", parsedOk, "");
844 0 : if (parsedOk) {
845 : // set tag
846 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setTag(SUMO_TAG_TRANSPORT);
847 : // add all attributes
848 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setPlanParameters(planParameters);
849 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addStringListAttribute(SUMO_ATTR_LINES, lines);
850 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addDoubleAttribute(SUMO_ATTR_ARRIVALPOS, arrivalPos);
851 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addStringAttribute(SUMO_ATTR_GROUP, group);
852 : }
853 0 : }
854 :
855 :
856 : void
857 0 : RouteHandler::parseTranship(const SUMOSAXAttributes& attrs) {
858 0 : if (attrs.hasAttribute(SUMO_ATTR_SPEED) && attrs.hasAttribute(SUMO_ATTR_DURATION)) {
859 0 : WRITE_ERROR(TL("Speed and duration attributes cannot be defined together in walks"));
860 : } else {
861 : // declare Ok Flag
862 0 : bool parsedOk = true;
863 : // plan parameters
864 0 : const auto planParameters = CommonXMLStructure::PlanParameters(myCommonXMLStructure.getCurrentSumoBaseObject(), attrs, parsedOk);
865 : // optional attributes
866 0 : const double arrivalPos = attrs.getOpt<double>(SUMO_ATTR_ARRIVALPOS, "", parsedOk, -1);
867 0 : const double departPos = attrs.getOpt<double>(SUMO_ATTR_DEPARTPOS, "", parsedOk, -1);
868 0 : const double speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, "", parsedOk, 1.39);
869 0 : const SUMOTime duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, "", parsedOk, 0);
870 0 : if (parsedOk) {
871 : // set tag
872 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setTag(SUMO_TAG_TRANSHIP);
873 : // add all attributes
874 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->setPlanParameters(planParameters);
875 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addDoubleAttribute(SUMO_ATTR_ARRIVALPOS, arrivalPos);
876 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addDoubleAttribute(SUMO_ATTR_DEPARTPOS, departPos);
877 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addDoubleAttribute(SUMO_ATTR_SPEED, speed);
878 0 : myCommonXMLStructure.getCurrentSumoBaseObject()->addTimeAttribute(SUMO_ATTR_DURATION, duration);
879 : }
880 0 : }
881 0 : }
882 :
883 :
884 : void
885 0 : RouteHandler::parseInterval(const SUMOSAXAttributes& attrs) {
886 : // declare Ok Flag
887 0 : bool parsedOk = true;
888 : // just parse begin and end default
889 0 : myFlowBeginDefault = attrs.getSUMOTimeReporting(SUMO_ATTR_BEGIN, nullptr, parsedOk);
890 0 : myFlowEndDefault = attrs.getSUMOTimeReporting(SUMO_ATTR_END, nullptr, parsedOk);
891 0 : }
892 :
893 :
894 : void
895 0 : RouteHandler::parseParameters(const SUMOSAXAttributes& attrs) {
896 : // declare Ok Flag
897 0 : bool parsedOk = true;
898 : // get key
899 0 : const std::string key = attrs.get<std::string>(SUMO_ATTR_KEY, nullptr, parsedOk);
900 : // get SumoBaseObject parent
901 0 : CommonXMLStructure::SumoBaseObject* SumoBaseObjectParent = myCommonXMLStructure.getCurrentSumoBaseObject()->getParentSumoBaseObject();
902 : // check parent
903 0 : if (SumoBaseObjectParent == nullptr) {
904 0 : writeError(TL("Parameters must be defined within an object"));
905 0 : } else if (SumoBaseObjectParent->getTag() == SUMO_TAG_ROOTFILE) {
906 0 : writeError(TL("Parameters cannot be defined in the additional file's root."));
907 0 : } else if (SumoBaseObjectParent->getTag() == SUMO_TAG_PARAM) {
908 0 : writeError(TL("Parameters cannot be defined within another parameter."));
909 0 : } else if (parsedOk) {
910 : // get tag str
911 0 : const std::string parentTagStr = toString(SumoBaseObjectParent->getTag());
912 : // circumventing empty string value
913 0 : const std::string value = attrs.hasAttribute(SUMO_ATTR_VALUE) ? attrs.getString(SUMO_ATTR_VALUE) : "";
914 : // show warnings if values are invalid
915 0 : if (key.empty()) {
916 0 : WRITE_WARNINGF(TL("Error parsing key from % generic parameter. Key cannot be empty"), parentTagStr);
917 0 : } else if (!SUMOXMLDefinitions::isValidParameterKey(key)) {
918 0 : WRITE_WARNINGF(TL("Error parsing key from % generic parameter. Key contains invalid characters"), parentTagStr);
919 : } else {
920 0 : WRITE_DEBUG("Inserting generic parameter '" + key + "|" + value + "' into " + parentTagStr);
921 : // insert parameter in SumoBaseObjectParent
922 0 : SumoBaseObjectParent->addParameter(key, value);
923 : }
924 : }
925 0 : }
926 :
927 :
928 : bool
929 0 : RouteHandler::parseNestedCFM(const SumoXMLTag tag, const SUMOSAXAttributes& attrs,
930 : CommonXMLStructure::SumoBaseObject* vTypeObject) {
931 : // write warning info
932 0 : WRITE_WARNINGF(TL("Defining car-following parameters in a nested element is deprecated in vType '%', use attributes instead!"), vTypeObject->getStringAttribute(SUMO_ATTR_ID));
933 : // get vType to modify it
934 0 : auto vType = vTypeObject->getVehicleTypeParameter();
935 : // parse nested CFM attributes
936 0 : if (SUMOVehicleParserHelper::parseCFMParams(&vType, tag, attrs, true)) {
937 0 : vTypeObject->setVehicleTypeParameter(&vType);
938 : return true;
939 0 : } else if (myHardFail) {
940 0 : throw ProcessError(TL("Invalid parsing embedded VType"));
941 : } else {
942 0 : writeError(TL("Invalid parsing embedded VType"));
943 : }
944 0 : return false;
945 0 : }
946 :
947 :
948 : bool
949 0 : RouteHandler::parseStopParameters(SUMOVehicleParameter::Stop& stop, const SUMOSAXAttributes& attrs) {
950 : // check stop parameters
951 0 : if (attrs.hasAttribute(SUMO_ATTR_ARRIVAL)) {
952 0 : stop.parametersSet |= STOP_ARRIVAL_SET;
953 : }
954 0 : if (attrs.hasAttribute(SUMO_ATTR_DURATION)) {
955 0 : stop.parametersSet |= STOP_DURATION_SET;
956 : }
957 0 : if (attrs.hasAttribute(SUMO_ATTR_UNTIL)) {
958 0 : stop.parametersSet |= STOP_UNTIL_SET;
959 : }
960 0 : if (attrs.hasAttribute(SUMO_ATTR_STARTED)) {
961 0 : stop.parametersSet |= STOP_STARTED_SET;
962 : }
963 0 : if (attrs.hasAttribute(SUMO_ATTR_ENDED)) {
964 0 : stop.parametersSet |= STOP_ENDED_SET;
965 : }
966 0 : if (attrs.hasAttribute(SUMO_ATTR_EXTENSION)) {
967 0 : stop.parametersSet |= STOP_EXTENSION_SET;
968 : }
969 0 : if (attrs.hasAttribute(SUMO_ATTR_ENDPOS)) {
970 0 : stop.parametersSet |= STOP_END_SET;
971 : }
972 0 : if (attrs.hasAttribute(SUMO_ATTR_STARTPOS)) {
973 0 : stop.parametersSet |= STOP_START_SET;
974 : }
975 0 : if (attrs.hasAttribute(SUMO_ATTR_POSITION_LAT)) {
976 0 : stop.parametersSet |= STOP_POSLAT_SET;
977 : }
978 0 : if (attrs.hasAttribute(SUMO_ATTR_TRIGGERED)) {
979 0 : stop.parametersSet |= STOP_TRIGGER_SET;
980 : }
981 : // legacy attribute
982 0 : if (attrs.hasAttribute(SUMO_ATTR_CONTAINER_TRIGGERED)) {
983 0 : stop.parametersSet |= STOP_TRIGGER_SET;
984 : }
985 0 : if (attrs.hasAttribute(SUMO_ATTR_PARKING)) {
986 0 : stop.parametersSet |= STOP_PARKING_SET;
987 : }
988 0 : if (attrs.hasAttribute(SUMO_ATTR_EXPECTED)) {
989 0 : stop.parametersSet |= STOP_EXPECTED_SET;
990 : }
991 0 : if (attrs.hasAttribute(SUMO_ATTR_PERMITTED)) {
992 0 : stop.parametersSet |= STOP_PERMITTED_SET;
993 : }
994 0 : if (attrs.hasAttribute(SUMO_ATTR_EXPECTED_CONTAINERS)) {
995 0 : stop.parametersSet |= STOP_EXPECTED_CONTAINERS_SET;
996 : }
997 0 : if (attrs.hasAttribute(SUMO_ATTR_TRIP_ID)) {
998 0 : stop.parametersSet |= STOP_TRIP_ID_SET;
999 : }
1000 0 : if (attrs.hasAttribute(SUMO_ATTR_SPLIT)) {
1001 0 : stop.parametersSet |= STOP_SPLIT_SET;
1002 : }
1003 0 : if (attrs.hasAttribute(SUMO_ATTR_JOIN)) {
1004 0 : stop.parametersSet |= STOP_JOIN_SET;
1005 : }
1006 0 : if (attrs.hasAttribute(SUMO_ATTR_LINE)) {
1007 0 : stop.parametersSet |= STOP_LINE_SET;
1008 : }
1009 0 : if (attrs.hasAttribute(SUMO_ATTR_SPEED)) {
1010 0 : stop.parametersSet |= STOP_SPEED_SET;
1011 : }
1012 0 : if (attrs.hasAttribute(SUMO_ATTR_ONDEMAND)) {
1013 0 : stop.parametersSet |= STOP_ONDEMAND_SET;
1014 : }
1015 0 : if (attrs.hasAttribute(SUMO_ATTR_JUMP)) {
1016 0 : stop.parametersSet |= STOP_JUMP_SET;
1017 : }
1018 : // get parameters
1019 0 : bool ok = true;
1020 : // edge/lane
1021 0 : stop.edge = attrs.getOpt<std::string>(SUMO_ATTR_EDGE, nullptr, ok, "");
1022 0 : stop.lane = attrs.getOpt<std::string>(SUMO_ATTR_LANE, nullptr, ok, stop.busstop);
1023 : // check errors
1024 0 : if (!stop.edge.empty() && !stop.lane.empty()) {
1025 0 : writeError(TL("A stop must be defined either with an edge or with an lane, not both"));
1026 0 : return false;
1027 : }
1028 : // stopping places
1029 0 : stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_BUS_STOP, nullptr, ok, "");
1030 0 : if (stop.busstop.empty()) {
1031 0 : stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_TRAIN_STOP, nullptr, ok, stop.busstop);
1032 : }
1033 0 : stop.chargingStation = attrs.getOpt<std::string>(SUMO_ATTR_CHARGING_STATION, nullptr, ok, "");
1034 0 : stop.overheadWireSegment = attrs.getOpt<std::string>(SUMO_ATTR_OVERHEAD_WIRE_SEGMENT, nullptr, ok, "");
1035 0 : stop.containerstop = attrs.getOpt<std::string>(SUMO_ATTR_CONTAINER_STOP, nullptr, ok, "");
1036 0 : stop.parkingarea = attrs.getOpt<std::string>(SUMO_ATTR_PARKING_AREA, nullptr, ok, "");
1037 : //check stopping places
1038 0 : const int numStoppingPlaces = !stop.busstop.empty() + !stop.chargingStation.empty() + !stop.overheadWireSegment.empty() +
1039 0 : !stop.containerstop.empty() + !stop.parkingarea.empty();
1040 0 : if (numStoppingPlaces > 1) {
1041 0 : writeError(TL("A stop must be defined only in a StoppingPlace"));
1042 0 : return false;
1043 0 : } else if ((numStoppingPlaces == 0) && stop.edge.empty() && stop.lane.empty()) {
1044 0 : writeError(TL("A stop must be defined in an edge, a lane, or in a StoppingPlace"));
1045 0 : return false;
1046 : }
1047 : // declare error suffix
1048 : std::string errorSuffix;
1049 0 : if (stop.busstop != "") {
1050 0 : errorSuffix = " at '" + stop.busstop + "'" + errorSuffix;
1051 0 : } else if (stop.chargingStation != "") {
1052 0 : errorSuffix = " at '" + stop.chargingStation + "'" + errorSuffix;
1053 0 : } else if (stop.overheadWireSegment != "") {
1054 0 : errorSuffix = " at '" + stop.overheadWireSegment + "'" + errorSuffix;
1055 0 : } else if (stop.containerstop != "") {
1056 0 : errorSuffix = " at '" + stop.containerstop + "'" + errorSuffix;
1057 0 : } else if (stop.parkingarea != "") {
1058 0 : errorSuffix = " at '" + stop.parkingarea + "'" + errorSuffix;
1059 0 : } else if (stop.edge != "") {
1060 0 : errorSuffix = " at '" + stop.edge + "'" + errorSuffix;
1061 : } else {
1062 0 : errorSuffix = " on lane '" + stop.lane + "'" + errorSuffix;
1063 : }
1064 : // speed for counting as stopped
1065 0 : stop.speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, nullptr, ok, 0);
1066 0 : if (stop.speed < 0) {
1067 0 : writeError("Speed cannot be negative for stop" + errorSuffix);
1068 0 : return false;
1069 : }
1070 : // get the standing duration
1071 0 : bool expectTrigger = !attrs.hasAttribute(SUMO_ATTR_DURATION) && !attrs.hasAttribute(SUMO_ATTR_UNTIL) && !attrs.hasAttribute(SUMO_ATTR_SPEED);
1072 0 : std::vector<std::string> triggers = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_TRIGGERED, nullptr, ok);
1073 : // legacy
1074 0 : if (attrs.getOpt<bool>(SUMO_ATTR_CONTAINER_TRIGGERED, nullptr, ok, false)) {
1075 0 : triggers.push_back(toString(SUMO_TAG_CONTAINER));
1076 : };
1077 0 : SUMOVehicleParameter::parseStopTriggers(triggers, expectTrigger, stop);
1078 0 : stop.startPos = attrs.getOpt<double>(SUMO_ATTR_STARTPOS, nullptr, ok, 0);
1079 0 : stop.endPos = attrs.getOpt<double>(SUMO_ATTR_ENDPOS, nullptr, ok, 0);
1080 0 : stop.friendlyPos = attrs.getOpt<bool>(SUMO_ATTR_FRIENDLY_POS, nullptr, ok, false);
1081 0 : stop.arrival = attrs.getOptSUMOTimeReporting(SUMO_ATTR_ARRIVAL, nullptr, ok, -1);
1082 0 : stop.duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, nullptr, ok, -1);
1083 0 : stop.until = attrs.getOptSUMOTimeReporting(SUMO_ATTR_UNTIL, nullptr, ok, -1);
1084 0 : if (!expectTrigger && (!ok || (stop.duration < 0 && stop.until < 0 && stop.speed == 0))) {
1085 0 : writeError("Invalid duration or end time is given for a stop" + errorSuffix);
1086 0 : return false;
1087 : }
1088 0 : stop.extension = attrs.getOptSUMOTimeReporting(SUMO_ATTR_EXTENSION, nullptr, ok, -1);
1089 0 : const bool defaultParking = (stop.triggered || stop.containerTriggered || stop.parkingarea != "");
1090 0 : stop.parking = attrs.getOpt<ParkingType>(SUMO_ATTR_PARKING, nullptr, ok, defaultParking ? ParkingType::OFFROAD : ParkingType::ONROAD);
1091 0 : if ((stop.parkingarea != "") && (stop.parking == ParkingType::ONROAD)) {
1092 0 : WRITE_WARNING("Stop at parkingarea overrides attribute 'parking' for stop" + errorSuffix);
1093 0 : stop.parking = ParkingType::OFFROAD;
1094 : }
1095 0 : if (!ok) {
1096 0 : writeError("Invalid bool for 'triggered', 'containerTriggered' or 'parking' for stop" + errorSuffix);
1097 0 : return false;
1098 : }
1099 : // expected persons
1100 0 : const std::vector<std::string>& expected = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_EXPECTED, nullptr, ok);
1101 : stop.awaitedPersons.insert(expected.begin(), expected.end());
1102 0 : if (stop.awaitedPersons.size() > 0 && (stop.parametersSet & STOP_TRIGGER_SET) == 0) {
1103 0 : stop.triggered = true;
1104 0 : if ((stop.parametersSet & STOP_PARKING_SET) == 0) {
1105 0 : stop.parking = ParkingType::OFFROAD;
1106 : }
1107 : }
1108 : // permitted transportables
1109 0 : const std::vector<std::string>& permitted = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_PERMITTED, nullptr, ok);
1110 : stop.permitted.insert(permitted.begin(), permitted.end());
1111 : // expected containers
1112 0 : const std::vector<std::string>& expectedContainers = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_EXPECTED_CONTAINERS, nullptr, ok);
1113 : stop.awaitedContainers.insert(expectedContainers.begin(), expectedContainers.end());
1114 0 : if (stop.awaitedContainers.size() > 0 && (stop.parametersSet & STOP_CONTAINER_TRIGGER_SET) == 0) {
1115 0 : stop.containerTriggered = true;
1116 0 : if ((stop.parametersSet & STOP_PARKING_SET) == 0) {
1117 0 : stop.parking = ParkingType::OFFROAD;
1118 : }
1119 : }
1120 : // public transport trip id
1121 0 : stop.tripId = attrs.getOpt<std::string>(SUMO_ATTR_TRIP_ID, nullptr, ok, "");
1122 0 : stop.split = attrs.getOpt<std::string>(SUMO_ATTR_SPLIT, nullptr, ok, "");
1123 0 : stop.join = attrs.getOpt<std::string>(SUMO_ATTR_JOIN, nullptr, ok, "");
1124 0 : stop.line = attrs.getOpt<std::string>(SUMO_ATTR_LINE, nullptr, ok, "");
1125 : // index
1126 0 : const std::string idx = attrs.getOpt<std::string>(SUMO_ATTR_INDEX, nullptr, ok, "end");
1127 0 : if (idx == "end") {
1128 0 : stop.index = STOP_INDEX_END;
1129 0 : } else if (idx == "fit") {
1130 0 : stop.index = STOP_INDEX_FIT;
1131 : } else {
1132 0 : stop.index = attrs.get<int>(SUMO_ATTR_INDEX, nullptr, ok);
1133 0 : if (!ok || stop.index < 0) {
1134 0 : writeError("Invalid 'index' for stop" + errorSuffix);
1135 0 : return false;
1136 : }
1137 : }
1138 0 : stop.started = attrs.getOptSUMOTimeReporting(SUMO_ATTR_STARTED, nullptr, ok, -1);
1139 0 : stop.ended = attrs.getOptSUMOTimeReporting(SUMO_ATTR_ENDED, nullptr, ok, -1);
1140 0 : stop.posLat = attrs.getOpt<double>(SUMO_ATTR_POSITION_LAT, nullptr, ok, INVALID_DOUBLE);
1141 0 : stop.actType = attrs.getOpt<std::string>(SUMO_ATTR_ACTTYPE, nullptr, ok, "");
1142 0 : stop.onDemand = attrs.getOpt<bool>(SUMO_ATTR_ONDEMAND, nullptr, ok, false);
1143 0 : stop.jump = attrs.getOptSUMOTimeReporting(SUMO_ATTR_JUMP, nullptr, ok, -1);
1144 0 : return true;
1145 0 : }
1146 :
1147 :
1148 : bool
1149 0 : RouteHandler::isEmbeddedRoute(const SUMOSAXAttributes& attrs) const {
1150 : // check conditions
1151 0 : if (attrs.hasAttribute(SUMO_ATTR_ID)) {
1152 : return false;
1153 0 : } else if (myCommonXMLStructure.getCurrentSumoBaseObject()->getParentSumoBaseObject() == nullptr) {
1154 : return false;
1155 0 : } else if (myCommonXMLStructure.getCurrentSumoBaseObject()->getParentSumoBaseObject()->hasStringAttribute(SUMO_ATTR_ROUTE)) {
1156 : return false;
1157 0 : } else if (myCommonXMLStructure.getCurrentSumoBaseObject()->getParentSumoBaseObject()->getTag() == SUMO_TAG_FLOW) {
1158 : return true;
1159 0 : } else if (myCommonXMLStructure.getCurrentSumoBaseObject()->getParentSumoBaseObject()->getTag() == SUMO_TAG_VEHICLE) {
1160 : return true;
1161 : } else {
1162 : return false;
1163 : }
1164 : }
1165 :
1166 :
1167 : void
1168 0 : RouteHandler::checkParent(const SumoXMLTag currentTag, const std::vector<SumoXMLTag>& parentTags, bool& ok) {
1169 : // check that parent SUMOBaseObject's tag is the parentTag
1170 0 : const CommonXMLStructure::SumoBaseObject* parent = myCommonXMLStructure.getCurrentSumoBaseObject()->getParentSumoBaseObject();
1171 : // set parent string
1172 : std::string parentStrings;
1173 0 : for (const auto& tag : parentTags) {
1174 0 : if (tag == parentTags.back()) {
1175 0 : parentStrings.append(toString(tag));
1176 : } else {
1177 0 : parentStrings.append(toString(tag) + ", ");
1178 : }
1179 : }
1180 0 : if ((parent != nullptr) &&
1181 0 : (parentTags.size() > 0) &&
1182 0 : (std::find(parentTags.begin(), parentTags.end(), parent->getTag()) == parentTags.end())) {
1183 0 : const std::string id = parent->hasStringAttribute(SUMO_ATTR_ID) ? ", id: '" + parent->getStringAttribute(SUMO_ATTR_ID) + "'" : "";
1184 0 : writeError("'" + toString(currentTag) + "' must be defined within the definition of a '" + parentStrings + "' (found '" + toString(parent->getTag()) + "'" + id + ").");
1185 0 : ok = false;
1186 : }
1187 0 : }
1188 :
1189 : /****************************************************************************/
|