Eclipse SUMO - Simulation of Urban MObility
GenericHandler.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 // Copyright (C) 2002-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 /****************************************************************************/
18 // A handler which converts occurring elements and attributes into strings
19 /****************************************************************************/
20 #include <config.h>
21 
22 #include <cassert>
27 #include <utils/common/ToString.h>
28 
29 #include "GenericHandler.h"
31 #include "XMLSubSys.h"
32 
33 
34 // ===========================================================================
35 // class definitions
36 // ===========================================================================
37 
38 GenericHandler::GenericHandler(const std::string& file, const std::string& expectedRoot) :
39  myParentHandler(nullptr),
40  myParentIndicator(SUMO_TAG_NOTHING),
41  myFileName(file),
42  myExpectedRoot(expectedRoot), myNextSectionStart(-1, nullptr) {
43 }
44 
45 
47  delete myNextSectionStart.second;
48 }
49 
50 
51 void
52 GenericHandler::setFileName(const std::string& name) {
53  myFileName = name;
54 }
55 
56 
57 const std::string&
59  return myFileName;
60 }
61 
62 
63 XMLCh*
64 GenericHandler::convert(const std::string& name) const {
65  int len = (int)name.length();
66  XMLCh* ret = new XMLCh[len + 1];
67  int i = 0;
68  for (; i < len; i++) {
69  ret[i] = (XMLCh) name[i];
70  }
71  ret[i] = 0;
72  return ret;
73 }
74 
75 
76 void
77 GenericHandler::startElement(const XMLCh* const /*uri*/,
78  const XMLCh* const /*localname*/,
79  const XMLCh* const qname,
80  const XERCES_CPP_NAMESPACE::Attributes& attrs) {
81  std::string name = StringUtils::transcode(qname);
82  if (!myRootSeen && myExpectedRoot != "" && name != myExpectedRoot) {
83  WRITE_WARNINGF(TL("Found root element '%' in file '%' (expected '%')."), name, getFileName(), myExpectedRoot);
84  }
85  myRootSeen = true;
86  myCharactersVector.clear();
87  const int element = convertTag(name);
88  if (mySectionSeen && !mySectionOpen && element != mySection) {
89  mySectionEnded = true;
90  myNextSectionStart.first = element;
91  myNextSectionStart.second = new SUMOSAXAttributesImpl_Xerces(attrs, {}, {}, name);
92  return;
93  }
94  if (element == mySection) {
95  mySectionSeen = true;
96  mySectionOpen = true;
97  }
98  SUMOSAXAttributesImpl_Xerces na(attrs, {}, {}, name);
99  if (element == SUMO_TAG_INCLUDE) {
100  std::string file = na.getString(SUMO_ATTR_HREF);
101  if (!FileHelpers::isAbsolute(file)) {
103  }
104  //XMLSubSys::runParser(*this, file);
105  } else {
106  myStartElement(element, na);
107  }
108 }
109 
110 
111 void
112 GenericHandler::endElement(const XMLCh* const /*uri*/,
113  const XMLCh* const /*localname*/,
114  const XMLCh* const qname) {
115  std::string name = StringUtils::transcode(qname);
116  int element = convertTag(name);
117  // collect characters
118  if (myCharactersVector.size() != 0) {
119  int len = 0;
120  for (int i = 0; i < (int)myCharactersVector.size(); ++i) {
121  len += (int)myCharactersVector[i].length();
122  }
123  char* buf = new char[len + 1];
124  int pos = 0;
125  for (int i = 0; i < (int)myCharactersVector.size(); ++i) {
126  memcpy((unsigned char*) buf + pos, (unsigned char*) myCharactersVector[i].c_str(),
127  sizeof(char)*myCharactersVector[i].length());
128  pos += (int)myCharactersVector[i].length();
129  }
130  buf[pos] = 0;
131 
132  // call user handler
133  try {
134  myCharacters(element, buf);
135  } catch (std::runtime_error&) {
136  delete[] buf;
137  throw;
138  }
139  delete[] buf;
140  }
141  if (element == mySection) {
142  mySectionOpen = false;
143  }
144  if (element != SUMO_TAG_INCLUDE) {
145  myEndElement(element);
146  if (myParentHandler && myParentIndicator == element) {
147  //XMLSubSys::setHandler(*myParentHandler);
149  myParentHandler = nullptr;
150  }
151  }
152 }
153 
154 
155 void
157  myParentHandler = handler;
158  myParentIndicator = tag;
159  //XMLSubSys::setHandler(*this);
160 }
161 
162 
163 void
164 GenericHandler::characters(const XMLCh* const chars, const XERCES3_SIZE_t length) {
166  myCharactersVector.push_back(StringUtils::transcode(chars, (int)length));
167  }
168 }
169 
170 
171 int
172 GenericHandler::convertTag(const std::string& tag) const {
173  TagMap::const_iterator i = myTagMap.find(tag);
174  if (i == myTagMap.end()) {
175  return SUMO_TAG_NOTHING;
176  }
177  return (*i).second;
178 }
179 
180 
181 std::string
182 GenericHandler::buildErrorMessage(const XERCES_CPP_NAMESPACE::SAXParseException& exception) {
183  std::ostringstream buf;
184  char* pMsg = XERCES_CPP_NAMESPACE::XMLString::transcode(exception.getMessage());
185  buf << pMsg << std::endl;
186  buf << " In file '" << getFileName() << "'" << std::endl;
187  buf << " At line/column " << exception.getLineNumber() + 1
188  << '/' << exception.getColumnNumber() << "." << std::endl;
189  XERCES_CPP_NAMESPACE::XMLString::release(&pMsg);
190  return buf.str();
191 }
192 
193 
194 void
195 GenericHandler::warning(const XERCES_CPP_NAMESPACE::SAXParseException& exception) {
196  WRITE_WARNING(buildErrorMessage(exception));
197 }
198 
199 
200 void
201 GenericHandler::error(const XERCES_CPP_NAMESPACE::SAXParseException& exception) {
202  throw ProcessError(buildErrorMessage(exception));
203 }
204 
205 
206 void
207 GenericHandler::fatalError(const XERCES_CPP_NAMESPACE::SAXParseException& exception) {
208  throw ProcessError(buildErrorMessage(exception));
209 }
210 
211 
212 void
214 
215 
216 void
217 GenericHandler::myCharacters(int, const std::string&) {}
218 
219 
220 void
222 
223 void
225  if (myParentHandler) {
226  myParentHandler->myEndElement(element);
227  }
228 }
229 
230 /****************************************************************************/
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:296
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:295
#define TL(string)
Definition: MsgHandler.h:315
@ SUMO_TAG_INCLUDE
@ SUMO_TAG_NOTHING
invalid tag
@ SUMO_ATTR_HREF
static bool isAbsolute(const std::string &path)
Returns the information whether the given path is absolute.
static std::string getConfigurationRelative(const std::string &configPath, const std::string &path)
Returns the second path as a relative path to the first file.
A handler which converts occurring elements and attributes into enums.
void endElement(const XMLCh *const uri, const XMLCh *const localname, const XMLCh *const qname)
The inherited method called when a tag is being closed.
bool myCollectCharacterData
whether the reader should collect character data
bool mySectionEnded
whether the reader has already seen the end of the section
void fatalError(const XERCES_CPP_NAMESPACE::SAXParseException &exception)
Handler for XML-errors.
bool mySectionOpen
whether an element of the current section is open
void registerParent(const int tag, GenericHandler *handler)
Assigning a parent handler which is enabled when the specified tag is closed.
virtual ~GenericHandler()
Destructor.
bool myRootSeen
whether the reader has already seen the root element
virtual void myCharacters(int element, const std::string &chars)
Callback method for characters to implement by derived classes.
void callParentEnd(int element)
signal endElement to the parent handler (special case for MSCalibrator)
GenericHandler(const std::string &file, const std::string &expectedRoot="")
Constructor.
std::string myFileName
The name of the currently parsed file.
int mySection
The tag indicating the current section to parse.
const std::string & getFileName() const
returns the current file name
std::vector< std::string > myCharactersVector
A list of character strings obtained so far to build the complete characters string at the end.
int myParentIndicator
The tag indicating that control should be given back.
virtual void myEndElement(int element)
Callback method for a closing tag to implement by derived classes.
std::string buildErrorMessage(const XERCES_CPP_NAMESPACE::SAXParseException &exception)
Builds an error message.
virtual void myStartElement(int element, const SUMOSAXAttributes &attrs)
Callback method for an opening tag to implement by derived classes.
std::pair< int, SUMOSAXAttributes * > myNextSectionStart
void error(const XERCES_CPP_NAMESPACE::SAXParseException &exception)
Handler for XML-errors.
int convertTag(const std::string &tag) const
Converts a tag from its string into its numerical representation.
XMLCh * convert(const std::string &name) const
converts from c++-string into unicode
void warning(const XERCES_CPP_NAMESPACE::SAXParseException &exception)
Handler for XML-warnings.
GenericHandler * myParentHandler
The handler to give control back to.
bool mySectionSeen
whether the reader has already seen the begin of the section
void setFileName(const std::string &name)
Sets the current file name.
std::string myExpectedRoot
The root element to expect, empty string disables the check.
void characters(const XMLCh *const chars, const XERCES3_SIZE_t length)
The inherited method called when characters occurred.
void startElement(const XMLCh *const uri, const XMLCh *const localname, const XMLCh *const qname, const XERCES_CPP_NAMESPACE::Attributes &attrs)
The inherited method called when a new tag opens.
Encapsulated SAX-Attributes.
Encapsulated Xerces-SAX-attributes.
std::string getString(int id, bool *isPresent=nullptr) const
Returns the string-value of the named (by its enum-value) attribute.
static std::string transcode(const XMLCh *const data)
converts a 0-terminated XMLCh* array (usually UTF-16, stemming from Xerces) into std::string in UTF-8
Definition: StringUtils.h:146