1 #include "otsdaq-core/ConfigurationDataFormats/ConfigurationInfoReader.h"
2 #include "otsdaq-core/ConfigurationDataFormats/ConfigurationBase.h"
3 #include "otsdaq-core/XmlUtilities/DOMTreeErrorReporter.h"
4 #include "otsdaq-core/XmlUtilities/ConvertFromXML.h"
5 #include "otsdaq-core/Macros/StringMacros.h"
10 #include <xercesc/parsers/XercesDOMParser.hpp>
11 #include <xercesc/dom/DOMElement.hpp>
12 #include <xercesc/dom/DOMImplementation.hpp>
13 #include <xercesc/dom/DOMImplementationRegistry.hpp>
14 #include <xercesc/dom/DOMNodeList.hpp>
15 #include <xercesc/dom/DOMText.hpp>
18 #include <xercesc/util/OutOfMemoryException.hpp>
19 #include <xercesc/framework/LocalFileFormatTarget.hpp>
31 #define __COUT_HDR__ "ConfigInfoReader"
35 ConfigurationInfoReader::ConfigurationInfoReader(
bool allowIllegalColumns)
36 : allowIllegalColumns_(allowIllegalColumns)
39 rootTag_ = xercesc::XMLString::transcode(
"ROOT");
40 configurationTag_ = xercesc::XMLString::transcode(
"CONFIGURATION");
41 configurationNameAttributeTag_ = xercesc::XMLString::transcode(
"Name");
42 viewTag_ = xercesc::XMLString::transcode(
"VIEW");
43 viewNameAttributeTag_ = xercesc::XMLString::transcode(
"Name");
44 viewTypeAttributeTag_ = xercesc::XMLString::transcode(
"Type");
45 viewDescriptionAttributeTag_ = xercesc::XMLString::transcode(
"Description");
46 columnTag_ = xercesc::XMLString::transcode(
"COLUMN");
47 columnTypeAttributeTag_ = xercesc::XMLString::transcode(
"Type");
48 columnNameAttributeTag_ = xercesc::XMLString::transcode(
"Name");
49 columnStorageNameAttributeTag_ = xercesc::XMLString::transcode(
"StorageName");
50 columnDataTypeAttributeTag_ = xercesc::XMLString::transcode(
"DataType");
51 columnDataChoicesAttributeTag_ = xercesc::XMLString::transcode(
"DataChoices");
55 ConfigurationInfoReader::~ConfigurationInfoReader(
void)
59 xercesc::XMLString::release( &rootTag_ );
60 xercesc::XMLString::release( &configurationTag_ );
61 xercesc::XMLString::release( &configurationNameAttributeTag_ );
62 xercesc::XMLString::release( &viewTag_ );
63 xercesc::XMLString::release( &viewNameAttributeTag_ );
64 xercesc::XMLString::release( &viewTypeAttributeTag_ );
65 xercesc::XMLString::release( &viewDescriptionAttributeTag_ );
66 xercesc::XMLString::release( &columnTag_ );
67 xercesc::XMLString::release( &columnTypeAttributeTag_ );
68 xercesc::XMLString::release( &columnNameAttributeTag_ );
69 xercesc::XMLString::release( &columnStorageNameAttributeTag_ );
70 xercesc::XMLString::release( &columnDataTypeAttributeTag_ );
71 xercesc::XMLString::release( &columnDataChoicesAttributeTag_ );
76 mf::LogError(__FILE__) <<
"Unknown exception encountered in TagNames destructor" << std::endl;
82 void ConfigurationInfoReader::initPlatform(
void)
86 xercesc::XMLPlatformUtils::Initialize();
88 catch( xercesc::XMLException& e )
90 mf::LogError(__FILE__) <<
"XML toolkit initialization error: " << XML_TO_CHAR(e.getMessage()) << std::endl;
96 void ConfigurationInfoReader::terminatePlatform(
void)
100 xercesc::XMLPlatformUtils::Terminate();
102 catch( xercesc::XMLException& e )
104 mf::LogError(__FILE__) <<
"XML tolkit teardown error: " << XML_TO_CHAR(e.getMessage()) << std::endl;
110 void ConfigurationInfoReader::setAllowColumnErrors(
bool setValue)
112 allowIllegalColumns_ = setValue;
115 const bool& ConfigurationInfoReader::getAllowColumnErrors(
void)
117 return allowIllegalColumns_;
121 bool ConfigurationInfoReader::checkViewType(std::string type)
123 std::vector<std::string> types;
124 int currentIndex = 0;
125 while( type.find(
',',currentIndex) != std::string::npos )
127 types.push_back(type.substr(currentIndex,type.find(
',',currentIndex)-currentIndex));
128 currentIndex = type.find(
',',currentIndex)+1;
130 types.push_back(type.substr(currentIndex,type.size()));
132 std::string systemType = getenv(
"CONFIGURATION_TYPE");
133 for(
unsigned int i=0; i<types.size(); i++)
135 if( types[i] == systemType )
139 const unsigned int allowedNamesSize = 3;
140 const std::string allowedNames[allowedNamesSize] =
141 {
"File",
"Database",
"DatabaseTest"
143 if(systemType != allowedNames[0] && systemType != allowedNames[1] && systemType != allowedNames[2] )
145 __COUT__ <<
"The type defined in CONFIGURATION_TYPE ("
146 << systemType <<
") doesn't match with any of the allowed types: File,Database or DatabaseTest"
149 throw(std::runtime_error(
"Illegal configuration type" ));
151 for(
unsigned int i=0; i<types.size(); i++)
153 if(types[i] != allowedNames[0] && types[i] != allowedNames[1] && types[i] != allowedNames[2] )
155 __COUT__ <<
"The type defined in the info file ("
156 << types[i] <<
") doesn't match with any of the allowed types: "
157 << allowedNames[0] <<
", " << allowedNames[1] <<
" or " << allowedNames[2]
159 throw(std::runtime_error(
"Illegal Type!" ));
167 xercesc::DOMNode* ConfigurationInfoReader::getNode(XMLCh* tagName, xercesc::DOMNode* parent,
unsigned int itemNumber)
169 return getNode(tagName, dynamic_cast< xercesc::DOMElement* >(parent), itemNumber);
173 xercesc::DOMNode* ConfigurationInfoReader::getNode(XMLCh* tagName, xercesc::DOMElement* parent,
unsigned int itemNumber)
175 xercesc::DOMNodeList* nodeList = parent->getElementsByTagName(tagName);
178 throw(std::runtime_error( std::string(
"Can't find ") + XML_TO_CHAR(tagName) +
" tag!"));
179 __COUT__ << (std::string(
"Can't find ") + XML_TO_CHAR(tagName) +
" tag!") << std::endl;
184 return nodeList->item(itemNumber);
188 xercesc::DOMElement* ConfigurationInfoReader::getElement(XMLCh* tagName, xercesc::DOMNode* parent,
unsigned int itemNumber)
190 return dynamic_cast< xercesc::DOMElement*
>(getNode(tagName,parent,itemNumber));
194 xercesc::DOMElement* ConfigurationInfoReader::getElement(XMLCh* tagName, xercesc::DOMElement* parent,
unsigned int itemNumber)
196 return dynamic_cast< xercesc::DOMElement*
>(getNode(tagName,parent,itemNumber));
202 std::string accumulatedExceptions =
"";
213 if(getenv(
"CONFIGURATION_TYPE" ) == NULL) __COUT__ <<
"Missing env variable: CONFIGURATION_TYPE. It must be set!" << std::endl;
214 if(getenv(
"CONFIGURATION_DATA_PATH") == NULL) __COUT__ <<
"Missing env variable: CONFIGURATION_DATA_PATH. It must be set!" << std::endl;
215 if(getenv(
"CONFIGURATION_INFO_PATH") == NULL) __COUT__ <<
"Missing env variable: CONFIGURATION_INFO_PATH. It must be set!" << std::endl;
224 std::string configurationDataDir = std::string(getenv(
"CONFIGURATION_INFO_PATH")) +
"/";
225 std::string configFile = configurationDataDir + configuration.getConfigurationName() +
"Info.xml";
227 struct stat fileStatus;
229 int iretStat = stat(configFile.c_str(), &fileStatus);
230 if( iretStat == ENOENT )
232 __SS__ << (
"Path file_name does not exist, or path is an empty std::string.") << std::endl;
233 __COUT_ERR__ << ss.str();
234 throw std::runtime_error(ss.str());
236 else if( iretStat == ENOTDIR )
238 __SS__ << (
"A component of the path is not a directory.") << std::endl;
239 __COUT_ERR__ << ss.str();
240 throw std::runtime_error(ss.str());
242 else if( iretStat == ELOOP )
244 __SS__ << (
"Too many symbolic links encountered while traversing the path.") << std::endl;
245 __COUT_ERR__ << ss.str();
246 throw std::runtime_error(ss.str());
248 else if( iretStat == EACCES )
250 __SS__ << (
"Permission denied.") << std::endl;
251 __COUT_ERR__ << ss.str();
252 throw std::runtime_error(ss.str());
254 else if( iretStat == ENAMETOOLONG )
256 __SS__ << (
"File can not be read. Name too long.") << std::endl;
257 __COUT_ERR__ << ss.str();
258 throw std::runtime_error(ss.str());
261 xercesc::XercesDOMParser* parser =
new xercesc::XercesDOMParser;
263 parser->setValidationScheme(xercesc::XercesDOMParser::Val_Auto);
264 parser->setDoNamespaces (
true );
265 parser->setDoSchema (
true );
266 parser->useCachedGrammarInParse (
false );
269 parser->setErrorHandler(errorHandler);
272 parser->parse( configFile.c_str() );
275 xercesc::DOMDocument* xmlDocument = parser->getDocument();
278 xercesc::DOMElement* elementRoot = xmlDocument->getDocumentElement();
283 throw(std::runtime_error(
"empty XML document" ));
287 xercesc::DOMElement* configurationElement = getElement(configurationTag_, elementRoot, 0);
288 if( configuration.getConfigurationName() != XML_TO_CHAR(configurationElement->getAttribute(configurationNameAttributeTag_)) )
291 __SS__ <<
"In " << configFile <<
" the configuration name " << XML_TO_CHAR(configurationElement->getAttribute(configurationNameAttributeTag_))
292 <<
" doesn't match the the class configuration name " << configuration.getConfigurationName() << std::endl;
296 __COUT_ERR__ <<
"\n" << ss.str();
297 throw(std::runtime_error( ss.str()));
300 xercesc::DOMNodeList* viewNodeList = configurationElement->getElementsByTagName(viewTag_);
301 bool storageTypeFound =
false;
303 if(viewNodeList->getLength() != 1)
306 __SS__ <<
"In " << configFile <<
" the configuration name " << XML_TO_CHAR(configurationElement->getAttribute(configurationNameAttributeTag_))
307 <<
" there must only be one view. There were " <<
308 viewNodeList->getLength() <<
" found." << std::endl;
312 __COUT_ERR__ <<
"\n" << ss.str();
313 throw(std::runtime_error( ss.str()));
316 for( XMLSize_t view = 0; view < viewNodeList->getLength(); view++ )
318 if( !viewNodeList->item(view)->getNodeType() || viewNodeList->item(view)->getNodeType() != xercesc::DOMNode::ELEMENT_NODE )
320 xercesc::DOMElement* viewElement =
dynamic_cast< xercesc::DOMElement*
>( viewNodeList->item(view) );
321 std::string viewType = XML_TO_CHAR(viewElement->getAttribute(viewTypeAttributeTag_));
322 if(!checkViewType(viewType))
324 storageTypeFound =
true;
325 configuration.getMockupViewP()->setTableName(XML_TO_CHAR(viewElement->getAttribute(viewNameAttributeTag_)));
326 xercesc::DOMNodeList* columnNodeList = viewElement->getElementsByTagName(columnTag_);
327 for( XMLSize_t column = 0; column < columnNodeList->getLength(); column++ )
330 xercesc::DOMElement* columnElement =
dynamic_cast< xercesc::DOMElement*
>( columnNodeList->item(column) );
334 std::string capturedException;
335 configuration.getMockupViewP()->getColumnsInfoP()->push_back(
337 XML_TO_CHAR(columnElement->getAttribute(columnTypeAttributeTag_)),
338 XML_TO_CHAR(columnElement->getAttribute(columnNameAttributeTag_)),
339 XML_TO_CHAR(columnElement->getAttribute(columnStorageNameAttributeTag_)),
340 XML_TO_CHAR(columnElement->getAttribute(columnDataTypeAttributeTag_)),
341 XML_TO_CHAR(columnElement->getAttribute(columnDataChoicesAttributeTag_)),
342 allowIllegalColumns_?&capturedException:0));
346 if(capturedException !=
"")
347 accumulatedExceptions += std::string(
"\n\nColumn Error:") + capturedException;
354 std::string configurationDescription = XML_TO_CHAR(viewElement->getAttribute(
355 viewDescriptionAttributeTag_));
357 configuration.setConfigurationDescription(
358 StringMacros::decodeURIComponent(configurationDescription));
363 if( !storageTypeFound )
365 __COUT__ <<
"The type defined in CONFIGURATION_TYPE ("
366 << getenv(
"CONFIGURATION_TYPE") <<
") doesn't match with any of the types defined in " << configFile << std::endl;
370 throw(std::runtime_error(
"Configuration Type mismatch!" ));
375 catch( xercesc::XMLException& e )
377 std::ostringstream errBuf;
378 errBuf <<
"Error parsing file: " << XML_TO_CHAR(e.getMessage()) << std::flush;
388 return accumulatedExceptions;
396 return read(*configuration);