/* * XMLRequestParser.cc * * Created on: Nov 23, 2012 * Author: f.casimir */ //Common module include #include "DicError.hh" // DD_Client_r_lib module includes #include "TimeUtil.hh" //Parameters module include #include "ServicesServer.hh" //XMLConfigurator module include #include "NodeCfg.hh" #include "Constant.hh" //XMLRequest module include #include "Config.hh" #include "XMLRequestParser.hh" #include "TimeInterval.hh" #include "TimeTableCatalogFactory.hh" #include "TimeTable.hh" #include "Catalog.hh" #include #include // Using namespace using namespace log4cxx; using namespace AMDA::Parameters; using namespace AMDA::XMLConfigurator; using namespace TimeTableCatalog; namespace AMDA { namespace XMLRequest { class ParamNode : public NodeCfg { public: void proceed(xmlNodePtr pNode,const AMDA::Parameters::CfgContext& pContext) { ParameterManager* lParameterManager = pContext.get(); try { xmlChar* lParamName = xmlGetProp(pNode, (const xmlChar *) "id"); std::string paramNameStr; if (lParamName) { paramNameStr = std::string((char*)lParamName); xmlFree(lParamName); } else { ERROR_EXCEPTION( ERROR_MANDATORY_ATTRIBUTE_MISSING << pNode->name << "@" << PARAMNAME) } lParameterManager->createParameter(paramNameStr.c_str()); } catch (...) { //This parameter is ignored, continue // throw; } } }; class IntervalNode : public NodeGrpCfg { public: class StartTimeNode : public NodeCfg { public: void proceed(xmlNodePtr pNode,const AMDA::Parameters::CfgContext& pContext) { IntervalNode* lIntervalNode = pContext.get(); double lStartTime = DD_Time2Double((const char*)pNode->children->content); lIntervalNode->_startTime = lStartTime; } }; class TimeIntervalNode : public NodeCfg { public: void proceed(xmlNodePtr pNode, const AMDA::Parameters::CfgContext& pContext) { IntervalNode* lIntervalNode = pContext.get(); double lTimeInt = DD_Time2Double((const char*)pNode->children->content); lIntervalNode->_timeInt = lTimeInt; } }; IntervalNode () : NodeGrpCfg(), _startTime(0), _timeInt(0) { getChildList()["startTime"] = NodeCfgSPtr(new StartTimeNode); getChildList()["timeInterval"] = NodeCfgSPtr(new TimeIntervalNode); } void proceed(xmlNodePtr pNode, const AMDA::Parameters::CfgContext& pContext) { LOG4CXX_DEBUG(gLogger, "IntervalNode::proceed"); // Create new context CfgContext lContext; lContext.push(this); // Go to next node NodeGrpCfg::proceed(pNode, lContext); // Get manager of the new output parameter for this node ParameterManager* lParameterManager = pContext.get(); std::string emptyStr; lParameterManager->addInputInterval(_startTime, _startTime + _timeInt, 0, emptyStr, emptyStr, 0); } double _startTime; double _timeInt; }; class TimeTableNode : public NodeCfg { public: void proceed(xmlNodePtr pNode, const AMDA::Parameters::CfgContext& pContext) { //TT Id => TT path xmlChar* lTTId = NULL; ParameterManager* lParameterManager = pContext.get(); if (!(lTTId = xmlGetProp(pNode, (const xmlChar *) "id"))) { ERROR_EXCEPTION( AMDA::XMLConfigurator::ERROR_MANDATORY_ATTRIBUTE_MISSING << pNode->name << "@" << AMDA::XMLConfigurator::TIMETABLENAME) } std::string lStrTTPath((const char*)lTTId); if(lTTId){ xmlFree(lTTId); } //Time Table name std::string lStrTTName; xmlChar* lTTName = NULL; if (!(lTTName = xmlGetProp(pNode, (const xmlChar *) "name"))) { boost::filesystem::path ttPath(lStrTTPath); lStrTTName = ttPath.filename().string(); // name of the tt without parent path and extension lStrTTName = lStrTTName.substr(0, lStrTTName.size() - ttPath.extension().string().size()); } else { lStrTTName = (const char*)lTTName; xmlFree(lTTName); } // check local file exists // if distant file does not exist an error will be thrown in the next if if((lStrTTPath.find("http://")!=std::string::npos && lStrTTPath.find("https://")!=std::string::npos) && !boost::filesystem::exists(lStrTTPath)){ ERROR_EXCEPTION( AMDA::XMLConfigurator::ERROR_FILE_NOT_EXIST << lStrTTPath); } // Read file std::string lReaderType = TimeTableCatalogFactory::getInstance().getReaderType(lStrTTPath); if(lReaderType.empty()){ ERROR_EXCEPTION( "Unknown Timetable : " << lStrTTPath); } TimeTableCatalog::TimeTable inputTT; inputTT.read(lStrTTPath, lReaderType); const std::vector lTimeIntervalList = inputTT.getIntervals(); // Get interval index if exists xmlChar* lTTIndex = xmlGetProp(pNode, (const xmlChar *) "index"); if (lTTIndex) { //Add only interval designate by index int tmpIndex = atoi( (const char*)lTTIndex ); size_t index; if(tmpIndex == -1) index = lTimeIntervalList.size() -1; else index = (size_t)tmpIndex; xmlFree(lTTIndex); if (index >= lTimeIntervalList.size()) { ERROR_EXCEPTION( "Cannot find index : " << index << " in TimeTable : " << lStrTTPath); } lParameterManager->addInputInterval( lTimeIntervalList[index]._startTime, lTimeIntervalList[index]._stopTime, lTimeIntervalList[index]._index, lStrTTPath, lStrTTName, inputTT.getIntervalNumber()); } else { //Add all intervals for(std::vector::const_iterator it = lTimeIntervalList.begin(); it != lTimeIntervalList.end(); ++it) { lParameterManager->addInputInterval(it->_startTime, it->_stopTime, it->_index, lStrTTPath, lStrTTName, inputTT.getIntervalNumber()); } } } }; class CatalogNode : public NodeCfg { public: void proceed(xmlNodePtr pNode, const AMDA::Parameters::CfgContext& pContext) { //Catalog Id => catalog path xmlChar* lCatalogId = NULL; ParameterManager* lParameterManager = pContext.get(); if (!(lCatalogId = xmlGetProp(pNode, (const xmlChar *) "id"))) { ERROR_EXCEPTION( AMDA::XMLConfigurator::ERROR_MANDATORY_ATTRIBUTE_MISSING << pNode->name << "@" << AMDA::XMLConfigurator::TIMETABLENAME) } std::string lStrCatalogPath((const char*)lCatalogId); if(lCatalogId){ xmlFree(lCatalogId); } //Catalog name std::string lStrCatalogName; xmlChar* lCatalogName = NULL; if (!(lCatalogName = xmlGetProp(pNode, (const xmlChar *) "name"))) { boost::filesystem::path ttPath(lStrCatalogPath); lStrCatalogName = ttPath.filename().string(); // name of the tt without parent path and extension lStrCatalogName = lStrCatalogName.substr(0, lStrCatalogName.size() - ttPath.extension().string().size()); } else { lStrCatalogName = (const char*)lCatalogName; xmlFree(lCatalogName); } // check local file exists // if distant file does not exist an error will be thrown in the next if if((lStrCatalogPath.find("http://")!=std::string::npos && lStrCatalogPath.find("https://")!=std::string::npos) && !boost::filesystem::exists(lStrCatalogPath)){ ERROR_EXCEPTION( AMDA::XMLConfigurator::ERROR_FILE_NOT_EXIST << lStrCatalogPath); } // Read file std::string lReaderType = TimeTableCatalogFactory::getInstance().getReaderType(lStrCatalogPath); if(lReaderType.empty()){ ERROR_EXCEPTION( "Unknown Catalog : " << lStrCatalogPath); } TimeTableCatalog::Catalog inputCatalog; inputCatalog.read(lStrCatalogPath, lReaderType); std::vector lTimeIntervalList = inputCatalog.getIntervals(); // Get interval index if exists xmlChar* lCatalogIndex = xmlGetProp(pNode, (const xmlChar *) "index"); if (lCatalogIndex) { //Add only interval designate by index int tmpIndex = atoi( (const char*)lCatalogIndex ); size_t index; if(tmpIndex == -1) index = lTimeIntervalList.size() -1; else index = (size_t)tmpIndex; xmlFree(lCatalogIndex); if (index >= lTimeIntervalList.size()) { ERROR_EXCEPTION( "Cannot find index : " << index << " in Catalog : " << lStrCatalogPath); } lParameterManager->addInputInterval( lTimeIntervalList[index]._startTime, lTimeIntervalList[index]._stopTime, lTimeIntervalList[index]._index, lStrCatalogPath, lStrCatalogName, inputCatalog.getIntervalNumber()); for (auto &desc : inputCatalog.getParameterDescriptions()) { lParameterManager->addInputIntervalDataList(index, desc.getId(), lTimeIntervalList[index].getParameterData(desc.getId())); } } else { //Add all intervals for(std::vector::const_iterator it = lTimeIntervalList.begin(); it != lTimeIntervalList.end(); ++it) { lParameterManager->addInputInterval(it->_startTime, it->_stopTime, it->_index, lStrCatalogPath, lStrCatalogName, inputCatalog.getIntervalNumber()); for (auto &desc : inputCatalog.getParameterDescriptions()) lParameterManager->addInputIntervalDataList(it->_index, desc.getId(), lTimeIntervalList[it->_index].getParameterData(desc.getId())); } } } }; class ParamTimeRestrictionNode : public NodeCfg { public: void proceed(xmlNodePtr pNode,const AMDA::Parameters::CfgContext& pContext) { ParameterManager* lParameterManager = pContext.get(); xmlChar* lParamName = xmlGetProp(pNode, (const xmlChar *) "id"); std::string paramNameStr; if (lParamName) { paramNameStr = std::string((char*)lParamName); xmlFree(lParamName); } else { ERROR_EXCEPTION( ERROR_MANDATORY_ATTRIBUTE_MISSING << pNode->name << "@id") } xmlChar* lRestrictionTime = xmlGetProp(pNode, (const xmlChar *) "restriction"); double restrictionTime = NAN; if (lRestrictionTime) { std::string restrictionTimeStr = std::string((char*)lRestrictionTime); xmlFree(lRestrictionTime); try { restrictionTime = boost::lexical_cast(restrictionTimeStr); } catch (boost::bad_lexical_cast &) { } } else { ERROR_EXCEPTION( ERROR_MANDATORY_ATTRIBUTE_MISSING << pNode->name << "@restriction") } lParameterManager->addParamTimeRestriction(paramNameStr, restrictionTime); } }; XMLRequestParser::XMLRequestParser(const char* pXSDFile) : XMLConfigurator(pXSDFile,false) { /* 2008000000000000 0000000100000000 ISO ISO */ // Request root node NodeGrpCfg* lRequestNode = new NodeGrpCfg(); getXmlConfiguratorMap()["request"] = RootNodeCfgSPtr(lRequestNode); { // Params group node NodeGrpCfg* lParamsNode = new NodeGrpCfg(); lRequestNode->getChildList()["params"] = NodeCfgSPtr(lParamsNode); lParamsNode->getChildList()["param"] = NodeCfgSPtr(new ParamNode); } { // Times group node NodeGrpCfg* lTimeNode = new NodeGrpCfg(); lRequestNode->getChildList()["times"] = NodeCfgSPtr(lTimeNode); { // Interval group node NodeGrpCfg* lIntervalNode = new IntervalNode(); lTimeNode->getChildList()["interval"] = NodeCfgSPtr(lIntervalNode); } { // Timetable group node lTimeNode->getChildList()["timetable"] = NodeCfgSPtr( new TimeTableNode); } { // Catalog group node lTimeNode->getChildList()["catalog"] = NodeCfgSPtr( new CatalogNode); } } { // Params time restrictions node NodeGrpCfg* lParamsTimeRestrictionsNode = new NodeGrpCfg(); lRequestNode->getChildList()["paramsTimeRestrictions"] = NodeCfgSPtr(lParamsTimeRestrictionsNode); lParamsTimeRestrictionsNode->getChildList()["param"] = NodeCfgSPtr(new ParamTimeRestrictionNode); } { // Output group node NodeGrpCfg* lOutputNode = new NodeGrpCfg(); lRequestNode->getChildList()["outputs"] = NodeCfgSPtr(lOutputNode); } } XMLRequestParser::~XMLRequestParser() { } void XMLRequestParser::operator()( AMDA::Parameters::ParameterManager& lParameterManager, const std::string& requestFile) { CfgContext ctx; ctx.push(&lParameterManager); ctx.push(ServicesServer::getInstance()); try { XMLConfigurator::proceed(requestFile.c_str(), ctx, false); } catch (AMDA::AMDA_exception & e) { e << AMDA::errno_code(AMDA_INFORMATION_REQUEST_ERR); throw; } } } /* namespace XMLRequest */ } /* namespace AMDA */