1 #include "otsdaq-core/TableCore/TableInfoReader.h"
3 #include "otsdaq-core/Macros/StringMacros.h"
4 #include "otsdaq-core/XmlUtilities/ConvertFromXML.h"
5 #include "otsdaq-core/XmlUtilities/DOMTreeErrorReporter.h"
9 #include <xercesc/dom/DOMElement.hpp>
10 #include <xercesc/dom/DOMImplementation.hpp>
11 #include <xercesc/dom/DOMImplementationRegistry.hpp>
12 #include <xercesc/dom/DOMNodeList.hpp>
13 #include <xercesc/dom/DOMText.hpp>
14 #include <xercesc/parsers/XercesDOMParser.hpp>
17 #include <xercesc/framework/LocalFileFormatTarget.hpp>
18 #include <xercesc/util/OutOfMemoryException.hpp>
27 #include "otsdaq-core/TableCore/TableBase.h"
32 #define __COUT_HDR__ "TableInfoReader"
36 #define CONFIGURATION_BACKEND_TYPE_ getenv("CONFIGURATION_TYPE")
39 TableInfoReader::TableInfoReader(
bool allowIllegalColumns)
40 : allowIllegalColumns_(allowIllegalColumns)
43 rootTag_ = xercesc::XMLString::transcode(
"ROOT");
44 tableTag_ = xercesc::XMLString::transcode(
"TABLE");
45 tableNameAttributeTag_ = xercesc::XMLString::transcode(
"Name");
46 viewTag_ = xercesc::XMLString::transcode(
"VIEW");
47 viewNameAttributeTag_ = xercesc::XMLString::transcode(
"Name");
48 viewTypeAttributeTag_ = xercesc::XMLString::transcode(
"Type");
49 viewDescriptionAttributeTag_ = xercesc::XMLString::transcode(
"Description");
50 columnTag_ = xercesc::XMLString::transcode(
"COLUMN");
51 columnTypeAttributeTag_ = xercesc::XMLString::transcode(
"Type");
52 columnNameAttributeTag_ = xercesc::XMLString::transcode(
"Name");
53 columnStorageNameAttributeTag_ = xercesc::XMLString::transcode(
"StorageName");
54 columnDataTypeAttributeTag_ = xercesc::XMLString::transcode(
"DataType");
55 columnDataChoicesAttributeTag_ = xercesc::XMLString::transcode(
"DataChoices");
59 TableInfoReader::~TableInfoReader(
void)
63 xercesc::XMLString::release(&rootTag_);
64 xercesc::XMLString::release(&tableTag_);
65 xercesc::XMLString::release(&tableNameAttributeTag_);
66 xercesc::XMLString::release(&viewTag_);
67 xercesc::XMLString::release(&viewNameAttributeTag_);
68 xercesc::XMLString::release(&viewTypeAttributeTag_);
69 xercesc::XMLString::release(&viewDescriptionAttributeTag_);
70 xercesc::XMLString::release(&columnTag_);
71 xercesc::XMLString::release(&columnTypeAttributeTag_);
72 xercesc::XMLString::release(&columnNameAttributeTag_);
73 xercesc::XMLString::release(&columnStorageNameAttributeTag_);
74 xercesc::XMLString::release(&columnDataTypeAttributeTag_);
75 xercesc::XMLString::release(&columnDataChoicesAttributeTag_);
79 __COUT_ERR__ <<
"Unknown exception encountered in TagNames destructor" << __E__;
85 void TableInfoReader::initPlatform(
void)
89 xercesc::XMLPlatformUtils::Initialize();
91 catch(xercesc::XMLException& e)
93 __COUT_ERR__ <<
"XML toolkit initialization error: "
94 << XML_TO_CHAR(e.getMessage()) << __E__;
100 void TableInfoReader::terminatePlatform(
void)
104 xercesc::XMLPlatformUtils::Terminate();
106 catch(xercesc::XMLException& e)
108 __COUT_ERR__ <<
"XML tolkit teardown error: " << XML_TO_CHAR(e.getMessage())
114 void TableInfoReader::setAllowColumnErrors(
bool setValue)
116 allowIllegalColumns_ = setValue;
119 const bool& TableInfoReader::getAllowColumnErrors(
void) {
return allowIllegalColumns_; }
122 bool TableInfoReader::checkViewType(std::string type)
124 std::vector<std::string> types;
125 int currentIndex = 0;
126 while(type.find(
',', currentIndex) != std::string::npos)
129 type.substr(currentIndex, type.find(
',', currentIndex) - currentIndex));
130 currentIndex = type.find(
',', currentIndex) + 1;
132 types.push_back(type.substr(currentIndex, type.size()));
134 const std::string systemType = CONFIGURATION_BACKEND_TYPE_;
136 for(
unsigned int i = 0; i < types.size(); i++)
138 if(types[i] == systemType)
143 const unsigned int allowedNamesSize = 3;
144 const std::string allowedNames[allowedNamesSize] = {
145 "File",
"Database",
"DatabaseTest"};
146 if(systemType != allowedNames[0] && systemType != allowedNames[1] &&
147 systemType != allowedNames[2])
149 __COUT__ <<
"The type defined in CONFIGURATION_BACKEND_TYPE (" << systemType
150 <<
") doesn't match with any of the allowed types: File,Database or "
154 throw(std::runtime_error(
"Illegal table type"));
156 for(
unsigned int i = 0; i < types.size(); i++)
158 if(types[i] != allowedNames[0] && types[i] != allowedNames[1] &&
159 types[i] != allowedNames[2])
161 __COUT__ <<
"The type defined in the info file (" << types[i]
162 <<
") doesn't match with any of the allowed types: "
163 << allowedNames[0] <<
", " << allowedNames[1] <<
" or "
164 << allowedNames[2] << __E__;
165 throw(std::runtime_error(
"Illegal Type!"));
173 xercesc::DOMNode* TableInfoReader::getNode(XMLCh* tagName,
174 xercesc::DOMNode* parent,
175 unsigned int itemNumber)
177 return getNode(tagName, dynamic_cast<xercesc::DOMElement*>(parent), itemNumber);
181 xercesc::DOMNode* TableInfoReader::getNode(XMLCh* tagName,
182 xercesc::DOMElement* parent,
183 unsigned int itemNumber)
185 xercesc::DOMNodeList* nodeList = parent->getElementsByTagName(tagName);
188 throw(std::runtime_error(std::string(
"Can't find ") + XML_TO_CHAR(tagName) +
190 __COUT__ << (std::string(
"Can't find ") + XML_TO_CHAR(tagName) +
" tag!")
198 return nodeList->item(itemNumber);
202 xercesc::DOMElement* TableInfoReader::getElement(XMLCh* tagName,
203 xercesc::DOMNode* parent,
204 unsigned int itemNumber)
206 return dynamic_cast<xercesc::DOMElement*
>(getNode(tagName, parent, itemNumber));
210 xercesc::DOMElement* TableInfoReader::getElement(XMLCh* tagName,
211 xercesc::DOMElement* parent,
212 unsigned int itemNumber)
214 return dynamic_cast<xercesc::DOMElement*
>(getNode(tagName, parent, itemNumber));
218 std::string TableInfoReader::read(
TableBase& table)
220 std::string accumulatedExceptions =
"";
231 if(getenv(
"CONFIGURATION_TYPE") == NULL)
232 __COUT__ <<
"Missing env variable: CONFIGURATION_TYPE. It must be set!" << __E__;
235 if(getenv(
"TABLE_INFO_PATH") == NULL)
236 __COUT__ <<
"Missing env variable: TABLE_INFO_PATH. It must be set!" << __E__;
245 std::string tableDataDir = std::string(getenv(
"TABLE_INFO_PATH")) +
"/";
246 std::string tableFile = tableDataDir + table.getTableName() +
"Info.xml";
248 struct stat fileStatus;
250 int iretStat = stat(tableFile.c_str(), &fileStatus);
251 if(iretStat == ENOENT)
253 __SS__ << (
"Path file_name does not exist, or path is an empty std::string.")
255 __COUT_ERR__ << ss.str();
258 else if(iretStat == ENOTDIR)
260 __SS__ << (
"A component of the path is not a directory.") << __E__;
261 __COUT_ERR__ << ss.str();
264 else if(iretStat == ELOOP)
266 __SS__ << (
"Too many symbolic links encountered while traversing the path.")
268 __COUT_ERR__ << ss.str();
271 else if(iretStat == EACCES)
273 __SS__ << (
"Permission denied.") << __E__;
274 __COUT_ERR__ << ss.str();
277 else if(iretStat == ENAMETOOLONG)
279 __SS__ << (
"File can not be read. Name too long.") << __E__;
280 __COUT_ERR__ << ss.str();
284 xercesc::XercesDOMParser* parser =
new xercesc::XercesDOMParser;
286 parser->setValidationScheme(xercesc::XercesDOMParser::Val_Auto);
287 parser->setDoNamespaces(
true);
288 parser->setDoSchema(
true);
289 parser->useCachedGrammarInParse(
false);
292 parser->setErrorHandler(errorHandler);
295 parser->parse(tableFile.c_str());
298 xercesc::DOMDocument* xmlDocument = parser->getDocument();
301 xercesc::DOMElement* elementRoot = xmlDocument->getDocumentElement();
306 throw(std::runtime_error(
"empty XML document"));
310 xercesc::DOMElement* tableElement = getElement(tableTag_, elementRoot, 0);
311 if(table.getTableName() !=
312 XML_TO_CHAR(tableElement->getAttribute(tableNameAttributeTag_)))
314 __SS__ <<
"In " << tableFile <<
" the table name "
315 << XML_TO_CHAR(tableElement->getAttribute(tableNameAttributeTag_))
316 <<
" doesn't match the the class table name " << table.getTableName()
321 __COUT_ERR__ <<
"\n" << ss.str();
322 throw(std::runtime_error(ss.str()));
325 xercesc::DOMNodeList* viewNodeList = tableElement->getElementsByTagName(viewTag_);
326 bool storageTypeFound =
false;
328 if(viewNodeList->getLength() != 1)
330 __SS__ <<
"In " << tableFile <<
" the table name "
331 << XML_TO_CHAR(tableElement->getAttribute(tableNameAttributeTag_))
332 <<
" there must only be one view. There were "
333 << viewNodeList->getLength() <<
" found." << __E__;
337 __COUT_ERR__ <<
"\n" << ss.str();
338 throw(std::runtime_error(ss.str()));
341 for(XMLSize_t view = 0; view < viewNodeList->getLength(); view++)
343 if(!viewNodeList->item(view)->getNodeType() ||
344 viewNodeList->item(view)->getNodeType() !=
345 xercesc::DOMNode::ELEMENT_NODE)
347 xercesc::DOMElement* viewElement =
348 dynamic_cast<xercesc::DOMElement*
>(viewNodeList->item(view));
349 std::string viewType =
350 XML_TO_CHAR(viewElement->getAttribute(viewTypeAttributeTag_));
351 if(!checkViewType(viewType))
353 storageTypeFound =
true;
354 table.getMockupViewP()->setTableName(
355 XML_TO_CHAR(viewElement->getAttribute(viewNameAttributeTag_)));
356 xercesc::DOMNodeList* columnNodeList =
357 viewElement->getElementsByTagName(columnTag_);
358 for(XMLSize_t column = 0; column < columnNodeList->getLength(); column++)
361 xercesc::DOMElement* columnElement =
362 dynamic_cast<xercesc::DOMElement*
>(columnNodeList->item(column));
368 std::string capturedException;
370 XML_TO_CHAR(columnElement->getAttribute(columnTypeAttributeTag_)),
371 XML_TO_CHAR(columnElement->getAttribute(columnNameAttributeTag_)),
373 columnElement->getAttribute(columnStorageNameAttributeTag_)),
374 XML_TO_CHAR(columnElement->getAttribute(columnDataTypeAttributeTag_)),
376 columnElement->getAttribute(columnDataChoicesAttributeTag_)),
383 if(capturedException !=
"")
384 accumulatedExceptions +=
385 std::string(
"\n\nColumn Error:") + capturedException;
392 std::string tableDescription =
393 XML_TO_CHAR(viewElement->getAttribute(viewDescriptionAttributeTag_));
395 table.setTableDescription(StringMacros::decodeURIComponent(tableDescription));
400 if(!storageTypeFound)
402 __COUT__ <<
"The type defined in CONFIGURATION_BACKEND_TYPE ("
403 << CONFIGURATION_BACKEND_TYPE_
404 <<
") doesn't match with any of the types defined in " << tableFile
409 throw(std::runtime_error(
"Table Type mismatch!"));
414 catch(xercesc::XMLException& e)
416 std::ostringstream errBuf;
417 errBuf <<
"Error parsing file: " << XML_TO_CHAR(e.getMessage()) << std::flush;
427 return accumulatedExceptions;
433 std::string TableInfoReader::read(
TableBase* table) {
return read(*table); }