Line data Source code
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 : /****************************************************************************/ 14 : /// @file GenericHandler.cpp 15 : /// @author Pablo Alvarez Lopez 16 : /// @date Dec 2022 17 : /// 18 : // A handler which converts occurring elements and attributes into strings 19 : /****************************************************************************/ 20 : #include <config.h> 21 : 22 : #include <cassert> 23 : #include <utils/common/StringUtils.h> 24 : #include <utils/common/StringUtils.h> 25 : #include <utils/common/FileHelpers.h> 26 : #include <utils/common/MsgHandler.h> 27 : #include <utils/common/ToString.h> 28 : 29 : #include "GenericHandler.h" 30 : #include "SUMOSAXAttributesImpl_Xerces.h" 31 : #include "XMLSubSys.h" 32 : 33 : 34 : // =========================================================================== 35 : // class definitions 36 : // =========================================================================== 37 : 38 0 : GenericHandler::GenericHandler(const std::string& file, const std::string& expectedRoot) : 39 0 : myParentHandler(nullptr), 40 0 : myParentIndicator(SUMO_TAG_NOTHING), 41 0 : myFileName(file), 42 0 : myExpectedRoot(expectedRoot), myNextSectionStart(-1, nullptr) { 43 0 : } 44 : 45 : 46 0 : GenericHandler::~GenericHandler() { 47 0 : delete myNextSectionStart.second; 48 0 : } 49 : 50 : 51 : void 52 0 : GenericHandler::setFileName(const std::string& name) { 53 0 : myFileName = name; 54 0 : } 55 : 56 : 57 : const std::string& 58 0 : GenericHandler::getFileName() const { 59 0 : return myFileName; 60 : } 61 : 62 : 63 : XMLCh* 64 0 : GenericHandler::convert(const std::string& name) const { 65 0 : int len = (int)name.length(); 66 0 : XMLCh* ret = new XMLCh[len + 1]; 67 : int i = 0; 68 0 : for (; i < len; i++) { 69 0 : ret[i] = (XMLCh) name[i]; 70 : } 71 0 : ret[i] = 0; 72 0 : return ret; 73 : } 74 : 75 : 76 : void 77 0 : GenericHandler::startElement(const XMLCh* const /*uri*/, 78 : const XMLCh* const /*localname*/, 79 : const XMLCh* const qname, 80 : const XERCES_CPP_NAMESPACE::Attributes& attrs) { 81 0 : std::string name = StringUtils::transcode(qname); 82 0 : if (!myRootSeen && myExpectedRoot != "" && name != myExpectedRoot) { 83 0 : WRITE_WARNINGF(TL("Found root element '%' in file '%' (expected '%')."), name, getFileName(), myExpectedRoot); 84 : } 85 0 : myRootSeen = true; 86 : myCharactersVector.clear(); 87 0 : const int element = convertTag(name); 88 0 : if (mySectionSeen && !mySectionOpen && element != mySection) { 89 0 : mySectionEnded = true; 90 0 : myNextSectionStart.first = element; 91 0 : myNextSectionStart.second = new SUMOSAXAttributesImpl_Xerces(attrs, {}, {}, name); 92 : return; 93 : } 94 0 : if (element == mySection) { 95 0 : mySectionSeen = true; 96 0 : mySectionOpen = true; 97 : } 98 0 : SUMOSAXAttributesImpl_Xerces na(attrs, {}, {}, name); 99 0 : if (element == SUMO_TAG_INCLUDE) { 100 0 : std::string file = na.getString(SUMO_ATTR_HREF); 101 0 : if (!FileHelpers::isAbsolute(file)) { 102 0 : file = FileHelpers::getConfigurationRelative(getFileName(), file); 103 : } 104 : //XMLSubSys::runParser(*this, file); 105 : } else { 106 0 : myStartElement(element, na); 107 : } 108 0 : } 109 : 110 : 111 : void 112 0 : GenericHandler::endElement(const XMLCh* const /*uri*/, 113 : const XMLCh* const /*localname*/, 114 : const XMLCh* const qname) { 115 0 : std::string name = StringUtils::transcode(qname); 116 0 : int element = convertTag(name); 117 : // collect characters 118 0 : if (myCharactersVector.size() != 0) { 119 : int len = 0; 120 0 : for (int i = 0; i < (int)myCharactersVector.size(); ++i) { 121 0 : len += (int)myCharactersVector[i].length(); 122 : } 123 0 : char* buf = new char[len + 1]; 124 : int pos = 0; 125 0 : for (int i = 0; i < (int)myCharactersVector.size(); ++i) { 126 0 : memcpy((unsigned char*) buf + pos, (unsigned char*) myCharactersVector[i].c_str(), 127 0 : sizeof(char)*myCharactersVector[i].length()); 128 0 : pos += (int)myCharactersVector[i].length(); 129 : } 130 0 : buf[pos] = 0; 131 : 132 : // call user handler 133 : try { 134 0 : myCharacters(element, buf); 135 0 : } catch (std::runtime_error&) { 136 0 : delete[] buf; 137 0 : throw; 138 0 : } 139 0 : delete[] buf; 140 : } 141 0 : if (element == mySection) { 142 0 : mySectionOpen = false; 143 : } 144 0 : if (element != SUMO_TAG_INCLUDE) { 145 0 : myEndElement(element); 146 0 : if (myParentHandler && myParentIndicator == element) { 147 : //XMLSubSys::setHandler(*myParentHandler); 148 0 : myParentIndicator = SUMO_TAG_NOTHING; 149 0 : myParentHandler = nullptr; 150 : } 151 : } 152 0 : } 153 : 154 : 155 : void 156 0 : GenericHandler::registerParent(const int tag, GenericHandler* handler) { 157 0 : myParentHandler = handler; 158 0 : myParentIndicator = tag; 159 : //XMLSubSys::setHandler(*this); 160 0 : } 161 : 162 : 163 : void 164 0 : GenericHandler::characters(const XMLCh* const chars, const XERCES3_SIZE_t length) { 165 0 : if (myCollectCharacterData) { 166 0 : myCharactersVector.push_back(StringUtils::transcode(chars, (int)length)); 167 : } 168 0 : } 169 : 170 : 171 : int 172 0 : GenericHandler::convertTag(const std::string& tag) const { 173 : TagMap::const_iterator i = myTagMap.find(tag); 174 0 : if (i == myTagMap.end()) { 175 : return SUMO_TAG_NOTHING; 176 : } 177 0 : return (*i).second; 178 : } 179 : 180 : 181 : std::string 182 0 : GenericHandler::buildErrorMessage(const XERCES_CPP_NAMESPACE::SAXParseException& exception) { 183 0 : std::ostringstream buf; 184 0 : char* pMsg = XERCES_CPP_NAMESPACE::XMLString::transcode(exception.getMessage()); 185 0 : buf << pMsg << std::endl; 186 0 : buf << " In file '" << getFileName() << "'" << std::endl; 187 0 : buf << " At line/column " << exception.getLineNumber() + 1 188 0 : << '/' << exception.getColumnNumber() << "." << std::endl; 189 0 : XERCES_CPP_NAMESPACE::XMLString::release(&pMsg); 190 0 : return buf.str(); 191 0 : } 192 : 193 : 194 : void 195 0 : GenericHandler::warning(const XERCES_CPP_NAMESPACE::SAXParseException& exception) { 196 0 : WRITE_WARNING(buildErrorMessage(exception)); 197 0 : } 198 : 199 : 200 : void 201 0 : GenericHandler::error(const XERCES_CPP_NAMESPACE::SAXParseException& exception) { 202 0 : throw ProcessError(buildErrorMessage(exception)); 203 : } 204 : 205 : 206 : void 207 0 : GenericHandler::fatalError(const XERCES_CPP_NAMESPACE::SAXParseException& exception) { 208 0 : throw ProcessError(buildErrorMessage(exception)); 209 : } 210 : 211 : 212 : void 213 0 : GenericHandler::myStartElement(int, const SUMOSAXAttributes&) {} 214 : 215 : 216 : void 217 0 : GenericHandler::myCharacters(int, const std::string&) {} 218 : 219 : 220 : void 221 0 : GenericHandler::myEndElement(int) {} 222 : 223 : void 224 0 : GenericHandler::callParentEnd(int element) { 225 0 : if (myParentHandler) { 226 0 : myParentHandler->myEndElement(element); 227 : } 228 0 : } 229 : 230 : /****************************************************************************/