Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/utils/handlers/CommonHandler.cpp
169678 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2001-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 CommonHandler.cpp
15
/// @author Pablo Alvarez Lopez
16
/// @date Dec 2024
17
///
18
// Collection of functions used in handlers
19
/****************************************************************************/
20
#include <config.h>
21
22
#include <utils/common/MsgHandler.h>
23
#include <utils/common/StringUtils.h>
24
#include <utils/xml/XMLSubSys.h>
25
26
#include "CommonHandler.h"
27
28
29
// ===========================================================================
30
// method definitions
31
// ===========================================================================
32
33
CommonHandler::CommonHandler(const std::string& filename) :
34
myFilename(filename) {
35
}
36
37
38
CommonHandler::~CommonHandler() {}
39
40
41
void
42
CommonHandler::forceOverwriteElements() {
43
myOverwriteElements = true;
44
}
45
46
47
void
48
CommonHandler::forceRemainElements() {
49
myRemainElements = true;
50
}
51
52
53
void
54
CommonHandler::abortLoading() {
55
myAbortLoading = true;
56
}
57
58
59
bool
60
CommonHandler::isErrorCreatingElement() const {
61
return myErrorCreatingElement;
62
}
63
64
65
bool
66
CommonHandler::isForceOverwriteElements() const {
67
return myOverwriteElements;
68
}
69
70
71
bool
72
CommonHandler::isForceRemainElements() const {
73
return myRemainElements;
74
}
75
76
77
bool
78
CommonHandler::isAbortLoading() const {
79
return myAbortLoading;
80
}
81
82
83
void
84
CommonHandler::parseParameters(const SUMOSAXAttributes& attrs) {
85
// declare Ok Flag
86
bool parsedOk = true;
87
// get key
88
const std::string key = attrs.get<std::string>(SUMO_ATTR_KEY, nullptr, parsedOk);
89
// get SumoBaseObject parent
90
CommonXMLStructure::SumoBaseObject* SumoBaseObjectParent = myCommonXMLStructure.getCurrentSumoBaseObject()->getParentSumoBaseObject();
91
// check parent
92
if ((SumoBaseObjectParent == nullptr) || (SumoBaseObjectParent->getTag() == SUMO_TAG_ROOTFILE)) {
93
writeError(TL("Parameters must be defined within an object"));
94
} else if (SumoBaseObjectParent->getTag() == SUMO_TAG_PARAM) {
95
writeError(TL("Parameters cannot be defined within another parameter."));
96
} else if ((SumoBaseObjectParent->getTag() != SUMO_TAG_ERROR) && parsedOk) {
97
// get tag str
98
const std::string parentTagStr = toString(SumoBaseObjectParent->getTag());
99
// circumventing empty string value
100
const std::string value = attrs.hasAttribute(SUMO_ATTR_VALUE) ? attrs.getString(SUMO_ATTR_VALUE) : "";
101
// show warnings if values are invalid
102
if (key.empty()) {
103
writeError(TLF("Error parsing key from % generic parameter. Key cannot be empty", parentTagStr));
104
} else if (!SUMOXMLDefinitions::isValidParameterKey(key)) {
105
writeError(TLF("Error parsing key from % generic parameter. Key contains invalid characters", parentTagStr));
106
} else {
107
// insert parameter in SumoBaseObjectParent
108
SumoBaseObjectParent->addParameter(key, value);
109
}
110
}
111
}
112
113
114
CommonXMLStructure::SumoBaseObject*
115
CommonHandler::getEmbeddedRoute(const CommonXMLStructure::SumoBaseObject* sumoBaseObject) const {
116
// locate route in childrens
117
for (const auto& embeddedRoute : sumoBaseObject->getSumoBaseObjectChildren()) {
118
if ((embeddedRoute->getTag() == SUMO_TAG_ROUTE) && (!embeddedRoute->hasStringAttribute(SUMO_ATTR_ID))) {
119
return embeddedRoute;
120
}
121
}
122
return nullptr;
123
}
124
125
126
void
127
CommonHandler::checkParsedParent(const SumoXMLTag currentTag, const std::vector<SumoXMLTag>& parentTags, bool& ok) {
128
if (parentTags.size() > 0) {
129
std::string tagsStr;
130
for (auto it = parentTags.begin(); it != parentTags.end(); it++) {
131
tagsStr.append(toString(*it));
132
if ((it + 1) != parentTags.end()) {
133
if ((it + 2) != parentTags.end()) {
134
tagsStr.append(", ");
135
} else {
136
tagsStr.append(" or ");
137
}
138
}
139
}
140
// obtain parent
141
CommonXMLStructure::SumoBaseObject* const parent = myCommonXMLStructure.getCurrentSumoBaseObject()->getParentSumoBaseObject();
142
if (parent == nullptr) {
143
ok = writeError(TLF("'%' must be defined within the definition of a %.", toString(currentTag), tagsStr));
144
} else if ((parent->getTag() != SUMO_TAG_ERROR) && std::find(parentTags.begin(), parentTags.end(), parent->getTag()) == parentTags.end()) {
145
if (parent->hasStringAttribute(SUMO_ATTR_ID)) {
146
ok = writeError(TLF("'%' must be defined within the definition of a '%' (found % '%').", toString(currentTag), tagsStr,
147
toString(parent->getTag()), parent->getStringAttribute(SUMO_ATTR_ID)));
148
} else {
149
ok = writeError(TLF("'%' must be defined within the definition of a '%' (found %).", toString(currentTag), tagsStr,
150
toString(parent->getTag())));
151
}
152
}
153
}
154
}
155
156
157
bool
158
CommonHandler::checkListOfVehicleTypes(const SumoXMLTag tag, const std::string& id, const std::vector<std::string>& vTypeIDs) {
159
for (const auto& vTypeID : vTypeIDs) {
160
if (!SUMOXMLDefinitions::isValidTypeID(vTypeID)) {
161
return writeError(TLF("Could not build % with ID '%' in netedit; '%' ist not a valid vType ID.", toString(tag), id, vTypeID));
162
}
163
}
164
return true;
165
}
166
167
168
bool
169
CommonHandler::checkWithinDistribution(CommonXMLStructure::SumoBaseObject* obj) {
170
if (obj->getParentSumoBaseObject() == nullptr) {
171
return false;
172
} else if (obj->getParentSumoBaseObject()->getTag() == SUMO_TAG_ROUTE_DISTRIBUTION) {
173
return true;
174
} else if (obj->getParentSumoBaseObject()->getTag() == SUMO_TAG_VTYPE_DISTRIBUTION) {
175
return true;
176
} else {
177
return false;
178
}
179
}
180
181
182
bool
183
CommonHandler::checkVehicleParents(CommonXMLStructure::SumoBaseObject* obj) {
184
if (obj == nullptr) {
185
return false;
186
} else if (!obj->hasStringAttribute(SUMO_ATTR_ID)) {
187
return false;
188
} else {
189
SumoXMLTag tag = obj->getTag();
190
const std::string id = obj->getStringAttribute(SUMO_ATTR_ID);
191
const bool hasRoute = obj->hasStringAttribute(SUMO_ATTR_ROUTE);
192
const bool hasEmbeddedRoute = (getEmbeddedRoute(obj) != nullptr);
193
const bool overEdges = obj->hasStringAttribute(SUMO_ATTR_FROM) && obj->hasStringAttribute(SUMO_ATTR_TO);
194
const bool overJunctions = obj->hasStringAttribute(SUMO_ATTR_FROM_JUNCTION) && obj->hasStringAttribute(SUMO_ATTR_TO_JUNCTION);
195
const bool overTAZs = obj->hasStringAttribute(SUMO_ATTR_FROM_TAZ) && obj->hasStringAttribute(SUMO_ATTR_TO_TAZ);
196
if (hasRoute && hasEmbeddedRoute) {
197
return writeError(TLF("Could not build % with ID '%' in netedit; Cannot have an external route and an embedded route in the same definition.", toString(tag), id));
198
}
199
if ((overEdges + overJunctions + overTAZs) > 1) {
200
return writeError(TLF("Could not build % with ID '%' in netedit; Cannot have multiple from-to attributes.", toString(tag), id));
201
}
202
if ((hasRoute + hasEmbeddedRoute + overEdges + overJunctions + overTAZs) > 1) {
203
return writeError(TLF("Could not build % with ID '%' in netedit; Cannot have from-to attributes and route attributes in the same definition.", toString(tag), id));
204
}
205
if ((hasRoute + hasEmbeddedRoute + overEdges + overJunctions + overTAZs) == 0) {
206
return writeError(TLF("Could not build % with ID '%' in netedit; Requires either a route or an embedded route or a from-to attribute (Edges, junctions or TAZs).", toString(tag), id));
207
}
208
return true;
209
}
210
}
211
212
213
bool
214
CommonHandler::checkPersonPlanParents(CommonXMLStructure::SumoBaseObject* obj) {
215
const auto parent = obj->getParentSumoBaseObject();
216
if (parent == nullptr) {
217
return false;
218
} else if (!parent->wasCreated()) {
219
return false;
220
} else if ((parent->getTag() == SUMO_TAG_PERSON) || (parent->getTag() == SUMO_TAG_PERSONFLOW)) {
221
return true;
222
} else {
223
return false;
224
}
225
}
226
227
228
bool
229
CommonHandler::checkContainerPlanParents(CommonXMLStructure::SumoBaseObject* obj) {
230
const auto parent = obj->getParentSumoBaseObject();
231
if (parent == nullptr) {
232
return false;
233
} else if (!parent->wasCreated()) {
234
return false;
235
} else if ((parent->getTag() == SUMO_TAG_CONTAINER) || (parent->getTag() == SUMO_TAG_CONTAINERFLOW)) {
236
return true;
237
} else {
238
return false;
239
}
240
}
241
242
243
bool
244
CommonHandler::checkStopParents(CommonXMLStructure::SumoBaseObject* obj) {
245
const auto parent = obj->getParentSumoBaseObject();
246
if (parent == nullptr) {
247
return false;
248
} else if (!parent->wasCreated()) {
249
return false;
250
} else if ((parent->getTag() == SUMO_TAG_ROUTE) || (parent->getTag() == SUMO_TAG_TRIP) ||
251
(parent->getTag() == SUMO_TAG_VEHICLE) || (parent->getTag() == SUMO_TAG_FLOW) ||
252
(parent->getTag() == SUMO_TAG_PERSON) || (parent->getTag() == SUMO_TAG_PERSONFLOW) ||
253
(parent->getTag() == SUMO_TAG_CONTAINER) || (parent->getTag() == SUMO_TAG_CONTAINERFLOW)) {
254
return true;
255
} else {
256
return false;
257
}
258
}
259
260
261
bool
262
CommonHandler::checkNegative(const SumoXMLTag tag, const std::string& id, const SumoXMLAttr attribute, const int value, const bool canBeZero) {
263
if (canBeZero) {
264
if (value < 0) {
265
return writeError(TLF("Could not build % with ID '%' in netedit; Attribute % cannot be negative.", toString(tag), id, toString(attribute)));
266
} else {
267
return true;
268
}
269
} else {
270
if (value <= 0) {
271
return writeError(TLF("Could not build % with ID '%' in netedit; Attribute % must be greather than zero.", toString(tag), id, toString(attribute)));
272
} else {
273
return true;
274
}
275
}
276
}
277
278
279
bool
280
CommonHandler::checkNegative(const SumoXMLTag tag, const std::string& id, const SumoXMLAttr attribute, const double value, const bool canBeZero) {
281
if (canBeZero) {
282
if (value < 0) {
283
return writeError(TLF("Could not build % with ID '%' in netedit; Attribute % cannot be negative (%).", toString(tag), id, toString(attribute), toString(value)));
284
} else {
285
return true;
286
}
287
} else {
288
if (value <= 0) {
289
return writeError(TLF("Could not build % with ID '%' in netedit; Attribute % must be greather than zero (%).", toString(tag), id, toString(attribute), toString(value)));
290
} else {
291
return true;
292
}
293
}
294
}
295
296
297
bool
298
CommonHandler::checkNegative(const SumoXMLTag tag, const std::string& id, const SumoXMLAttr attribute, const SUMOTime value, const bool canBeZero) {
299
if (canBeZero) {
300
if (value < 0) {
301
return writeError(TLF("Could not build % with ID '%' in netedit; Attribute % cannot be negative (%).", toString(tag), id, toString(attribute), time2string(value)));
302
} else {
303
return true;
304
}
305
} else {
306
if (value <= 0) {
307
return writeError(TLF("Could not build % with ID '%' in netedit; Attribute % must be greather than zero (%).", toString(tag), id, toString(attribute), time2string(value)));
308
} else {
309
return true;
310
}
311
}
312
}
313
314
315
bool
316
CommonHandler::checkFileName(const SumoXMLTag tag, const std::string& id, const SumoXMLAttr attribute, const std::string& value) {
317
if (SUMOXMLDefinitions::isValidFilename(value)) {
318
return true;
319
} else {
320
return writeError(TLF("Could not build % with ID '%' in netedit; % is invalid % ()", toString(tag), id, toString(attribute), value));
321
}
322
}
323
324
325
bool
326
CommonHandler::checkValidAdditionalID(const SumoXMLTag tag, const std::string& value) {
327
if (value.empty()) {
328
return writeError(TLF("Could not build %; ID cannot be empty", toString(tag)));
329
} else if (!SUMOXMLDefinitions::isValidVehicleID(value)) {
330
return writeError(TLF("Could not build % with ID '%' in netedit; ID contains invalid characters.", toString(tag), value));
331
} else {
332
return true;
333
}
334
}
335
336
337
bool
338
CommonHandler::checkValidDetectorID(const SumoXMLTag tag, const std::string& value) {
339
if (value.empty()) {
340
return writeError(TLF("Could not build %; ID cannot be empty", toString(tag)));
341
} else if (!SUMOXMLDefinitions::isValidDetectorID(value)) {
342
return writeError(TLF("Could not build % with ID '%' in netedit; detector ID contains invalid characters.", toString(tag), value));
343
} else {
344
return true;
345
}
346
}
347
348
349
bool
350
CommonHandler::checkValidDemandElementID(const SumoXMLTag tag, const std::string& value) {
351
if (value.empty()) {
352
return writeError(TLF("Could not build %; ID cannot be empty", toString(tag)));
353
} else if (!SUMOXMLDefinitions::isValidVehicleID(value)) {
354
return writeError(TLF("Could not build % with ID '%' in netedit; ID contains invalid characters.", toString(tag), value));
355
} else {
356
return true;
357
}
358
}
359
360
361
void
362
CommonHandler::writeWarningOverwriting(const SumoXMLTag tag, const std::string& id) {
363
WRITE_WARNING(TLF("Overwriting % with ID '%'", toString(tag), id));
364
}
365
366
367
bool
368
CommonHandler::writeWarningDuplicated(const SumoXMLTag tag, const std::string& id, const SumoXMLTag checkedTag) {
369
WRITE_WARNING(TLF("Could not build % with ID '%' in netedit; Found another % with the same ID.", toString(tag), id, toString(checkedTag)));
370
return false;
371
}
372
373
374
bool
375
CommonHandler::writeError(const std::string& error) {
376
WRITE_ERROR(error);
377
myErrorCreatingElement = true;
378
return false;
379
}
380
381
382
bool
383
CommonHandler::writeErrorInvalidPosition(const SumoXMLTag tag, const std::string& id) {
384
return writeError(TLF("Could not build % with ID '%' in netedit; Invalid position over lane.", toString(tag), id));
385
}
386
387
388
bool
389
CommonHandler::writeErrorEmptyEdges(const SumoXMLTag tag, const std::string& id) {
390
return writeError(TLF("Could not build % with ID '%' in netedit; List of edges cannot be empty.", toString(tag), id));
391
}
392
393
394
bool
395
CommonHandler::writeErrorInvalidLanes(const SumoXMLTag tag, const std::string& id) {
396
return writeError(TLF("Could not build % with ID '%' in netedit; List of lanes isn't valid.", toString(tag), id));
397
}
398
399
400
bool
401
CommonHandler::writeErrorInvalidParent(const SumoXMLTag tag, const std::string& id, const SumoXMLTag parentTag, const std::string& parentID) {
402
return writeError(TLF("Could not build % with ID '%' in netedit; % parent with ID '%' doesn't exist.", toString(tag), id, toString(parentTag), parentID));
403
}
404
405
406
bool
407
CommonHandler::writeErrorInvalidParent(const SumoXMLTag tag, const SumoXMLTag parentTag, const std::string& parentID) {
408
return writeError(TLF("Could not build % in netedit; % parent with ID '%' doesn't exist.", toString(tag), toString(parentTag), parentID));
409
}
410
411
412
bool
413
CommonHandler::writeErrorInvalidParent(const SumoXMLTag tag, const SumoXMLTag parentTag) {
414
return writeError(TLF("Could not build % in netedit; % parent doesn't exist.", toString(tag), toString(parentTag)));
415
}
416
417
/****************************************************************************/
418
419