YARP
Yet Another Robot Platform
xmltemploader.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006-2021 Istituto Italiano di Tecnologia (IIT)
3  * All rights reserved.
4  *
5  * This software may be modified and distributed under the terms of the
6  * BSD-3-Clause license. See the accompanying LICENSE file for details.
7  */
8 
10 #include <yarp/conf/filesystem.h>
11 #include <yarp/manager/utility.h>
12 #include <dirent.h>
13 
14 #include <algorithm>
15 #include <cctype>
16 #include <string>
17 #include <fstream>
18 
19 #include <tinyxml.h>
20 
21 
22 using namespace std;
23 using namespace yarp::manager;
24 
25 
31 XmlTempLoader::XmlTempLoader(const char* szPath, const char* szAppName)
32 {
33  if(szAppName)
34  strAppName = szAppName;
35 
36  if(strlen(szPath))
37  {
38  const std::string directorySeparator{yarp::conf::filesystem::preferred_separator};
39  strPath = szPath;
40  if((strPath.rfind(directorySeparator)==string::npos) ||
41  (strPath.rfind(directorySeparator)!=strPath.size()-1))
42  strPath = strPath + string(directorySeparator);
43  }
44 }
45 
49 XmlTempLoader::XmlTempLoader(const char* szFileName)
50 {
51  if(szFileName)
52  strFileName = szFileName;
53 }
54 
55 
56 XmlTempLoader::~XmlTempLoader() = default;
57 
58 
59 bool XmlTempLoader::init()
60 {
61  fileNames.clear();
62  ErrorLogger* logger = ErrorLogger::Instance();
63 
67  if(!strFileName.empty())
68  {
69  fileNames.push_back(strFileName);
70  return true;
71  }
72 
73  if(strPath.empty())
74  {
75  logger->addError("No application template path is introduced.");
76  return false;
77  }
78 
79  DIR *dir;
80  struct dirent *entry;
81  if ((dir = opendir(strPath.c_str())) == nullptr)
82  {
83  OSTRINGSTREAM err;
84  err<<"Cannot access "<<strPath;
85  logger->addError(err);
86  return false;
87  }
88 
89  /* we need to load all xml app templates */
90  while((entry = readdir(dir)))
91  {
92  string name = entry->d_name;
93  if(name.size() > 12)
94  {
95  string ext = name.substr(name.size()-12,12);
96  if(compareString(ext.c_str(), "xml.template"))
97  fileNames.push_back(strPath+name);
98  }
99  }
100  closedir(dir);
101  return true;
102 }
103 
104 void XmlTempLoader::reset()
105 {
106  fini();
107  init();
108 }
109 
110 
111 void XmlTempLoader::fini()
112 {
113  fileNames.clear();
114 }
115 
116 
117 AppTemplate* XmlTempLoader::getNextAppTemplate()
118 {
119  if(strAppName.empty())
120  {
121  AppTemplate* app = nullptr;
122  while(!app)
123  {
124  if(fileNames.empty())
125  return nullptr;
126  string fname = fileNames.back();
127  fileNames.pop_back();
128  app = parsXml(fname.c_str());
129  }
130  return app;
131  }
132  else
133  {
134  vector<string>::iterator itr;
135  for(itr=fileNames.begin(); itr<fileNames.end(); itr++)
136  {
137  AppTemplate* app = parsXml((*itr).c_str());
138  if(app && (app->name==strAppName))
139  return app;
140  }
141  }
142  return nullptr;
143 }
144 
145 
146 
147 AppTemplate* XmlTempLoader::parsXml(const char* szFile)
148 {
149  app.name.clear();
150  app.tmpFileName.clear();
151 
152  ErrorLogger* logger = ErrorLogger::Instance();
153 
154  TiXmlDocument doc(szFile);
155  if(!doc.LoadFile())
156  {
157  OSTRINGSTREAM err;
158  err<<"Syntax error while loading "<<szFile<<" at line "\
159  <<doc.ErrorRow()<<": ";
160  err<<doc.ErrorDesc();
161  logger->addError(err);
162  return nullptr;
163  }
164 
165  /* retrieving root element */
166  TiXmlElement *root = doc.RootElement();
167  if(!root)
168  {
169  OSTRINGSTREAM err;
170  err<<"Syntax error while loading "<<szFile<<" . ";
171  err<<"No root element.";
172  logger->addError(err);
173  return nullptr;
174  }
175 
176  if(!compareString(root->Value(), "application"))
177  {
178  return nullptr;
179  }
180 
181  app.tmpFileName = szFile;
182 
183  /* retrieving name */
184  auto* name = (TiXmlElement*) root->FirstChild("name");
185  if(!name || !name->GetText())
186  {
187  OSTRINGSTREAM err;
188  err<<"Application from "<<szFile<<" has no name.";
189  logger->addError(err);
190  //return NULL;
191  }
192  else
193  {
194  string strname = name->GetText();
195  for(char& i : strname)
196  if(i == ' ')
197  i = '_';
198  app.name = strname;
199  }
200 
201  return &app;
202 }
Singleton class ErrorLogger.
Definition: utility.h:60
void addError(const char *szError)
Definition: utility.cpp:121
static constexpr value_type preferred_separator
Definition: filesystem.h:26
bool compareString(const char *szFirst, const char *szSecond)
Definition: utility.cpp:305
std::stringstream OSTRINGSTREAM
Definition: utility.h:52
Abstract Class TempLoader.