LCOV - code coverage report
Current view: top level - src/utils/handlers - TemplateHandler.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 0.0 % 121 0
Test Date: 2024-12-21 15:45:41 Functions: 0.0 % 10 0

            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    TemplateHandler.cpp
      15              : /// @author  Pablo Alvarez Lopez
      16              : /// @date    Dec 2022
      17              : ///
      18              : // A SAX-Handler for loading templates
      19              : /****************************************************************************/
      20              : #include <config.h>
      21              : 
      22              : #include <algorithm>
      23              : #include <string>
      24              : #include <vector>
      25              : #include <xercesc/sax/HandlerBase.hpp>
      26              : #include <xercesc/sax/AttributeList.hpp>
      27              : #include <xercesc/sax/SAXParseException.hpp>
      28              : #include <xercesc/sax/SAXException.hpp>
      29              : #include <utils/common/StringUtils.h>
      30              : #include <utils/common/StringTokenizer.h>
      31              : #include <utils/common/UtilExceptions.h>
      32              : #include <utils/common/FileHelpers.h>
      33              : #include <utils/common/MsgHandler.h>
      34              : #include <utils/common/ToString.h>
      35              : #include <utils/options/OptionsCont.h>
      36              : #include <xercesc/parsers/SAXParser.hpp>
      37              : #include <xercesc/sax2/XMLReaderFactory.hpp>
      38              : #include <xercesc/framework/LocalFileInputSource.hpp>
      39              : #include <xercesc/framework/MemBufInputSource.hpp>
      40              : 
      41              : #include "TemplateHandler.h"
      42              : 
      43              : 
      44              : const std::string TemplateHandler::INVALID_INT_STR = toString(INVALID_INT);
      45              : const std::string TemplateHandler::INVALID_DOUBLE_STR = toString(INVALID_DOUBLE);
      46              : 
      47              : // ===========================================================================
      48              : // method definitions
      49              : // ===========================================================================
      50              : 
      51              : void
      52            0 : TemplateHandler::parseTemplate(OptionsCont& options, const std::string& templateString) {
      53              :     // build parser
      54            0 :     XERCES_CPP_NAMESPACE::SAXParser parser;
      55              :     // disable validation
      56            0 :     parser.setValidationScheme(XERCES_CPP_NAMESPACE::SAXParser::Val_Never);
      57            0 :     parser.setDisableDefaultEntityResolution(true);
      58              :     // build TemplateHandler
      59            0 :     TemplateHandler handler(options);
      60              :     // start parsing
      61              :     try {
      62            0 :         parser.setDocumentHandler(&handler);
      63            0 :         parser.setErrorHandler(&handler);
      64            0 :         XERCES_CPP_NAMESPACE::MemBufInputSource memBufIS((const XMLByte*)templateString.c_str(), templateString.size(), "template");
      65            0 :         parser.parse(memBufIS);
      66            0 :         if (handler.myError) {
      67            0 :             throw ProcessError(TLF("Could not load template '%'.", templateString));
      68              :         }
      69            0 :     } catch (const XERCES_CPP_NAMESPACE::XMLException& e) {
      70            0 :         throw ProcessError("Could not load template '" + templateString + "':\n " + StringUtils::transcode(e.getMessage()));
      71            0 :     }
      72              :     // mark al loaded options as default
      73            0 :     options.resetDefault();
      74            0 : }
      75              : 
      76            0 : TemplateHandler::TemplateHandler(OptionsCont& options) :
      77            0 :     myError(false),
      78            0 :     myOptions(options) {
      79            0 : }
      80              : 
      81              : 
      82            0 : TemplateHandler::~TemplateHandler() {}
      83              : 
      84              : 
      85              : void
      86            0 : TemplateHandler::startElement(const XMLCh* const name, XERCES_CPP_NAMESPACE::AttributeList& attributes) {
      87              :     // get current topic
      88            0 :     myOptionName = StringUtils::transcode(name);
      89            0 :     if (myLevel++ == 0) {
      90              :         // skip root elemnt
      91              :         return;
      92              :     }
      93              :     // check if this is a subtopic
      94            0 :     if (attributes.getLength() == 0) {
      95            0 :         mySubTopic = myOptionName;
      96            0 :         myOptions.addOptionSubTopic(mySubTopic);
      97              :     } else {
      98              :         // declare options parameters (by default all empty)
      99              :         std::string value;
     100              :         std::string synonymes;
     101              :         std::string type;
     102              :         std::string help;
     103              :         bool required = false;
     104              :         bool positional = false;
     105            0 :         std::string listSep = "";
     106              :         // iterate over attributes
     107            0 :         for (int i = 0; i < (int)attributes.getLength(); i++) {
     108            0 :             const std::string attributeName = StringUtils::transcode(attributes.getName(i));
     109            0 :             const std::string attributeValue = StringUtils::transcode(attributes.getValue(i));
     110              :             // check attribute name
     111            0 :             if (attributeName == "value") {
     112              :                 value = attributeValue;
     113            0 :             } else if (attributeName == "synonymes") {
     114              :                 synonymes = attributeValue;
     115            0 :             } else if (attributeName == "type") {
     116              :                 type = attributeValue;
     117            0 :             } else if (attributeName == "help") {
     118              :                 help = attributeValue;
     119            0 :             } else if (attributeName == "category") {
     120              :                 // tool templates have subtopic as attribute category
     121            0 :                 mySubTopic = attributeValue;
     122            0 :                 const auto& topics = myOptions.getSubTopics();
     123            0 :                 if (std::find(topics.begin(), topics.end(), attributeValue) == topics.end()) {
     124            0 :                     myOptions.addOptionSubTopic(attributeValue);
     125              :                 }
     126            0 :             } else if (attributeName == "required") {
     127            0 :                 required = StringUtils::toBool(attributeValue);
     128            0 :             } else if (attributeName == "positional") {
     129            0 :                 positional = StringUtils::toBool(attributeValue);
     130            0 :             } else if (attributeName == "listSeparator") {
     131              :                 listSep = attributeValue;
     132              :             }
     133              :         }
     134              :         // add option
     135            0 :         addOption(value, synonymes, type, help, required, positional, listSep);
     136              :     }
     137              : }
     138              : 
     139              : 
     140              : bool
     141            0 : TemplateHandler::addOption(std::string value, const std::string& synonymes, const std::string& type,
     142              :                            const std::string& help, bool required, bool positional, const std::string& listSep) const {
     143            0 :     if (myOptions.exists(myOptionName)) {
     144            0 :         WRITE_WARNING(myOptionName + " already exists");
     145            0 :         return false;
     146              :     } else {
     147              :         // declare option
     148              :         Option* option = nullptr;
     149              :         // handle "None" as empty
     150            0 :         if (value == "None") {
     151              :             value.clear();
     152              :         }
     153              :         // create register depending of type
     154            0 :         if ((type == "STR") || (type == "string")) {
     155            0 :             option = new Option_String(value);
     156            0 :         } else if ((type == "TIME") || (type == "time")) {
     157            0 :             option = new Option_String(value, "TIME");
     158            0 :         } else if ((type == "INT") || (type == "int")) {
     159            0 :             option = new Option_Integer(0);
     160            0 :             if (value.empty()) {
     161            0 :                 option->set(INVALID_INT_STR, "", true);
     162              :             } else {
     163            0 :                 option->set(value, value, true);
     164              :             }
     165            0 :         } else if ((type == "FLOAT") || (type == "float")) {
     166            0 :             option = new Option_Float(0);
     167            0 :             if (value.empty()) {
     168            0 :                 option->set(INVALID_DOUBLE_STR, "", true);
     169              :             } else {
     170            0 :                 option->set(value, value, true);
     171              :             }
     172            0 :         } else if ((type == "BOOL") || (type == "bool")) {
     173            0 :             option = new Option_Bool(false);
     174            0 :             if (value.empty()) {
     175            0 :                 option->set("false", "", true);
     176              :             } else {
     177            0 :                 option->set(value, value, true);
     178              :             }
     179            0 :         } else if (type == "INT[]") {
     180            0 :             option = new Option_IntVector();
     181            0 :         } else if (type == "STR[]") {
     182            0 :             option = new Option_StringVector();
     183            0 :         } else if ((type == "FILE") || (type == "file")) {
     184            0 :             option = new Option_FileName();
     185            0 :         } else if ((type == "NETWORK") || (type == "net_file")) {
     186            0 :             option = new Option_Network(value);
     187            0 :         } else if ((type == "ADDITIONAL") || (type == "additional_file")) {
     188            0 :             option = new Option_Additional(value);
     189            0 :         } else if ((type == "ROUTE") || (type == "route_file")) {
     190            0 :             option = new Option_Route(value);
     191            0 :         } else if ((type == "DATA") || (type == "data_file") || (type == "edgedata_file")) {
     192            0 :             option = new Option_Data(value);
     193            0 :         } else if ((type == "SUMOCONFIG") || (type == "sumoconfig_file")) {
     194            0 :             option = new Option_SumoConfig(value);
     195            0 :         } else if ((type == "EDGE") || (type == "edge")) {
     196            0 :             if (listSep.empty()) {
     197            0 :                 option = new Option_Edge(value);
     198              :             } else {
     199            0 :                 option = new Option_EdgeVector(value);
     200              :             }
     201            0 :         } else if (type.size() > 0) {
     202            0 :             WRITE_WARNING(type + " is an invalid type");
     203              :         }
     204              :         // check if option was created
     205              :         if (option) {
     206              :             // set value
     207            0 :             if (!option->isSet()) {
     208            0 :                 option->set(value, "", false);
     209              :             }
     210            0 :             myOptions.doRegister(myOptionName, option);
     211              :             // check if add synonyme
     212            0 :             if (synonymes.size() > 0) {
     213            0 :                 myOptions.addSynonyme(myOptionName, synonymes);
     214              :             }
     215              :             // check if add help
     216            0 :             if (help.size() > 0) {
     217            0 :                 myOptions.addDescription(myOptionName, mySubTopic, help);
     218              :             }
     219            0 :             myOptions.setFurtherAttributes(myOptionName, mySubTopic, required, positional, listSep);
     220            0 :             return true;
     221              :         } else {
     222            0 :             return false;
     223              :         }
     224              :     }
     225              : }
     226              : 
     227              : 
     228              : void
     229            0 : TemplateHandler::endElement(const XMLCh* const /*name*/) {
     230            0 :     myLevel--;
     231            0 :     if (myOptionName.length() == 0) {
     232              :         return;
     233              :     }
     234            0 :     myOptionName = "";
     235              : }
     236              : 
     237              : 
     238              : void
     239            0 : TemplateHandler::warning(const XERCES_CPP_NAMESPACE::SAXParseException& exception) {
     240            0 :     WRITE_WARNING(StringUtils::transcode(exception.getMessage()));
     241            0 :     WRITE_WARNING(" (At line/column " \
     242              :                   + toString(exception.getLineNumber() + 1) + '/' \
     243              :                   + toString(exception.getColumnNumber()) + ").");
     244            0 :     myError = true;
     245            0 : }
     246              : 
     247              : 
     248              : void
     249            0 : TemplateHandler::error(const XERCES_CPP_NAMESPACE::SAXParseException& exception) {
     250            0 :     WRITE_ERROR(StringUtils::transcode(exception.getMessage()));
     251            0 :     WRITE_ERROR(" (At line/column "
     252              :                 + toString(exception.getLineNumber() + 1) + '/'
     253              :                 + toString(exception.getColumnNumber()) + ").");
     254            0 :     myError = true;
     255            0 : }
     256              : 
     257              : 
     258              : void
     259            0 : TemplateHandler::fatalError(const XERCES_CPP_NAMESPACE::SAXParseException& exception) {
     260            0 :     WRITE_ERROR(StringUtils::transcode(exception.getMessage()));
     261            0 :     WRITE_ERROR(" (At line/column "
     262              :                 + toString(exception.getLineNumber() + 1) + '/'
     263              :                 + toString(exception.getColumnNumber()) + ").");
     264            0 :     myError = true;
     265            0 : }
     266              : 
     267              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1