1 #include "otsdaq/TableCore/TableInfoReader.h"
3 #include "otsdaq/Macros/StringMacros.h"
4 #include "otsdaq/XmlUtilities/ConvertFromXML.h"
5 #include "otsdaq/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/TableCore/TableBase.h"
32 #define __COUT_HDR__ "TableInfoReader"
36 #define CONFIGURATION_BACKEND_TYPE_ __ENV__("CONFIGURATION_TYPE")
39 TableInfoReader::TableInfoReader(
bool allowIllegalColumns) : allowIllegalColumns_(allowIllegalColumns)
42 rootTag_ = xercesc::XMLString::transcode(
"ROOT");
43 tableTag_ = xercesc::XMLString::transcode(
"TABLE");
44 tableNameAttributeTag_ = xercesc::XMLString::transcode(
"Name");
45 viewTag_ = xercesc::XMLString::transcode(
"VIEW");
46 viewNameAttributeTag_ = xercesc::XMLString::transcode(
"Name");
47 viewTypeAttributeTag_ = xercesc::XMLString::transcode(
"Type");
48 viewDescriptionAttributeTag_ = xercesc::XMLString::transcode(
"Description");
49 columnTag_ = xercesc::XMLString::transcode(
"COLUMN");
50 columnTypeAttributeTag_ = xercesc::XMLString::transcode(
"Type");
51 columnNameAttributeTag_ = xercesc::XMLString::transcode(
"Name");
52 columnStorageNameAttributeTag_ = xercesc::XMLString::transcode(
"StorageName");
53 columnDataTypeAttributeTag_ = xercesc::XMLString::transcode(
"DataType");
54 columnDataChoicesAttributeTag_ = xercesc::XMLString::transcode(
"DataChoices");
58 TableInfoReader::~TableInfoReader(
void)
62 xercesc::XMLString::release(&rootTag_);
63 xercesc::XMLString::release(&tableTag_);
64 xercesc::XMLString::release(&tableNameAttributeTag_);
65 xercesc::XMLString::release(&viewTag_);
66 xercesc::XMLString::release(&viewNameAttributeTag_);
67 xercesc::XMLString::release(&viewTypeAttributeTag_);
68 xercesc::XMLString::release(&viewDescriptionAttributeTag_);
69 xercesc::XMLString::release(&columnTag_);
70 xercesc::XMLString::release(&columnTypeAttributeTag_);
71 xercesc::XMLString::release(&columnNameAttributeTag_);
72 xercesc::XMLString::release(&columnStorageNameAttributeTag_);
73 xercesc::XMLString::release(&columnDataTypeAttributeTag_);
74 xercesc::XMLString::release(&columnDataChoicesAttributeTag_);
78 __COUT_ERR__ <<
"Unknown exception encountered in TagNames destructor" << __E__;
84 void TableInfoReader::initPlatform(
void)
88 xercesc::XMLPlatformUtils::Initialize();
90 catch(xercesc::XMLException& e)
92 __COUT_ERR__ <<
"XML toolkit initialization error: " << XML_TO_CHAR(e.getMessage()) << __E__;
98 void TableInfoReader::terminatePlatform(
void)
102 xercesc::XMLPlatformUtils::Terminate();
104 catch(xercesc::XMLException& e)
106 __COUT_ERR__ <<
"XML tolkit teardown error: " << XML_TO_CHAR(e.getMessage()) << __E__;
111 void TableInfoReader::setAllowColumnErrors(
bool setValue) { allowIllegalColumns_ = setValue; }
113 const bool& TableInfoReader::getAllowColumnErrors(
void) {
return allowIllegalColumns_; }
116 bool TableInfoReader::checkViewType(std::string type)
118 std::vector<std::string> types;
119 int currentIndex = 0;
120 while(type.find(
',', currentIndex) != std::string::npos)
122 types.push_back(type.substr(currentIndex, type.find(
',', currentIndex) - currentIndex));
123 currentIndex = type.find(
',', currentIndex) + 1;
125 types.push_back(type.substr(currentIndex, type.size()));
127 const std::string systemType = CONFIGURATION_BACKEND_TYPE_;
129 for(
unsigned int i = 0; i < types.size(); i++)
131 if(types[i] == systemType)
136 const unsigned int allowedNamesSize = 3;
137 const std::string allowedNames[allowedNamesSize] = {
"File",
"Database",
"DatabaseTest"};
138 if(systemType != allowedNames[0] && systemType != allowedNames[1] && systemType != allowedNames[2])
140 __COUT__ <<
"The type defined in CONFIGURATION_BACKEND_TYPE (" << systemType
141 <<
") doesn't match with any of the allowed types: File,Database or "
145 throw(std::runtime_error(
"Illegal table type"));
147 for(
unsigned int i = 0; i < types.size(); i++)
149 if(types[i] != allowedNames[0] && types[i] != allowedNames[1] && types[i] != allowedNames[2])
151 __COUT__ <<
"The type defined in the info file (" << types[i] <<
") doesn't match with any of the allowed types: " << allowedNames[0] <<
", "
152 << allowedNames[1] <<
" or " << allowedNames[2] << __E__;
153 throw(std::runtime_error(
"Illegal Type!"));
161 xercesc::DOMNode* TableInfoReader::getNode(XMLCh* tagName, xercesc::DOMNode* parent,
unsigned int itemNumber)
163 return getNode(tagName, dynamic_cast<xercesc::DOMElement*>(parent), itemNumber);
167 xercesc::DOMNode* TableInfoReader::getNode(XMLCh* tagName, xercesc::DOMElement* parent,
unsigned int itemNumber)
169 xercesc::DOMNodeList* nodeList = parent->getElementsByTagName(tagName);
172 throw(std::runtime_error(std::string(
"Can't find ") + XML_TO_CHAR(tagName) +
" tag!"));
173 __COUT__ << (std::string(
"Can't find ") + XML_TO_CHAR(tagName) +
" tag!") << __E__;
180 return nodeList->item(itemNumber);
184 xercesc::DOMElement* TableInfoReader::getElement(XMLCh* tagName, xercesc::DOMNode* parent,
unsigned int itemNumber)
186 return dynamic_cast<xercesc::DOMElement*
>(getNode(tagName, parent, itemNumber));
190 xercesc::DOMElement* TableInfoReader::getElement(XMLCh* tagName, xercesc::DOMElement* parent,
unsigned int itemNumber)
192 return dynamic_cast<xercesc::DOMElement*
>(getNode(tagName, parent, itemNumber));
196 std::string TableInfoReader::read(
TableBase& table)
198 std::string accumulatedExceptions =
"";
209 if(__ENV__(
"CONFIGURATION_TYPE") == NULL)
210 __COUT__ <<
"Missing env variable: CONFIGURATION_TYPE. It must be set!" << __E__;
213 if(__ENV__(
"TABLE_INFO_PATH") == NULL)
214 __COUT__ <<
"Missing env variable: TABLE_INFO_PATH. It must be set!" << __E__;
223 std::string tableDataDir = std::string(__ENV__(
"TABLE_INFO_PATH")) +
"/";
224 std::string tableFile = tableDataDir + table.getTableName() +
"Info.xml";
226 struct stat fileStatus;
228 int iretStat = stat(tableFile.c_str(), &fileStatus);
229 if(iretStat == ENOENT)
231 __SS__ << (
"Path file_name does not exist, or path is an empty std::string.") << __E__;
232 __COUT_ERR__ << ss.str();
235 else if(iretStat == ENOTDIR)
237 __SS__ << (
"A component of the path is not a directory.") << __E__;
238 __COUT_ERR__ << ss.str();
241 else if(iretStat == ELOOP)
243 __SS__ << (
"Too many symbolic links encountered while traversing the path.") << __E__;
244 __COUT_ERR__ << ss.str();
247 else if(iretStat == EACCES)
249 __SS__ << (
"Permission denied.") << __E__;
250 __COUT_ERR__ << ss.str();
253 else if(iretStat == ENAMETOOLONG)
255 __SS__ << (
"File can not be read. Name too long.") << __E__;
256 __COUT_ERR__ << ss.str();
260 xercesc::XercesDOMParser* parser =
new xercesc::XercesDOMParser;
262 parser->setValidationScheme(xercesc::XercesDOMParser::Val_Auto);
263 parser->setDoNamespaces(
true);
264 parser->setDoSchema(
true);
265 parser->useCachedGrammarInParse(
false);
268 parser->setErrorHandler(errorHandler);
271 parser->parse(tableFile.c_str());
274 xercesc::DOMDocument* xmlDocument = parser->getDocument();
277 xercesc::DOMElement* elementRoot = xmlDocument->getDocumentElement();
282 throw(std::runtime_error(
"empty XML document"));
286 xercesc::DOMElement* tableElement = getElement(tableTag_, elementRoot, 0);
287 if(table.getTableName() != XML_TO_CHAR(tableElement->getAttribute(tableNameAttributeTag_)))
289 __SS__ <<
"In " << tableFile <<
" the table name " << XML_TO_CHAR(tableElement->getAttribute(tableNameAttributeTag_))
290 <<
" doesn't match the the class table name " << table.getTableName() << __E__;
294 __COUT_ERR__ <<
"\n" << ss.str();
295 throw(std::runtime_error(ss.str()));
298 xercesc::DOMNodeList* viewNodeList = tableElement->getElementsByTagName(viewTag_);
299 bool storageTypeFound =
false;
301 if(viewNodeList->getLength() != 1)
303 __SS__ <<
"In " << tableFile <<
" the table name " << XML_TO_CHAR(tableElement->getAttribute(tableNameAttributeTag_))
304 <<
" there must only be one view. There were " << viewNodeList->getLength() <<
" found." << __E__;
308 __COUT_ERR__ <<
"\n" << ss.str();
309 throw(std::runtime_error(ss.str()));
312 for(XMLSize_t view = 0; view < viewNodeList->getLength(); view++)
314 if(!viewNodeList->item(view)->getNodeType() ||
315 viewNodeList->item(view)->getNodeType() != xercesc::DOMNode::ELEMENT_NODE)
317 xercesc::DOMElement* viewElement =
dynamic_cast<xercesc::DOMElement*
>(viewNodeList->item(view));
318 std::string viewType = XML_TO_CHAR(viewElement->getAttribute(viewTypeAttributeTag_));
319 if(!checkViewType(viewType))
321 storageTypeFound =
true;
326 if(std::string(XML_TO_CHAR(viewElement->getAttribute(viewNameAttributeTag_))) !=
327 table.getMockupViewP()->getTableName())
328 __COUT_WARN__ <<
"Table Info name mismatch: " <<
329 std::string(XML_TO_CHAR(viewElement->getAttribute(viewNameAttributeTag_))) <<
" vs " <<
330 table.getMockupViewP()->getTableName() << __E__;
333 xercesc::DOMNodeList* columnNodeList = viewElement->getElementsByTagName(columnTag_);
334 for(XMLSize_t column = 0; column < columnNodeList->getLength(); column++)
337 xercesc::DOMElement* columnElement =
dynamic_cast<xercesc::DOMElement*
>(columnNodeList->item(column));
343 std::string capturedException;
344 table.getMockupViewP()->getColumnsInfoP()->push_back(
346 XML_TO_CHAR(columnElement->getAttribute(columnNameAttributeTag_)),
347 XML_TO_CHAR(columnElement->getAttribute(columnStorageNameAttributeTag_)),
348 XML_TO_CHAR(columnElement->getAttribute(columnDataTypeAttributeTag_)),
349 XML_TO_CHAR(columnElement->getAttribute(columnDataChoicesAttributeTag_)),
350 allowIllegalColumns_ ? &capturedException : 0));
354 if(capturedException !=
"")
355 accumulatedExceptions += std::string(
"\n\nColumn Error:") + capturedException;
362 std::string tableDescription = XML_TO_CHAR(viewElement->getAttribute(viewDescriptionAttributeTag_));
364 table.setTableDescription(StringMacros::decodeURIComponent(tableDescription));
369 if(!storageTypeFound)
371 __COUT__ <<
"The type defined in CONFIGURATION_BACKEND_TYPE (" << CONFIGURATION_BACKEND_TYPE_ <<
") doesn't match with any of the types defined in "
372 << tableFile << __E__;
376 throw(std::runtime_error(
"Table Type mismatch!"));
381 catch(xercesc::XMLException& e)
383 std::ostringstream errBuf;
384 errBuf <<
"Error parsing file: " << XML_TO_CHAR(e.getMessage()) << std::flush;
394 return accumulatedExceptions;
400 std::string TableInfoReader::read(
TableBase* table) {
return read(*table); }