Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/utils/xml/GenericHandler.h
169678 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2002-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 GenericHandler.h
15
/// @author Pablo Alvarez Lopez
16
/// @date Dec 2022
17
///
18
// A handler which converts occurring elements and attributes into strings
19
/****************************************************************************/
20
#pragma once
21
#include <config.h>
22
23
#include <string>
24
#include <map>
25
#include <stack>
26
#include <sstream>
27
#include <vector>
28
#include <xercesc/sax2/Attributes.hpp>
29
#include <xercesc/sax2/DefaultHandler.hpp>
30
#include <utils/common/UtilExceptions.h>
31
#include <utils/common/StringBijection.h>
32
#include "SUMOSAXAttributes.h"
33
34
35
// ===========================================================================
36
// class definitions
37
// ===========================================================================
38
/**
39
* @class GenericHandler
40
* @brief A handler which converts occurring elements and attributes into enums
41
*
42
* Normally, when using a standard SAX-handler, we would have to compare
43
* the incoming XMLCh*-element names with the ones we can parse. The same
44
* applies to parsing the attributes. This was assumed to be very time consuming,
45
* that's why we derive our handlers from this class.
46
*
47
* The idea behind this second handler layer was avoid repeated conversion
48
* from strings/whatever to XMLCh* and back again. The usage is quite straight
49
* forward, the only overhead is the need to define the enums - both elements
50
* and attributes within "SUMOXMLDefinitions". Still, it maybe helps to avoid typos.
51
*
52
* This class implements the SAX-callback and offers a new set of callbacks
53
* which must be implemented by derived classes. Instead of XMLCh*-values,
54
* element names are supplied to the derived classes as enums (int).
55
*
56
* Also, this class allows to retrieve attributes using enums (int) within
57
* the implemented "myStartElement" method.
58
*
59
* Basically, GenericHandler is not derived within SUMO directly, but via SUMOSAXHandler
60
* which knows all tags/attributes used by SUMO. It is still kept separate for
61
* an easier maintainability and later extensions.
62
*/
63
class GenericHandler : public XERCES_CPP_NAMESPACE::DefaultHandler {
64
65
public:
66
// Reader needs access to myStartElement, myEndElement
67
friend class SUMOSAXReader;
68
69
/**
70
* @brief Constructor
71
*
72
* This constructor gets the lists of known tag and attribute names with
73
* their enums (sumotags and sumoattrs in most cases). The end of the list
74
* is signaled by terminatorTag/terminatorAttr respectively.
75
*
76
* The attribute names are converted into XMLCh* and stored within an
77
* internal container. This container is cleared within the destructor.
78
*
79
* @param[in] tags The list of known tags
80
* @param[in] terminatorTag The tag which indicates the end of tags (usually the last entry)
81
* @param[in] attrs The list of known attributes
82
* @param[in] terminatorAttr The attr which indicates the end of attrs (usually the last entry)
83
* @param[in] file The name of the processed file
84
* @param[in] expectedRoot The expected root element, empty string disables the check
85
*
86
* @todo Why are both lists non-const and given as pointers?
87
*/
88
GenericHandler(const std::string& file, const std::string& expectedRoot = "");
89
90
/// @brief Destructor
91
virtual ~GenericHandler();
92
93
/**
94
* @brief The inherited method called when a new tag opens
95
*
96
* The method parses the supplied XMLCh*-qname using the internal name/enum-map
97
* to obtain the enum representation of the attribute name.
98
*
99
* Then, "myStartElement" is called supplying the enumeration value, the
100
* string-representation of the name and the attributes.
101
*
102
* @todo recheck/describe encoding of the string-representation
103
* @todo do not generate and report the string-representation
104
*/
105
void startElement(const XMLCh* const uri, const XMLCh* const localname,
106
const XMLCh* const qname, const XERCES_CPP_NAMESPACE::Attributes& attrs);
107
108
/**
109
* @brief The inherited method called when characters occurred
110
*
111
* The retrieved characters are converted into a string and appended into a
112
* private buffer. They are reported as soon as the element ends.
113
*
114
* @todo recheck/describe what happens with characters when a new element is opened
115
* @todo describe characters processing in the class' head
116
*/
117
void characters(const XMLCh* const chars, const XERCES3_SIZE_t length);
118
119
/**
120
* @brief The inherited method called when a tag is being closed
121
*
122
* This method calls the user-implemented methods myCharacters with the previously
123
* collected and converted characters.
124
*
125
* Then, myEndElement is called, supplying it the qname converted to its enum-
126
* and string-representations.
127
*
128
* @todo recheck/describe encoding of the string-representation
129
* @todo do not generate and report the string-representation
130
*/
131
void endElement(const XMLCh* const uri, const XMLCh* const localname,
132
const XMLCh* const qname);
133
134
/// @brief Assigning a parent handler which is enabled when the specified tag is closed
135
void registerParent(const int tag, GenericHandler* handler);
136
137
/**
138
* @brief Sets the current file name
139
*
140
* @param[in] name The name of the currently processed file
141
*
142
* @todo Hmmm - this is as unsafe as having a direct access to the variable; recheck
143
*/
144
void setFileName(const std::string& name);
145
146
/**
147
* @brief returns the current file name
148
*
149
* @return The name of the currently processed file
150
*/
151
const std::string& getFileName() const;
152
153
/// @name SAX ErrorHandler callbacks
154
//@{
155
156
/**
157
* @brief Handler for XML-warnings
158
*
159
* The message is built using buildErrorMessage and reported
160
* to the warning-instance of the MsgHandler.
161
*
162
* @param[in] exception The occurred exception to process
163
*/
164
void warning(const XERCES_CPP_NAMESPACE::SAXParseException& exception);
165
166
/**
167
* @brief Handler for XML-errors
168
*
169
* The message is built using buildErrorMessage and thrown within a ProcessError.
170
*
171
* @param[in] exception The occurred exception to process
172
* @exception ProcessError On any call
173
*/
174
void error(const XERCES_CPP_NAMESPACE::SAXParseException& exception);
175
176
/**
177
* @brief Handler for XML-errors
178
*
179
* The message is built using buildErrorMessage and thrown within a ProcessError.
180
*
181
* @exception ProcessError On any call
182
* @param[in] exception The occurred exception to process
183
*/
184
void fatalError(const XERCES_CPP_NAMESPACE::SAXParseException& exception);
185
186
//@}
187
188
void setSection(const int element, const bool seen) {
189
mySection = element;
190
mySectionSeen = seen;
191
mySectionOpen = seen;
192
mySectionEnded = false;
193
}
194
195
bool sectionFinished() const {
196
return mySectionEnded;
197
}
198
199
std::pair<int, SUMOSAXAttributes*> retrieveNextSectionStart() {
200
std::pair<int, SUMOSAXAttributes*> ret = myNextSectionStart;
201
myNextSectionStart.first = -1;
202
myNextSectionStart.second = nullptr;
203
return ret;
204
}
205
206
void needsCharacterData(const bool value = true) {
207
myCollectCharacterData = value;
208
}
209
210
protected:
211
/**
212
* @brief Builds an error message
213
*
214
* The error message includes the file name and the line/column information
215
* as supported by the given SAXParseException
216
*
217
* @param[in] exception The name of the currently processed file
218
* @return A string describing the given exception
219
*/
220
std::string buildErrorMessage(const XERCES_CPP_NAMESPACE::SAXParseException& exception);
221
222
/**
223
* @brief Callback method for an opening tag to implement by derived classes
224
*
225
* Called by "startElement" (see there).
226
* @param[in] element The element that contains the characters, given as a int
227
* @param[in] attrs The SAX-attributes, wrapped as SUMOSAXAttributes
228
* @exceptions ProcessError These method may throw a ProcessError if something fails
229
*/
230
virtual void myStartElement(int element,
231
const SUMOSAXAttributes& attrs);
232
233
/**
234
* @brief Callback method for characters to implement by derived classes
235
*
236
* Called by "endElement" (see there).
237
* @param[in] element The opened element, given as a int
238
* @param[in] chars The complete embedded character string
239
* @exceptions ProcessError These method may throw a ProcessError if something fails
240
*/
241
virtual void myCharacters(int element,
242
const std::string& chars);
243
244
/** @brief Callback method for a closing tag to implement by derived classes
245
*
246
* Called by "endElement" (see there).
247
* @param[in] element The closed element, given as a int
248
* @exceptions ProcessError These method may throw a ProcessError if something fails
249
*/
250
virtual void myEndElement(int element);
251
252
/// @brief signal endElement to the parent handler (special case for MSCalibrator)
253
void callParentEnd(int element);
254
255
private:
256
/**
257
* @brief converts from c++-string into unicode
258
*
259
* @todo recheck encoding
260
* @param[in] name The string to convert
261
* @return The string converted into a XMLCh-string
262
*/
263
XMLCh* convert(const std::string& name) const;
264
265
/**
266
* @brief Converts a tag from its string into its numerical representation
267
*
268
* Returns the enum-representation stored for the given tag. If the tag is not
269
* known, SUMO_TAG_NOTHING is returned.
270
* @param[in] tag The string to convert
271
* @return The int-value that represents the string, SUMO_TAG_NOTHING if the named attribute is not known
272
*/
273
int convertTag(const std::string& tag) const;
274
275
private:
276
/// @name elements parsing
277
//@{
278
279
// the type of the map that maps tag names to ints
280
typedef std::map<std::string, int> TagMap;
281
282
// the map of tag names to their internal numerical representation
283
TagMap myTagMap;
284
285
//@}
286
287
/// A list of character strings obtained so far to build the complete characters string at the end
288
std::vector<std::string> myCharactersVector;
289
290
/// @brief The handler to give control back to
291
GenericHandler* myParentHandler;
292
293
/// @brief The tag indicating that control should be given back
294
int myParentIndicator;
295
296
/// @brief The name of the currently parsed file
297
std::string myFileName;
298
299
/// @brief The root element to expect, empty string disables the check
300
std::string myExpectedRoot;
301
302
/// @brief whether the reader should collect character data
303
bool myCollectCharacterData = false;
304
305
/// @brief whether the reader has already seen the root element
306
bool myRootSeen = false;
307
308
/// @brief The tag indicating the current section to parse
309
int mySection = -1;
310
311
/// @brief whether the reader has already seen the begin of the section
312
bool mySectionSeen = false;
313
314
/// @brief whether the reader has already seen the end of the section
315
bool mySectionEnded = false;
316
317
/// @brief whether an element of the current section is open
318
bool mySectionOpen = false;
319
320
std::pair<int, SUMOSAXAttributes*> myNextSectionStart;
321
322
private:
323
/// @brief invalidated copy constructor
324
GenericHandler(const GenericHandler& s);
325
326
/// @brief invalidated assignment operator
327
const GenericHandler& operator=(const GenericHandler& s);
328
329
};
330
331